summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/.indent.pro2
-rw-r--r--src/CMakeLists.txt413
-rw-r--r--src/H5.c13
-rw-r--r--src/H5A.c457
-rw-r--r--src/H5AC.c813
-rw-r--r--src/H5ACdbg.c115
-rw-r--r--src/H5AClog.c1105
-rw-r--r--src/H5ACmpio.c6
-rw-r--r--src/H5ACpkg.h69
-rw-r--r--src/H5ACprivate.h7
-rw-r--r--src/H5Abtree2.c9
-rw-r--r--src/H5Adense.c65
-rw-r--r--src/H5Adeprec.c168
-rw-r--r--src/H5Aint.c633
-rw-r--r--src/H5Apkg.h9
-rw-r--r--src/H5Apublic.h18
-rw-r--r--src/H5Atest.c5
-rw-r--r--src/H5B.c59
-rw-r--r--src/H5B2.c8
-rw-r--r--src/H5B2cache.c6
-rw-r--r--src/H5B2int.c84
-rw-r--r--src/H5B2leaf.c14
-rw-r--r--src/H5B2private.h3
-rw-r--r--src/H5Bcache.c3
-rw-r--r--src/H5Bdbg.c6
-rw-r--r--src/H5Bprivate.h1
-rw-r--r--src/H5Bpublic.h39
-rw-r--r--src/H5C.c80
-rw-r--r--src/H5CX.c888
-rw-r--r--src/H5CXprivate.h37
-rw-r--r--src/H5Cdbg.c57
-rw-r--r--src/H5Cimage.c16
-rw-r--r--src/H5Clog.c946
-rw-r--r--src/H5Clog.h114
-rw-r--r--src/H5Clog_json.c1364
-rw-r--r--src/H5Clog_trace.c1007
-rw-r--r--src/H5Cmpio.c16
-rw-r--r--src/H5Cpkg.h50
-rw-r--r--src/H5Cprivate.h30
-rw-r--r--src/H5Cquery.c94
-rw-r--r--src/H5Ctag.c26
-rw-r--r--src/H5Ctest.c3
-rw-r--r--src/H5D.c474
-rw-r--r--src/H5Dbtree.c5
-rw-r--r--src/H5Dbtree2.c11
-rw-r--r--src/H5Dchunk.c1250
-rw-r--r--src/H5Dcompact.c22
-rw-r--r--src/H5Dcontig.c137
-rw-r--r--src/H5Ddbg.c3
-rw-r--r--src/H5Ddeprec.c162
-rw-r--r--src/H5Dearray.c11
-rw-r--r--src/H5Defl.c5
-rw-r--r--src/H5Dfarray.c4
-rw-r--r--src/H5Dfill.c11
-rw-r--r--src/H5Dint.c494
-rw-r--r--src/H5Dio.c169
-rw-r--r--src/H5Dlayout.c50
-rw-r--r--src/H5Dmpio.c235
-rw-r--r--src/H5Dnone.c57
-rw-r--r--src/H5Doh.c31
-rw-r--r--src/H5Dpkg.h28
-rw-r--r--src/H5Dprivate.h17
-rw-r--r--src/H5Dpublic.h28
-rw-r--r--src/H5Dscatgath.c88
-rw-r--r--src/H5Dselect.c10
-rw-r--r--src/H5Dtest.c13
-rw-r--r--src/H5Dvirtual.c88
-rw-r--r--src/H5E.c16
-rw-r--r--src/H5EA.c19
-rw-r--r--src/H5EAcache.c13
-rw-r--r--src/H5EAdbg.c6
-rw-r--r--src/H5EAhdr.c9
-rw-r--r--src/H5EAstat.c3
-rw-r--r--src/H5EAtest.c2
-rw-r--r--src/H5ESpublic.h (renamed from src/H5HFpublic.h)41
-rw-r--r--src/H5Eint.c50
-rw-r--r--src/H5F.c944
-rw-r--r--src/H5FA.c23
-rw-r--r--src/H5FAcache.c9
-rw-r--r--src/H5FAhdr.c3
-rw-r--r--src/H5FAstat.c3
-rw-r--r--src/H5FAtest.c2
-rw-r--r--src/H5FD.c4
-rw-r--r--src/H5FDcore.c188
-rw-r--r--src/H5FDdirect.c34
-rw-r--r--src/H5FDfamily.c43
-rw-r--r--src/H5FDhdfs.c2167
-rw-r--r--src/H5FDhdfs.h122
-rw-r--r--src/H5FDlog.c68
-rw-r--r--src/H5FDmpi.c109
-rw-r--r--src/H5FDmpio.c1580
-rw-r--r--src/H5FDmulti.c115
-rw-r--r--src/H5FDprivate.h44
-rw-r--r--src/H5FDros3.c1833
-rw-r--r--src/H5FDros3.h105
-rw-r--r--src/H5FDs3comms.c3593
-rw-r--r--src/H5FDs3comms.h604
-rw-r--r--src/H5FDsec2.c54
-rw-r--r--src/H5FDtest.c5
-rw-r--r--src/H5FDvfd_swmr.c151
-rw-r--r--src/H5FDvfd_swmr_private.h12
-rw-r--r--src/H5FL.c20
-rw-r--r--src/H5FLprivate.h4
-rw-r--r--src/H5FS.c3
-rw-r--r--src/H5FScache.c65
-rw-r--r--src/H5FSprivate.h3
-rw-r--r--src/H5FSsection.c339
-rw-r--r--src/H5Faccum.c94
-rw-r--r--src/H5Fcwfs.c2
-rw-r--r--src/H5Fdeprec.c93
-rw-r--r--src/H5Fefc.c40
-rw-r--r--src/H5Ffake.c4
-rw-r--r--src/H5Fint.c693
-rw-r--r--src/H5Fio.c97
-rw-r--r--src/H5Fmount.c23
-rw-r--r--src/H5Fmpi.c247
-rw-r--r--src/H5Fpkg.h129
-rw-r--r--src/H5Fprivate.h91
-rw-r--r--src/H5Fpublic.h101
-rw-r--r--src/H5Fquery.c183
-rw-r--r--src/H5Fsfile.c12
-rw-r--r--src/H5Fsuper.c221
-rw-r--r--src/H5Fsuper_cache.c17
-rw-r--r--src/H5Ftest.c49
-rw-r--r--src/H5Fvfd_swmr.c338
-rw-r--r--src/H5G.c209
-rw-r--r--src/H5Gbtree2.c13
-rw-r--r--src/H5Gcache.c3
-rw-r--r--src/H5Gcompact.c68
-rw-r--r--src/H5Gdense.c77
-rw-r--r--src/H5Gdeprec.c695
-rw-r--r--src/H5Gent.c3
-rw-r--r--src/H5Gint.c6
-rw-r--r--src/H5Glink.c19
-rw-r--r--src/H5Gloc.c73
-rw-r--r--src/H5Gname.c32
-rw-r--r--src/H5Gnode.c4
-rw-r--r--src/H5Goh.c29
-rw-r--r--src/H5Gpkg.h15
-rw-r--r--src/H5Gprivate.h5
-rw-r--r--src/H5Gpublic.h9
-rw-r--r--src/H5Gstab.c115
-rw-r--r--src/H5Gtest.c24
-rw-r--r--src/H5Gtraverse.c6
-rw-r--r--src/H5HF.c6
-rw-r--r--src/H5HFcache.c20
-rw-r--r--src/H5HFdbg.c2
-rw-r--r--src/H5HFhdr.c3
-rw-r--r--src/H5HFhuge.c4
-rw-r--r--src/H5HFman.c2
-rw-r--r--src/H5HFprivate.h3
-rw-r--r--src/H5HFsection.c8
-rw-r--r--src/H5HFtest.c4
-rw-r--r--src/H5HFtiny.c3
-rw-r--r--src/H5HG.c15
-rw-r--r--src/H5HGcache.c4
-rw-r--r--src/H5HGpkg.h4
-rw-r--r--src/H5HGprivate.h7
-rw-r--r--src/H5HL.c2
-rw-r--r--src/H5HLcache.c11
-rw-r--r--src/H5HLprivate.h3
-rw-r--r--src/H5I.c549
-rw-r--r--src/H5Iprivate.h32
-rw-r--r--src/H5Ipublic.h11
-rw-r--r--src/H5Itest.c23
-rw-r--r--src/H5L.c428
-rw-r--r--src/H5Lexternal.c41
-rw-r--r--src/H5M.c1032
-rw-r--r--src/H5MF.c933
-rw-r--r--src/H5MFaggr.c16
-rw-r--r--src/H5MFdbg.c8
-rw-r--r--src/H5MFpkg.h17
-rw-r--r--src/H5MFprivate.h2
-rw-r--r--src/H5MFsection.c19
-rw-r--r--src/H5MM.c56
-rw-r--r--src/H5MMprivate.h1
-rw-r--r--src/H5MP.c6
-rw-r--r--src/H5MPtest.c2
-rw-r--r--src/H5MV.c6
-rw-r--r--src/H5Mmodule.h (renamed from src/H5HLpublic.h)36
-rw-r--r--src/H5Mpkg.h (renamed from src/H5FSpublic.h)57
-rw-r--r--src/H5Mprivate.h80
-rw-r--r--src/H5Mpublic.h126
-rw-r--r--src/H5O.c555
-rw-r--r--src/H5Oalloc.c11
-rw-r--r--src/H5Oattr.c27
-rw-r--r--src/H5Oattribute.c6
-rw-r--r--src/H5Obogus.c4
-rw-r--r--src/H5Ocache.c29
-rw-r--r--src/H5Ocache_image.c33
-rw-r--r--src/H5Ochunk.c2
-rw-r--r--src/H5Ocopy.c231
-rw-r--r--src/H5Ocopy_ref.c498
-rw-r--r--src/H5Odeprec.c92
-rw-r--r--src/H5Odrvinfo.c10
-rw-r--r--src/H5Odtype.c76
-rw-r--r--src/H5Oefl.c4
-rw-r--r--src/H5Ofill.c258
-rw-r--r--src/H5Oflush.c85
-rw-r--r--src/H5Ofsinfo.c182
-rw-r--r--src/H5Oint.c1047
-rw-r--r--src/H5Olayout.c26
-rw-r--r--src/H5Olink.c31
-rw-r--r--src/H5Omessage.c25
-rw-r--r--src/H5Omtime.c2
-rw-r--r--src/H5Oname.c2
-rw-r--r--src/H5Opkg.h9
-rw-r--r--src/H5Opline.c346
-rw-r--r--src/H5Oprivate.h56
-rw-r--r--src/H5Opublic.h8
-rw-r--r--src/H5Osdspace.c12
-rw-r--r--src/H5Oshared.c5
-rw-r--r--src/H5P.c19
-rw-r--r--src/H5PB.c434
-rw-r--r--src/H5PBprivate.h38
-rw-r--r--src/H5PLint.c57
-rw-r--r--src/H5PLpath.c8
-rw-r--r--src/H5PLpkg.h10
-rw-r--r--src/H5PLplugin_cache.c6
-rw-r--r--src/H5PLprivate.h14
-rw-r--r--src/H5PLpublic.h4
-rw-r--r--src/H5Pacpl.c2
-rw-r--r--src/H5Pdapl.c6
-rw-r--r--src/H5Pdcpl.c134
-rw-r--r--src/H5Pdeprec.c49
-rw-r--r--src/H5Pdxpl.c9
-rw-r--r--src/H5Pencdec.c2
-rw-r--r--src/H5Pfapl.c1163
-rw-r--r--src/H5Pint.c332
-rw-r--r--src/H5Plapl.c2
-rw-r--r--src/H5Plcpl.c1
-rw-r--r--src/H5Pmapl.c217
-rw-r--r--src/H5Pmcpl.c115
-rw-r--r--src/H5Pocpl.c2
-rw-r--r--src/H5Pocpypl.c2
-rw-r--r--src/H5Ppkg.h4
-rw-r--r--src/H5Pprivate.h13
-rw-r--r--src/H5Ppublic.h35
-rw-r--r--src/H5R.c972
-rw-r--r--src/H5RS.c4
-rw-r--r--src/H5RSprivate.h2
-rw-r--r--src/H5Rdeprec.c487
-rw-r--r--src/H5Rint.c1914
-rw-r--r--src/H5Rpkg.h80
-rw-r--r--src/H5Rprivate.h3
-rw-r--r--src/H5Rpublic.h106
-rw-r--r--src/H5S.c1043
-rw-r--r--src/H5SL.c4
-rw-r--r--src/H5SM.c5
-rw-r--r--src/H5SMbtree2.c3
-rw-r--r--src/H5SMcache.c4
-rw-r--r--src/H5SMmessage.c5
-rw-r--r--src/H5ST.c16
-rw-r--r--src/H5Sall.c416
-rw-r--r--src/H5Sdbg.c18
-rw-r--r--src/H5Sdeprec.c121
-rw-r--r--src/H5Shyper.c11055
-rw-r--r--src/H5Smpio.c1324
-rw-r--r--src/H5Snone.c616
-rw-r--r--src/H5Spkg.h207
-rw-r--r--src/H5Spoint.c1729
-rw-r--r--src/H5Sprivate.h73
-rw-r--r--src/H5Spublic.h119
-rw-r--r--src/H5Sselect.c1174
-rw-r--r--src/H5Stest.c323
-rw-r--r--src/H5T.c590
-rw-r--r--src/H5Tcommit.c319
-rw-r--r--src/H5Tconv.c419
-rw-r--r--src/H5Tdbg.c2
-rw-r--r--src/H5Tdeprec.c61
-rw-r--r--src/H5Tenum.c24
-rw-r--r--src/H5Tfields.c20
-rw-r--r--src/H5Tnative.c54
-rw-r--r--src/H5Toh.c30
-rw-r--r--src/H5Torder.c6
-rw-r--r--src/H5Tpkg.h129
-rw-r--r--src/H5Tprecis.c2
-rw-r--r--src/H5Tprivate.h20
-rw-r--r--src/H5Tpublic.h5
-rw-r--r--src/H5Tref.c768
-rw-r--r--src/H5Tvlen.c916
-rw-r--r--src/H5VL.c660
-rw-r--r--src/H5VLcallback.c7024
-rw-r--r--src/H5VLconnector.h449
-rw-r--r--src/H5VLconnector_passthru.h175
-rw-r--r--src/H5VLint.c2029
-rw-r--r--src/H5VLmodule.h (renamed from src/H5HGpublic.h)28
-rw-r--r--src/H5VLnative.c182
-rw-r--r--src/H5VLnative.h108
-rw-r--r--src/H5VLnative_attr.c585
-rw-r--r--src/H5VLnative_blob.c237
-rw-r--r--src/H5VLnative_dataset.c643
-rw-r--r--src/H5VLnative_datatype.c265
-rw-r--r--src/H5VLnative_file.c881
-rw-r--r--src/H5VLnative_group.c353
-rw-r--r--src/H5VLnative_link.c419
-rw-r--r--src/H5VLnative_object.c511
-rw-r--r--src/H5VLnative_private.h114
-rw-r--r--src/H5VLpassthru.c2928
-rw-r--r--src/H5VLpassthru.h (renamed from src/H5B2public.h)43
-rw-r--r--src/H5VLpkg.h63
-rw-r--r--src/H5VLprivate.h205
-rw-r--r--src/H5VLpublic.h77
-rw-r--r--src/H5VM.c25
-rw-r--r--src/H5VMprivate.h3
-rw-r--r--src/H5Z.c16
-rw-r--r--src/H5Zfletcher32.c6
-rw-r--r--src/H5Zpublic.h2
-rw-r--r--src/H5Zscaleoffset.c65
-rw-r--r--src/H5Zshuffle.c18
-rw-r--r--src/H5Ztrans.c8
-rw-r--r--src/H5checksum.c11
-rw-r--r--src/H5dbg.c2
-rw-r--r--src/H5detect.c21
-rw-r--r--src/H5err.txt12
-rw-r--r--src/H5make_libsettings.c13
-rw-r--r--src/H5mpi.c563
-rw-r--r--src/H5private.h140
-rw-r--r--src/H5public.h9
-rw-r--r--src/H5system.c210
-rw-r--r--src/H5timer.c16
-rw-r--r--src/H5trace.c813
-rw-r--r--src/H5vers.txt2
-rw-r--r--src/H5win32defs.h24
-rw-r--r--src/Makefile.am50
-rw-r--r--src/bsdqueue.h847
-rw-r--r--src/hdf5.h26
-rw-r--r--src/libhdf5.settings.in6
328 files changed, 64326 insertions, 20189 deletions
diff --git a/src/.indent.pro b/src/.indent.pro
index e0fda85..fa375f0 100644
--- a/src/.indent.pro
+++ b/src/.indent.pro
@@ -68,7 +68,7 @@
-T H5E_minor_t
-T H5E_t
-T H5F_create_t
--T H5F_file_t
+-T H5F_shared_t
-T H5F_isop_t
-T H5F_istore_key_t
-T H5F_istore_ud1_t
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index d16adf8..9bb73a9 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -8,6 +8,7 @@ set (H5_SOURCES
${HDF5_SRC_DIR}/H5.c
${HDF5_SRC_DIR}/H5checksum.c
${HDF5_SRC_DIR}/H5dbg.c
+ ${HDF5_SRC_DIR}/H5mpi.c
${HDF5_SRC_DIR}/H5system.c
${HDF5_SRC_DIR}/H5timer.c
${HDF5_SRC_DIR}/H5trace.c
@@ -32,7 +33,6 @@ set (H5A_SOURCES
)
set (H5A_HDRS
- ${HDF5_SRC_DIR}/H5Apkg.h
${HDF5_SRC_DIR}/H5Apublic.h
)
IDE_GENERATED_PROPERTIES ("H5A" "${H5A_HDRS}" "${H5A_SOURCES}" )
@@ -40,13 +40,11 @@ IDE_GENERATED_PROPERTIES ("H5A" "${H5A_HDRS}" "${H5A_SOURCES}" )
set (H5AC_SOURCES
${HDF5_SRC_DIR}/H5AC.c
${HDF5_SRC_DIR}/H5ACdbg.c
- ${HDF5_SRC_DIR}/H5AClog.c
${HDF5_SRC_DIR}/H5ACmpio.c
${HDF5_SRC_DIR}/H5ACproxy_entry.c
)
set (H5AC_HDRS
- ${HDF5_SRC_DIR}/H5ACpkg.h
${HDF5_SRC_DIR}/H5ACpublic.h
)
IDE_GENERATED_PROPERTIES ("H5AC" "${H5AC_HDRS}" "${H5AC_SOURCES}" )
@@ -57,8 +55,6 @@ set (H5B_SOURCES
${HDF5_SRC_DIR}/H5Bdbg.c
)
set (H5B_HDRS
- ${HDF5_SRC_DIR}/H5Bpkg.h
- ${HDF5_SRC_DIR}/H5Bpublic.h
)
IDE_GENERATED_PROPERTIES ("H5B" "${H5B_HDRS}" "${H5B_SOURCES}" )
@@ -75,8 +71,6 @@ set (H5B2_SOURCES
${HDF5_SRC_DIR}/H5B2test.c
)
set (H5B2_HDRS
- ${HDF5_SRC_DIR}/H5B2pkg.h
- ${HDF5_SRC_DIR}/H5B2public.h
)
IDE_GENERATED_PROPERTIES ("H5B2" "${H5B2_HDRS}" "${H5B2_SOURCES}" )
@@ -87,6 +81,8 @@ set (H5C_SOURCES
${HDF5_SRC_DIR}/H5Cepoch.c
${HDF5_SRC_DIR}/H5Cimage.c
${HDF5_SRC_DIR}/H5Clog.c
+ ${HDF5_SRC_DIR}/H5Clog_json.c
+ ${HDF5_SRC_DIR}/H5Clog_trace.c
${HDF5_SRC_DIR}/H5Cmpio.c
${HDF5_SRC_DIR}/H5Cprefetched.c
${HDF5_SRC_DIR}/H5Cquery.c
@@ -94,7 +90,6 @@ set (H5C_SOURCES
${HDF5_SRC_DIR}/H5Ctest.c
)
set (H5C_HDRS
- ${HDF5_SRC_DIR}/H5Cpkg.h
${HDF5_SRC_DIR}/H5Cpublic.h
)
IDE_GENERATED_PROPERTIES ("H5C" "${H5C_HDRS}" "${H5C_SOURCES}" )
@@ -143,7 +138,6 @@ set (H5D_SOURCES
)
set (H5D_HDRS
- ${HDF5_SRC_DIR}/H5Dpkg.h
${HDF5_SRC_DIR}/H5Dpublic.h
)
IDE_GENERATED_PROPERTIES ("H5D" "${H5D_HDRS}" "${H5D_SOURCES}" )
@@ -155,12 +149,8 @@ set (H5E_SOURCES
)
set (H5E_HDRS
- #${HDF5_SRC_DIR}/H5Edefin.h
- #${HDF5_SRC_DIR}/H5Einit.h
- ${HDF5_SRC_DIR}/H5Epkg.h
- #${HDF5_SRC_DIR}/H5Epubgen.h
+ ${HDF5_SRC_DIR}/H5Epubgen.h
${HDF5_SRC_DIR}/H5Epublic.h
- #${HDF5_SRC_DIR}/H5Eterm.h
)
IDE_GENERATED_PROPERTIES ("H5E" "${H5E_HDRS}" "${H5E_SOURCES}" )
@@ -179,11 +169,18 @@ set (H5EA_SOURCES
${HDF5_SRC_DIR}/H5EAtest.c
)
set (H5EA_HDRS
- ${HDF5_SRC_DIR}/H5EApkg.h
)
IDE_GENERATED_PROPERTIES ("H5EA" "${H5EA_HDRS}" "${H5EA_SOURCES}" )
+set (H5ES_SOURCES
+)
+set (H5ES_HDRS
+ ${HDF5_SRC_DIR}/H5ESpublic.h
+)
+IDE_GENERATED_PROPERTIES ("H5ES" "${H5ES_HDRS}" "${H5ES_SOURCES}" )
+
+
set (H5F_SOURCES
${HDF5_SRC_DIR}/H5F.c
${HDF5_SRC_DIR}/H5Faccum.c
@@ -205,7 +202,6 @@ set (H5F_SOURCES
)
set (H5F_HDRS
- ${HDF5_SRC_DIR}/H5Fpkg.h
${HDF5_SRC_DIR}/H5Fpublic.h
)
IDE_GENERATED_PROPERTIES ("H5F" "${H5F_HDRS}" "${H5F_SOURCES}" )
@@ -223,7 +219,6 @@ set (H5FA_SOURCES
${HDF5_SRC_DIR}/H5FAtest.c
)
set (H5FA_HDRS
- ${HDF5_SRC_DIR}/H5FApkg.h
)
IDE_GENERATED_PROPERTIES ("H5FA" "${H5FA_HDRS}" "${H5FA_SOURCES}" )
@@ -233,11 +228,14 @@ set (H5FD_SOURCES
${HDF5_SRC_DIR}/H5FDcore.c
${HDF5_SRC_DIR}/H5FDdirect.c
${HDF5_SRC_DIR}/H5FDfamily.c
+ ${HDF5_SRC_DIR}/H5FDhdfs.c
${HDF5_SRC_DIR}/H5FDint.c
${HDF5_SRC_DIR}/H5FDlog.c
${HDF5_SRC_DIR}/H5FDmpi.c
${HDF5_SRC_DIR}/H5FDmpio.c
${HDF5_SRC_DIR}/H5FDmulti.c
+ ${HDF5_SRC_DIR}/H5FDros3.c
+ ${HDF5_SRC_DIR}/H5FDs3comms.c
${HDF5_SRC_DIR}/H5FDsec2.c
${HDF5_SRC_DIR}/H5FDspace.c
${HDF5_SRC_DIR}/H5FDstdio.c
@@ -249,12 +247,14 @@ set (H5FD_HDRS
${HDF5_SRC_DIR}/H5FDcore.h
${HDF5_SRC_DIR}/H5FDdirect.h
${HDF5_SRC_DIR}/H5FDfamily.h
+ ${HDF5_SRC_DIR}/H5FDhdfs.h
${HDF5_SRC_DIR}/H5FDlog.h
${HDF5_SRC_DIR}/H5FDmpi.h
${HDF5_SRC_DIR}/H5FDmpio.h
${HDF5_SRC_DIR}/H5FDmulti.h
- ${HDF5_SRC_DIR}/H5FDpkg.h
${HDF5_SRC_DIR}/H5FDpublic.h
+ ${HDF5_SRC_DIR}/H5FDros3.h
+ ${HDF5_SRC_DIR}/H5FDs3comms.c
${HDF5_SRC_DIR}/H5FDsec2.h
${HDF5_SRC_DIR}/H5FDstdio.h
${HDF5_SRC_DIR}/H5FDwindows.h
@@ -289,8 +289,6 @@ set (H5FS_SOURCES
)
set (H5FS_HDRS
- ${HDF5_SRC_DIR}/H5FSpkg.h
- ${HDF5_SRC_DIR}/H5FSpublic.h
)
IDE_GENERATED_PROPERTIES ("H5FS" "${H5FS_HDRS}" "${H5FS_SOURCES}" )
@@ -316,7 +314,6 @@ set (H5G_SOURCES
)
set (H5G_HDRS
- ${HDF5_SRC_DIR}/H5Gpkg.h
${HDF5_SRC_DIR}/H5Gpublic.h
)
IDE_GENERATED_PROPERTIES ("H5G" "${H5G_HDRS}" "${H5G_SOURCES}" )
@@ -341,8 +338,6 @@ set (H5HF_SOURCES
)
set (H5HF_HDRS
- ${HDF5_SRC_DIR}/H5HFpkg.h
- ${HDF5_SRC_DIR}/H5HFpublic.h
)
IDE_GENERATED_PROPERTIES ("H5HF" "${H5HF_HDRS}" "${H5HF_SOURCES}" )
@@ -354,8 +349,6 @@ set (H5HG_SOURCES
)
set (H5HG_HDRS
- ${HDF5_SRC_DIR}/H5HGpkg.h
- ${HDF5_SRC_DIR}/H5HGpublic.h
)
IDE_GENERATED_PROPERTIES ("H5HG" "${H5HG_HDRS}" "${H5HG_SOURCES}" )
@@ -369,8 +362,6 @@ set (H5HL_SOURCES
)
set (H5HL_HDRS
- ${HDF5_SRC_DIR}/H5HLpkg.h
- ${HDF5_SRC_DIR}/H5HLpublic.h
)
IDE_GENERATED_PROPERTIES ("H5HL" "${H5HL_HDRS}" "${H5HL_SOURCES}" )
@@ -388,7 +379,6 @@ set (H5I_SOURCES
${HDF5_SRC_DIR}/H5Itest.c
)
set (H5I_HDRS
- ${HDF5_SRC_DIR}/H5Ipkg.h
${HDF5_SRC_DIR}/H5Ipublic.h
)
IDE_GENERATED_PROPERTIES ("H5I" "${H5I_HDRS}" "${H5I_SOURCES}" )
@@ -399,12 +389,20 @@ set (H5L_SOURCES
${HDF5_SRC_DIR}/H5Lexternal.c
)
set (H5L_HDRS
- ${HDF5_SRC_DIR}/H5Lpkg.h
${HDF5_SRC_DIR}/H5Lpublic.h
)
IDE_GENERATED_PROPERTIES ("H5L" "${H5L_HDRS}" "${H5L_SOURCES}" )
+set (H5M_SOURCES
+ ${HDF5_SRC_DIR}/H5M.c
+)
+set (H5M_HDRS
+ ${HDF5_SRC_DIR}/H5Mpublic.h
+)
+IDE_GENERATED_PROPERTIES ("H5M" "${H5M_HDRS}" "${H5M_SOURCES}")
+
+
set (H5MF_SOURCES
${HDF5_SRC_DIR}/H5MF.c
${HDF5_SRC_DIR}/H5MFaggr.c
@@ -432,7 +430,6 @@ set (H5MP_SOURCES
)
set (H5MP_HDRS
- ${HDF5_SRC_DIR}/H5MPpkg.h
)
IDE_GENERATED_PROPERTIES ("H5MP" "${H5MP_HDRS}" "${H5MP_SOURCES}" )
@@ -449,6 +446,7 @@ set (H5O_SOURCES
${HDF5_SRC_DIR}/H5Ochunk.c
${HDF5_SRC_DIR}/H5Ocont.c
${HDF5_SRC_DIR}/H5Ocopy.c
+ ${HDF5_SRC_DIR}/H5Ocopy_ref.c
${HDF5_SRC_DIR}/H5Odbg.c
${HDF5_SRC_DIR}/H5Odeprec.c
${HDF5_SRC_DIR}/H5Odrvinfo.c
@@ -477,9 +475,7 @@ set (H5O_SOURCES
)
set (H5O_HDRS
- ${HDF5_SRC_DIR}/H5Opkg.h
${HDF5_SRC_DIR}/H5Opublic.h
- ${HDF5_SRC_DIR}/H5Oshared.h
)
IDE_GENERATED_PROPERTIES ("H5O" "${H5O_HDRS}" "${H5O_SOURCES}" )
@@ -498,6 +494,8 @@ set (H5P_SOURCES
${HDF5_SRC_DIR}/H5Pint.c
${HDF5_SRC_DIR}/H5Plapl.c
${HDF5_SRC_DIR}/H5Plcpl.c
+ ${HDF5_SRC_DIR}/H5Pmapl.c
+ ${HDF5_SRC_DIR}/H5Pmcpl.c
${HDF5_SRC_DIR}/H5Pocpl.c
${HDF5_SRC_DIR}/H5Pocpypl.c
${HDF5_SRC_DIR}/H5Pstrcpl.c
@@ -505,7 +503,6 @@ set (H5P_SOURCES
)
set (H5P_HDRS
- ${HDF5_SRC_DIR}/H5Ppkg.h
${HDF5_SRC_DIR}/H5Ppublic.h
)
IDE_GENERATED_PROPERTIES ("H5P" "${H5P_HDRS}" "${H5P_SOURCES}" )
@@ -515,7 +512,6 @@ set (H5PB_SOURCES
)
set (H5PB_HDRS
- ${HDF5_SRC_DIR}/H5PBpkg.h
)
IDE_GENERATED_PROPERTIES ("H5PB" "${H5PB_HDRS}" "${H5PB_SOURCES}" )
@@ -528,7 +524,6 @@ set (H5PL_SOURCES
set (H5PL_HDRS
${HDF5_SRC_DIR}/H5PLextern.h
- ${HDF5_SRC_DIR}/H5PLpkg.h
${HDF5_SRC_DIR}/H5PLpublic.h
)
IDE_GENERATED_PROPERTIES ("H5PL" "${H5PL_HDRS}" "${H5PL_SOURCES}" )
@@ -540,7 +535,6 @@ set (H5R_SOURCES
${HDF5_SRC_DIR}/H5Rint.c
)
set (H5R_HDRS
- ${HDF5_SRC_DIR}/H5Rpkg.h
${HDF5_SRC_DIR}/H5Rpublic.h
)
IDE_GENERATED_PROPERTIES ("H5R" "${H5R_HDRS}" "${H5R_SOURCES}" )
@@ -558,6 +552,7 @@ set (H5S_SOURCES
${HDF5_SRC_DIR}/H5S.c
${HDF5_SRC_DIR}/H5Sall.c
${HDF5_SRC_DIR}/H5Sdbg.c
+ ${HDF5_SRC_DIR}/H5Sdeprec.c
${HDF5_SRC_DIR}/H5Shyper.c
${HDF5_SRC_DIR}/H5Smpio.c
${HDF5_SRC_DIR}/H5Snone.c
@@ -567,7 +562,6 @@ set (H5S_SOURCES
)
set (H5S_HDRS
- ${HDF5_SRC_DIR}/H5Spkg.h
${HDF5_SRC_DIR}/H5Spublic.h
)
IDE_GENERATED_PROPERTIES ("H5S" "${H5S_HDRS}" "${H5S_SOURCES}" )
@@ -590,7 +584,6 @@ set (H5SM_SOURCES
)
set (H5SM_HDRS
- ${HDF5_SRC_DIR}/H5SMpkg.h
)
IDE_GENERATED_PROPERTIES ("H5SM" "${H5SM_HDRS}" "${H5SM_SOURCES}" )
@@ -624,13 +617,13 @@ set (H5T_SOURCES
${HDF5_SRC_DIR}/H5Torder.c
${HDF5_SRC_DIR}/H5Tpad.c
${HDF5_SRC_DIR}/H5Tprecis.c
+ ${HDF5_SRC_DIR}/H5Tref.c
${HDF5_SRC_DIR}/H5Tstrpad.c
${HDF5_SRC_DIR}/H5Tvisit.c
${HDF5_SRC_DIR}/H5Tvlen.c
)
set (H5T_HDRS
- ${HDF5_SRC_DIR}/H5Tpkg.h
${HDF5_SRC_DIR}/H5Tpublic.h
)
IDE_GENERATED_PROPERTIES ("H5T" "${H5T_HDRS}" "${H5T_SOURCES}" )
@@ -652,6 +645,30 @@ set (H5UC_HDRS
IDE_GENERATED_PROPERTIES ("H5UC" "${H5UC_HDRS}" "${H5UC_SOURCES}" )
+set (H5VL_SOURCES
+ ${HDF5_SRC_DIR}/H5VL.c
+ ${HDF5_SRC_DIR}/H5VLcallback.c
+ ${HDF5_SRC_DIR}/H5VLint.c
+ ${HDF5_SRC_DIR}/H5VLnative.c
+ ${HDF5_SRC_DIR}/H5VLnative_attr.c
+ ${HDF5_SRC_DIR}/H5VLnative_blob.c
+ ${HDF5_SRC_DIR}/H5VLnative_dataset.c
+ ${HDF5_SRC_DIR}/H5VLnative_datatype.c
+ ${HDF5_SRC_DIR}/H5VLnative_file.c
+ ${HDF5_SRC_DIR}/H5VLnative_group.c
+ ${HDF5_SRC_DIR}/H5VLnative_link.c
+ ${HDF5_SRC_DIR}/H5VLnative_object.c
+ ${HDF5_SRC_DIR}/H5VLpassthru.c
+)
+set (H5VL_HDRS
+ ${HDF5_SRC_DIR}/H5VLconnector.h
+ ${HDF5_SRC_DIR}/H5VLconnector_passthru.h
+ ${HDF5_SRC_DIR}/H5VLnative.h
+ ${HDF5_SRC_DIR}/H5VLpassthru.h
+ ${HDF5_SRC_DIR}/H5VLpublic.h
+)
+IDE_GENERATED_PROPERTIES ("H5VL" "${H5VL_HDRS}" "${H5VL_SOURCES}" )
+
set (H5VM_SOURCES
${HDF5_SRC_DIR}/H5VM.c
)
@@ -685,7 +702,6 @@ endif ()
set (H5Z_HDRS
- ${HDF5_SRC_DIR}/H5Zpkg.h
${HDF5_SRC_DIR}/H5Zpublic.h
)
IDE_GENERATED_PROPERTIES ("H5Z" "${H5Z_HDRS}" "${H5Z_SOURCES}" )
@@ -715,6 +731,7 @@ set (common_SRCS
${H5HP_SOURCES}
${H5I_SOURCES}
${H5L_SOURCES}
+ ${H5M_SOURCES}
${H5MF_SOURCES}
${H5MM_SOURCES}
${H5MP_SOURCES}
@@ -731,6 +748,7 @@ set (common_SRCS
${H5ST_SOURCES}
${H5T_SOURCES}
${H5TS_SOURCES}
+ ${H5VL_SOURCES}
${H5VM_SOURCES}
${H5WB_SOURCES}
${H5Z_SOURCES}
@@ -746,6 +764,7 @@ set (H5_PUBLIC_HEADERS
${H5D_HDRS}
${H5E_HDRS}
${H5EA_HDRS}
+ ${H5ES_HDRS}
${H5F_HDRS}
${H5FA_HDRS}
${H5FD_HDRS}
@@ -756,6 +775,7 @@ set (H5_PUBLIC_HEADERS
${H5HL_HDRS}
${H5I_HDRS}
${H5L_HDRS}
+ ${H5M_HDRS}
${H5MF_HDRS}
${H5MM_HDRS}
${H5MP_HDRS}
@@ -767,54 +787,137 @@ set (H5_PUBLIC_HEADERS
${H5S_HDRS}
${H5SM_HDRS}
${H5T_HDRS}
+ ${H5VL_HDRS}
${H5Z_HDRS}
)
set (H5_PRIVATE_HEADERS
${HDF5_SRC_DIR}/H5private.h
+
+ ${HDF5_SRC_DIR}/H5Apkg.h
${HDF5_SRC_DIR}/H5Aprivate.h
+
+ ${HDF5_SRC_DIR}/H5ACpkg.h
${HDF5_SRC_DIR}/H5ACprivate.h
- ${HDF5_SRC_DIR}/H5B2private.h
+
+ ${HDF5_SRC_DIR}/H5Bpkg.h
${HDF5_SRC_DIR}/H5Bprivate.h
+
+ ${HDF5_SRC_DIR}/H5B2pkg.h
+ ${HDF5_SRC_DIR}/H5B2private.h
+
+ ${HDF5_SRC_DIR}/H5Clog.h
+ ${HDF5_SRC_DIR}/H5Cpkg.h
${HDF5_SRC_DIR}/H5Cprivate.h
+
${HDF5_SRC_DIR}/H5CSprivate.h
+
${HDF5_SRC_DIR}/H5CXprivate.h
+
+ ${HDF5_SRC_DIR}/H5Dpkg.h
${HDF5_SRC_DIR}/H5Dprivate.h
+
+ ${HDF5_SRC_DIR}/H5Edefin.h
+ ${HDF5_SRC_DIR}/H5Einit.h
+ ${HDF5_SRC_DIR}/H5Epkg.h
${HDF5_SRC_DIR}/H5Eprivate.h
+ ${HDF5_SRC_DIR}/H5Eterm.h
+
+ ${HDF5_SRC_DIR}/H5EApkg.h
${HDF5_SRC_DIR}/H5EAprivate.h
+
+ ${HDF5_SRC_DIR}/H5Fpkg.h
+ ${HDF5_SRC_DIR}/H5Fprivate.h
+
+ ${HDF5_SRC_DIR}/H5FApkg.h
${HDF5_SRC_DIR}/H5FAprivate.h
+
+ ${HDF5_SRC_DIR}/H5FDpkg.h
${HDF5_SRC_DIR}/H5FDprivate.h
- ${HDF5_SRC_DIR}/H5Fprivate.h
+
${HDF5_SRC_DIR}/H5FLprivate.h
+
${HDF5_SRC_DIR}/H5FOprivate.h
- ${HDF5_SRC_DIR}/H5MFprivate.h
- ${HDF5_SRC_DIR}/H5MMprivate.h
- ${HDF5_SRC_DIR}/H5Cprivate.h
+
+ ${HDF5_SRC_DIR}/H5FSpkg.h
${HDF5_SRC_DIR}/H5FSprivate.h
+
+ ${HDF5_SRC_DIR}/H5Gpkg.h
${HDF5_SRC_DIR}/H5Gprivate.h
+
+ ${HDF5_SRC_DIR}/H5HFpkg.h
${HDF5_SRC_DIR}/H5HFprivate.h
+
+ ${HDF5_SRC_DIR}/H5HGpkg.h
${HDF5_SRC_DIR}/H5HGprivate.h
+
+ ${HDF5_SRC_DIR}/H5HLpkg.h
${HDF5_SRC_DIR}/H5HLprivate.h
+
${HDF5_SRC_DIR}/H5HPprivate.h
+
+ ${HDF5_SRC_DIR}/H5Ipkg.h
${HDF5_SRC_DIR}/H5Iprivate.h
+
+ ${HDF5_SRC_DIR}/H5Lpkg.h
${HDF5_SRC_DIR}/H5Lprivate.h
+
+ ${HDF5_SRC_DIR}/H5Mpkg.h
+ ${HDF5_SRC_DIR}/H5Mprivate.h
+
+ ${HDF5_SRC_DIR}/H5MFprivate.h
+
+ ${HDF5_SRC_DIR}/H5MMprivate.h
+
+ ${HDF5_SRC_DIR}/H5MPpkg.h
${HDF5_SRC_DIR}/H5MPprivate.h
+
+ ${HDF5_SRC_DIR}/H5Opkg.h
${HDF5_SRC_DIR}/H5Oprivate.h
+ ${HDF5_SRC_DIR}/H5Oshared.h
+
+ ${HDF5_SRC_DIR}/H5Ppkg.h
${HDF5_SRC_DIR}/H5Pprivate.h
+
${HDF5_SRC_DIR}/H5PBprivate.h
+ ${HDF5_SRC_DIR}/H5PBpkg.h
+
+ ${HDF5_SRC_DIR}/H5PLpkg.h
${HDF5_SRC_DIR}/H5PLprivate.h
- ${HDF5_SRC_DIR}/H5UCprivate.h
+
+ ${HDF5_SRC_DIR}/H5Rpkg.h
${HDF5_SRC_DIR}/H5Rprivate.h
+
${HDF5_SRC_DIR}/H5RSprivate.h
+
+ ${HDF5_SRC_DIR}/H5Spkg.h
+ ${HDF5_SRC_DIR}/H5Sprivate.h
+
${HDF5_SRC_DIR}/H5SLprivate.h
+
+ ${HDF5_SRC_DIR}/H5SMpkg.h
${HDF5_SRC_DIR}/H5SMprivate.h
- ${HDF5_SRC_DIR}/H5Sprivate.h
+
${HDF5_SRC_DIR}/H5STprivate.h
+
+ ${HDF5_SRC_DIR}/H5Tpkg.h
${HDF5_SRC_DIR}/H5Tprivate.h
+
${HDF5_SRC_DIR}/H5TSprivate.h
+
+ ${HDF5_SRC_DIR}/H5UCprivate.h
+
+ ${HDF5_SRC_DIR}/H5VLnative_private.h
+ ${HDF5_SRC_DIR}/H5VLpkg.h
+ ${HDF5_SRC_DIR}/H5VLprivate.h
+
${HDF5_SRC_DIR}/H5VMprivate.h
+
${HDF5_SRC_DIR}/H5WBprivate.h
+
+ ${HDF5_SRC_DIR}/H5Zpkg.h
${HDF5_SRC_DIR}/H5Zprivate.h
+
${HDF5_SRC_DIR}/H5win32defs.h
)
@@ -827,6 +930,12 @@ set (H5_GENERATED_HEADERS
${HDF5_SRC_DIR}/H5overflow.h
)
+set (H5_PUBLIC_GENERATED_HEADERS
+ ${HDF5_SRC_DIR}/H5Epubgen.h
+ ${HDF5_SRC_DIR}/H5version.h
+ ${HDF5_SRC_DIR}/H5overflow.h
+)
+
option (HDF5_GENERATE_HEADERS "Rebuild Generated Files" ON)
if (HDF5_GENERATE_HEADERS)
set_source_files_properties(${H5_GENERATED_HEADERS} PROPERTIES GENERATED TRUE)
@@ -853,7 +962,6 @@ endif ()
# Setup the H5detect utility which generates H5Tinit with platform
# specific type checks inside
#-----------------------------------------------------------------------------
-option (HDF5_USE_PREGEN "Use pre-generated Files" OFF)
if (HDF5_USE_PREGEN)
set (HDF5_GENERATED_SOURCE_DIR ${HDF5_USE_PREGEN_DIR})
else ()
@@ -864,73 +972,150 @@ if (BUILD_SHARED_LIBS)
file (MAKE_DIRECTORY "${HDF5_BINARY_DIR}/shared")
endif ()
-if (NOT EXISTS ${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c)
+if (LOCAL_BATCH_TEST)
+ if (LOCAL_BATCH_SCRIPT_COMMAND STREQUAL "raybsub")
+ configure_file (
+ ${HDF5_SOURCE_DIR}/bin/batch/${LOCAL_BATCH_SCRIPT_COMMAND}
+ ${HDF5_BINARY_DIR}/${LOCAL_BATCH_SCRIPT_COMMAND} ESCAPE_QUOTES @ONLY
+ )
+ endif ()
+ if (LOCAL_BATCH_SCRIPT_NAME)
+ configure_file (
+ ${HDF5_SOURCE_DIR}/bin/batch/${LOCAL_BATCH_SCRIPT_NAME}.in.cmake
+ ${HDF5_BINARY_DIR}/${LOCAL_BATCH_SCRIPT_NAME} ESCAPE_QUOTES @ONLY
+ )
+ endif ()
+ if (LOCAL_BATCH_SCRIPT_PARALLEL_NAME)
+ configure_file (
+ ${HDF5_SOURCE_DIR}/bin/batch/${LOCAL_BATCH_SCRIPT_PARALLEL_NAME}.in.cmake
+ ${HDF5_BINARY_DIR}/${LOCAL_BATCH_SCRIPT_PARALLEL_NAME} ESCAPE_QUOTES @ONLY
+ )
+ endif ()
+endif ()
+
+if (NOT EXISTS "${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c")
add_executable (H5detect ${HDF5_SRC_DIR}/H5detect.c)
- target_include_directories(H5detect PRIVATE "${HDF5_SRC_DIR};${HDF5_BINARY_DIR};$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_INCLUDE_DIRS}>")
+ target_include_directories (H5detect PRIVATE "${HDF5_SRC_DIR};${HDF5_BINARY_DIR};$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_INCLUDE_DIRS}>")
target_compile_definitions(H5detect PUBLIC ${HDF_EXTRA_C_FLAGS} ${HDF_EXTRA_FLAGS})
TARGET_C_PROPERTIES (H5detect STATIC)
target_link_libraries (H5detect
- PRIVATE "$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_LIBRARIES}>" $<$<PLATFORM_ID:Windows>:ws2_32.lib>
- INTERFACE $<$<PLATFORM_ID:Emscripten>:"-O0">
+ PRIVATE "$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_LIBRARIES}>" $<$<OR:$<PLATFORM_ID:Windows>,$<PLATFORM_ID:MinGW>>:ws2_32.lib>
+ PRIVATE $<$<PLATFORM_ID:Emscripten>:"-O0">
)
- add_custom_command (
- OUTPUT ${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c
- COMMAND $<TARGET_FILE:H5detect>
- ARGS ${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c
- DEPENDS H5detect
- WORKING_DIRECTORY ${HDF5_GENERATED_SOURCE_DIR}
- )
- if (BUILD_SHARED_LIBS)
- if (NOT EXISTS ${HDF5_GENERATED_SOURCE_DIR}/shared/H5Tinit.c)
+ if (HDF5_BATCH_H5DETECT)
+ configure_file (
+ ${HDF5_SOURCE_DIR}/bin/batch/${HDF5_BATCH_H5DETECT_SCRIPT}.in.cmake
+ ${HDF5_BINARY_DIR}/${HDF5_BATCH_H5DETECT_SCRIPT} ESCAPE_QUOTES @ONLY
+ )
+ add_custom_command (
+ OUTPUT ${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c
+ ${HDF5_GENERATED_SOURCE_DIR}/gen_SRCS.stamp1
+ COMMAND ${HDF5_BATCH_CMD}
+ ARGS ${HDF5_BINARY_DIR}/${HDF5_BATCH_H5DETECT_SCRIPT}
+ COMMAND ${CMAKE_COMMAND}
+ ARGS -E echo "Executed batch command to create H5Tinit.c"
+ COMMAND ${CMAKE_COMMAND}
+ ARGS -E touch ${HDF5_GENERATED_SOURCE_DIR}/gen_SRCS.stamp1
+ DEPENDS H5detect
+ WORKING_DIRECTORY ${HDF5_GENERATED_SOURCE_DIR}
+ )
+ add_custom_target (gen_H5Tinit
+ COMMAND ${CMAKE_COMMAND} -P ${HDF5_SOURCE_DIR}/config/cmake/wait_H5Tinit.cmake
+ )
+ if (BUILD_SHARED_LIBS)
add_custom_command (
- OUTPUT ${HDF5_GENERATED_SOURCE_DIR}/shared/H5Tinit.c
- COMMAND $<TARGET_FILE:H5detect>
- ARGS ${HDF5_GENERATED_SOURCE_DIR}/shared/H5Tinit.c
- DEPENDS H5detect
- WORKING_DIRECTORY ${HDF5_GENERATED_SOURCE_DIR}/shared
+ OUTPUT ${HDF5_GENERATED_SOURCE_DIR}/shared/H5Tinit.c
+ ${HDF5_GENERATED_SOURCE_DIR}/shared/shared_gen_SRCS.stamp1
+ COMMAND ${CMAKE_COMMAND}
+ ARGS -E copy_if_different "${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c" "${HDF5_GENERATED_SOURCE_DIR}/shared/H5Tinit.c"
+ COMMAND ${CMAKE_COMMAND}
+ ARGS -E touch ${HDF5_GENERATED_SOURCE_DIR}/shared/shared_gen_SRCS.stamp1
+ DEPENDS gen_H5Tinit ${HDF5_GENERATED_SOURCE_DIR}/H5Tinit_created
+ WORKING_DIRECTORY ${HDF5_GENERATED_SOURCE_DIR}
+ )
+ set_source_files_properties (${HDF5_GENERATED_SOURCE_DIR}/shared/H5Tinit.c PROPERTIES GENERATED TRUE)
+ endif ()
+ else ()
+ add_custom_command (
+ OUTPUT ${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c
+ ${HDF5_GENERATED_SOURCE_DIR}/gen_SRCS.stamp1
+ COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $<TARGET_FILE:H5detect>
+ ARGS ${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c
+ COMMAND ${CMAKE_COMMAND}
+ ARGS -E touch ${HDF5_GENERATED_SOURCE_DIR}/gen_SRCS.stamp1
+ DEPENDS H5detect
+ WORKING_DIRECTORY ${HDF5_GENERATED_SOURCE_DIR}
+ )
+ if (BUILD_SHARED_LIBS)
+ add_custom_command (
+ OUTPUT ${HDF5_GENERATED_SOURCE_DIR}/shared/H5Tinit.c
+ ${HDF5_GENERATED_SOURCE_DIR}/shared/shared_gen_SRCS.stamp1
+ COMMAND ${CMAKE_COMMAND}
+ ARGS -E copy_if_different "${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c" "${HDF5_GENERATED_SOURCE_DIR}/shared/H5Tinit.c"
+ COMMAND ${CMAKE_COMMAND}
+ ARGS -E touch ${HDF5_GENERATED_SOURCE_DIR}/shared/shared_gen_SRCS.stamp1
+ DEPENDS ${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c
+ WORKING_DIRECTORY ${HDF5_GENERATED_SOURCE_DIR}
)
- else ()
set_source_files_properties (${HDF5_GENERATED_SOURCE_DIR}/shared/H5Tinit.c PROPERTIES GENERATED TRUE)
endif ()
endif ()
-else ()
set_source_files_properties (${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c PROPERTIES GENERATED TRUE)
+else ()
+ add_custom_command (
+ OUTPUT ${HDF5_GENERATED_SOURCE_DIR}/gen_SRCS.stamp1
+ COMMAND ${CMAKE_COMMAND}
+ ARGS -E touch ${HDF5_GENERATED_SOURCE_DIR}/gen_SRCS.stamp1
+ DEPENDS ${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c
+ WORKING_DIRECTORY ${HDF5_GENERATED_SOURCE_DIR}
+ )
if (BUILD_SHARED_LIBS)
add_custom_command (
- OUTPUT ${HDF5_GENERATED_SOURCE_DIR}/shared/H5Tinit.c
+ OUTPUT ${HDF5_GENERATED_SOURCE_DIR}/shared/shared_gen_SRCS.stamp1
COMMAND ${CMAKE_COMMAND}
ARGS -E copy_if_different "${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c" "${HDF5_GENERATED_SOURCE_DIR}/shared/H5Tinit.c"
+ COMMAND ${CMAKE_COMMAND}
+ ARGS -E touch ${HDF5_GENERATED_SOURCE_DIR}/shared/shared_gen_SRCS.stamp1
DEPENDS ${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c
+ WORKING_DIRECTORY ${HDF5_GENERATED_SOURCE_DIR}
)
set_source_files_properties (${HDF5_GENERATED_SOURCE_DIR}/shared/H5Tinit.c PROPERTIES GENERATED TRUE)
endif ()
endif ()
add_executable (H5make_libsettings ${HDF5_SRC_DIR}/H5make_libsettings.c)
-target_include_directories(H5make_libsettings PRIVATE "${HDF5_SRC_DIR};${HDF5_BINARY_DIR};$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_INCLUDE_DIRS}>")
+target_include_directories (H5make_libsettings PRIVATE "${HDF5_SRC_DIR};${HDF5_BINARY_DIR};$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_INCLUDE_DIRS}>")
target_compile_definitions(H5make_libsettings PUBLIC ${HDF_EXTRA_C_FLAGS} ${HDF_EXTRA_FLAGS})
TARGET_C_PROPERTIES (H5make_libsettings STATIC)
target_link_libraries (H5make_libsettings
- PRIVATE "$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_LIBRARIES}>" $<$<PLATFORM_ID:Windows>:ws2_32.lib>
- INTERFACE $<$<PLATFORM_ID:Emscripten>:"-O0">
+ PRIVATE "$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_LIBRARIES}>" $<$<OR:$<PLATFORM_ID:Windows>,$<PLATFORM_ID:MinGW>>:ws2_32.lib>
+ PRIVATE $<$<PLATFORM_ID:Emscripten>:"-O0">
)
add_custom_command (
OUTPUT ${HDF5_BINARY_DIR}/H5lib_settings.c
- COMMAND $<TARGET_FILE:H5make_libsettings>
+ ${HDF5_BINARY_DIR}/gen_SRCS.stamp2
+ COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $<TARGET_FILE:H5make_libsettings>
ARGS ${HDF5_BINARY_DIR}/H5lib_settings.c
+ COMMAND ${CMAKE_COMMAND}
+ ARGS -E touch ${HDF5_GENERATED_SOURCE_DIR}/gen_SRCS.stamp2
DEPENDS H5make_libsettings
WORKING_DIRECTORY ${HDF5_BINARY_DIR}
)
+set_source_files_properties (${HDF5_BINARY_DIR}/H5lib_settings.c PROPERTIES GENERATED TRUE)
if (BUILD_SHARED_LIBS)
add_custom_command (
OUTPUT ${HDF5_BINARY_DIR}/shared/H5lib_settings.c
- COMMAND $<TARGET_FILE:H5make_libsettings>
- ARGS ${HDF5_BINARY_DIR}/shared/H5lib_settings.c
- DEPENDS H5make_libsettings
+ ${HDF5_BINARY_DIR}/shared/shared_gen_SRCS.stamp2
+ COMMAND ${CMAKE_COMMAND}
+ ARGS -E copy_if_different "${HDF5_BINARY_DIR}/H5lib_settings.c" "${HDF5_BINARY_DIR}/shared/H5lib_settings.c"
+ COMMAND ${CMAKE_COMMAND}
+ ARGS -E touch ${HDF5_GENERATED_SOURCE_DIR}/shared/shared_gen_SRCS.stamp2
+ DEPENDS ${HDF5_BINARY_DIR}/H5lib_settings.c
WORKING_DIRECTORY ${HDF5_BINARY_DIR}
)
+ set_source_files_properties (${HDF5_BINARY_DIR}/shared/H5lib_settings.c PROPERTIES GENERATED TRUE)
endif ()
## all_packages="AC,B,B2,D,F,FA,FL,FS,HL,I,O,S,ST,T,Z"
@@ -940,39 +1125,49 @@ option (HDF5_ENABLE_DEBUG_APIS "Turn on extra debug output in all packages" OFF)
#-----------------------------------------------------------------------------
# Add H5Tinit source to build - generated by H5detect/CMake at configure time
#-----------------------------------------------------------------------------
-set (gen_SRCS ${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c ${HDF5_BINARY_DIR}/H5lib_settings.c)
+if (NOT ONLY_SHARED_LIBS)
+ set (gen_SRCS ${HDF5_GENERATED_SOURCE_DIR}/H5Tinit.c ${HDF5_BINARY_DIR}/H5lib_settings.c)
+ add_custom_target (gen_${HDF5_LIB_TARGET} ALL DEPENDS ${HDF5_GENERATED_SOURCE_DIR}/gen_SRCS.stamp1 ${HDF5_GENERATED_SOURCE_DIR}/gen_SRCS.stamp2)
-add_library (${HDF5_LIB_TARGET} STATIC ${common_SRCS} ${gen_SRCS} ${H5_PUBLIC_HEADERS} ${H5_PRIVATE_HEADERS} ${H5_GENERATED_HEADERS})
-target_include_directories(${HDF5_LIB_TARGET}
- PRIVATE "${HDF5_SRC_DIR};${HDF5_BINARY_DIR};$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_INCLUDE_DIRS}>"
- INTERFACE "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include>"
-)
-target_compile_definitions(${HDF5_LIB_TARGET}
- PUBLIC
- ${HDF_EXTRA_C_FLAGS}
- ${HDF_EXTRA_FLAGS}
- $<IF:$<CONFIG:Debug>,DEBUG,NDEBUG>
- PRIVATE
- $<$<BOOL:${HDF5_ENABLE_TRACE}>:H5_DEBUG_API> # Enable tracing of the API
- $<$<BOOL:${HDF5_ENABLE_DEBUG_APIS}>:H5Z_DEBUG;H5T_DEBUG;H5ST_DEBUG;H5S_DEBUG;H5O_DEBUG;H5I_DEBUG;H5HL_DEBUG;H5F_DEBUG;H5D_DEBUG;H5B2_DEBUG;H5AC_DEBUG>
-)
-TARGET_C_PROPERTIES (${HDF5_LIB_TARGET} STATIC)
-target_link_libraries (${HDF5_LIB_TARGET}
- PRIVATE ${LINK_LIBS} ${LINK_COMP_LIBS} "$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_LIBRARIES}>"
- PUBLIC $<$<NOT:$<PLATFORM_ID:Windows>>:${CMAKE_DL_LIBS}>
-)
-set_global_variable (HDF5_LIBRARIES_TO_EXPORT ${HDF5_LIB_TARGET})
-H5_SET_LIB_OPTIONS (${HDF5_LIB_TARGET} ${HDF5_LIB_NAME} STATIC 0)
-set_target_properties (${HDF5_LIB_TARGET} PROPERTIES FOLDER libraries)
+ add_library (${HDF5_LIB_TARGET} STATIC ${common_SRCS} ${gen_SRCS} ${H5_PUBLIC_HEADERS} ${H5_PRIVATE_HEADERS} ${H5_GENERATED_HEADERS})
+ target_include_directories (${HDF5_LIB_TARGET}
+ PRIVATE "${HDF5_SRC_DIR};${HDF5_BINARY_DIR};$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_INCLUDE_DIRS}>"
+ INTERFACE "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include>"
+ )
+ target_compile_definitions(${HDF5_LIB_TARGET}
+ PUBLIC
+ ${HDF_EXTRA_C_FLAGS}
+ ${HDF_EXTRA_FLAGS}
+ PRIVATE
+ $<$<BOOL:${HDF5_ENABLE_TRACE}>:H5_DEBUG_API> # Enable tracing of the API
+ $<$<BOOL:${HDF5_ENABLE_DEBUG_APIS}>:H5Z_DEBUG;H5T_DEBUG;H5ST_DEBUG;H5S_DEBUG;H5O_DEBUG;H5I_DEBUG;H5HL_DEBUG;H5F_DEBUG;H5D_DEBUG;H5B2_DEBUG;H5AC_DEBUG>
+ )
+ TARGET_C_PROPERTIES (${HDF5_LIB_TARGET} STATIC)
+ target_link_libraries (${HDF5_LIB_TARGET}
+ PRIVATE ${LINK_LIBS} ${LINK_COMP_LIBS} "$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_LIBRARIES}>"
+ PUBLIC $<$<NOT:$<PLATFORM_ID:Windows>>:${CMAKE_DL_LIBS}>
+ )
+ if (NOT WIN32)
+ target_link_libraries (${HDF5_LIB_TARGET}
+ PRIVATE $<$<BOOL:${HDF5_ENABLE_THREADSAFE}>:Threads::Threads>
+ )
+ endif ()
+ set_global_variable (HDF5_LIBRARIES_TO_EXPORT ${HDF5_LIB_TARGET})
+ H5_SET_LIB_OPTIONS (${HDF5_LIB_TARGET} ${HDF5_LIB_NAME} STATIC 0)
+ set_target_properties (${HDF5_LIB_TARGET} PROPERTIES FOLDER libraries)
+ add_dependencies (${HDF5_LIB_TARGET} gen_${HDF5_LIB_TARGET})
-set (install_targets ${HDF5_LIB_TARGET})
+ set (install_targets ${HDF5_LIB_TARGET})
+endif ()
if (BUILD_SHARED_LIBS)
set (shared_gen_SRCS ${HDF5_GENERATED_SOURCE_DIR}/shared/H5Tinit.c ${HDF5_BINARY_DIR}/shared/H5lib_settings.c)
+ add_custom_target (gen_${HDF5_LIBSH_TARGET} ALL DEPENDS ${HDF5_GENERATED_SOURCE_DIR}/shared/shared_gen_SRCS.stamp1 ${HDF5_GENERATED_SOURCE_DIR}/shared/shared_gen_SRCS.stamp2)
add_library (${HDF5_LIBSH_TARGET} SHARED ${common_SRCS} ${shared_gen_SRCS} ${H5_PUBLIC_HEADERS} ${H5_PRIVATE_HEADERS} ${H5_GENERATED_HEADERS})
- target_include_directories(${HDF5_LIBSH_TARGET}
+ target_include_directories (${HDF5_LIBSH_TARGET}
PRIVATE "${HDF5_SRC_DIR};${HDF5_BINARY_DIR};$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_INCLUDE_DIRS}>"
+ PUBLIC "$<$<BOOL:${HDF5_ENABLE_HDFS}>:${HDFS_INCLUDE_DIR}>"
INTERFACE "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include>"
)
target_compile_definitions(${HDF5_LIBSH_TARGET}
@@ -980,7 +1175,6 @@ if (BUILD_SHARED_LIBS)
"H5_BUILT_AS_DYNAMIC_LIB"
${HDF_EXTRA_C_FLAGS}
${HDF_EXTRA_FLAGS}
- $<IF:$<CONFIG:Debug>,DEBUG,NDEBUG>
PRIVATE
$<$<BOOL:${HDF5_ENABLE_THREADSAFE}>:H5_HAVE_THREADSAFE>
$<$<BOOL:${HDF5_ENABLE_TRACE}>:H5_DEBUG_API> # Enable tracing of the API
@@ -988,12 +1182,13 @@ if (BUILD_SHARED_LIBS)
)
TARGET_C_PROPERTIES (${HDF5_LIBSH_TARGET} SHARED)
target_link_libraries (${HDF5_LIBSH_TARGET}
- PRIVATE ${LINK_LIBS} ${LINK_COMP_LIBS} "$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_LIBRARIES}>"
- PUBLIC $<$<NOT:$<PLATFORM_ID:Windows>>:${CMAKE_DL_LIBS}> $<$<BOOL:${HDF5_ENABLE_THREADSAFE}>:Threads::Threads>
+ PRIVATE ${LINK_LIBS} ${LINK_COMP_LIBS} "$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_LIBRARIES}>" $<$<BOOL:${HDF5_ENABLE_THREADSAFE}>:Threads::Threads>
+ PUBLIC $<$<NOT:$<PLATFORM_ID:Windows>>:${CMAKE_DL_LIBS}>
)
set_global_variable (HDF5_LIBRARIES_TO_EXPORT "${HDF5_LIBRARIES_TO_EXPORT};${HDF5_LIBSH_TARGET}")
H5_SET_LIB_OPTIONS (${HDF5_LIBSH_TARGET} ${HDF5_LIB_NAME} SHARED "LIB")
set_target_properties (${HDF5_LIBSH_TARGET} PROPERTIES FOLDER libraries)
+ add_dependencies (${HDF5_LIBSH_TARGET} gen_${HDF5_LIBSH_TARGET})
set (install_targets ${install_targets} ${HDF5_LIBSH_TARGET})
endif ()
@@ -1005,7 +1200,7 @@ if (NOT HDF5_INSTALL_NO_DEVELOPMENT)
install (
FILES
${H5_PUBLIC_HEADERS}
- ${H5_GENERATED_HEADERS}
+ ${H5_PUBLIC_GENERATED_HEADERS}
${HDF5_BINARY_DIR}/H5pubconf.h
DESTINATION
${HDF5_INSTALL_INCLUDE_DIR}
@@ -1021,7 +1216,9 @@ if (HDF5_EXPORTED_TARGETS)
if (BUILD_SHARED_LIBS)
INSTALL_TARGET_PDB (${HDF5_LIBSH_TARGET} ${HDF5_INSTALL_BIN_DIR} libraries)
endif ()
- INSTALL_TARGET_PDB (${HDF5_LIB_TARGET} ${HDF5_INSTALL_BIN_DIR} libraries)
+ if (NOT ONLY_SHARED_LIBS)
+ INSTALL_TARGET_PDB (${HDF5_LIB_TARGET} ${HDF5_INSTALL_LIB_DIR} libraries)
+ endif ()
install (
TARGETS
@@ -1050,7 +1247,9 @@ foreach (libs ${LINK_LIBS} ${LINK_COMP_LIBS})
set (_PKG_CONFIG_LIBS_PRIVATE "${_PKG_CONFIG_LIBS_PRIVATE} -l${libs}")
endforeach ()
-set (_PKG_CONFIG_LIBS "${_PKG_CONFIG_LIBS} -l${HDF5_LIB_CORENAME}")
+if (NOT ONLY_SHARED_LIBS)
+ set (_PKG_CONFIG_LIBS "${_PKG_CONFIG_LIBS} -l${HDF5_LIB_CORENAME}")
+endif ()
if (BUILD_SHARED_LIBS)
set (_PKG_CONFIG_SH_LIBS "${_PKG_CONFIG_SH_LIBS} -l${HDF5_LIB_CORENAME}")
endif ()
diff --git a/src/H5.c b/src/H5.c
index c401667..401bb15 100644
--- a/src/H5.c
+++ b/src/H5.c
@@ -137,7 +137,7 @@ H5_init_library(void)
if (mpi_initialized && !mpi_finalized) {
int key_val;
- if(MPI_SUCCESS != (mpi_code = MPI_Comm_create_keyval(MPI_NULL_COPY_FN,
+ if(MPI_SUCCESS != (mpi_code = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,
(MPI_Comm_delete_attr_function *)H5_mpi_delete_cb,
&key_val, NULL)))
HMPI_GOTO_ERROR(FAIL, "MPI_Comm_create_keyval failed", mpi_code)
@@ -165,6 +165,7 @@ H5_init_library(void)
H5_debug_g.pkg[H5_PKG_HG].name = "hg";
H5_debug_g.pkg[H5_PKG_HL].name = "hl";
H5_debug_g.pkg[H5_PKG_I].name = "i";
+ H5_debug_g.pkg[H5_PKG_M].name = "m";
H5_debug_g.pkg[H5_PKG_MF].name = "mf";
H5_debug_g.pkg[H5_PKG_MM].name = "mm";
H5_debug_g.pkg[H5_PKG_O].name = "o";
@@ -172,6 +173,7 @@ H5_init_library(void)
H5_debug_g.pkg[H5_PKG_S].name = "s";
H5_debug_g.pkg[H5_PKG_T].name = "t";
H5_debug_g.pkg[H5_PKG_V].name = "v";
+ H5_debug_g.pkg[H5_PKG_VL].name = "vl";
H5_debug_g.pkg[H5_PKG_Z].name = "z";
/*
@@ -212,6 +214,8 @@ H5_init_library(void)
*/
if(H5E_init() < 0)
HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize error interface")
+ if(H5VL_init_phase1() < 0)
+ HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize vol interface")
if(H5P_init() < 0)
HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize property list interface")
if(H5T_init() < 0)
@@ -225,6 +229,10 @@ H5_init_library(void)
if(H5FS_init() < 0)
HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize FS interface")
+ /* Finish initializing interfaces that depend on the interfaces above */
+ if(H5VL_init_phase2() < 0)
+ HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize vol interface")
+
/* Debugging? */
H5_debug_mask("-all");
H5_debug_mask(HDgetenv("HDF5_DEBUG"));
@@ -304,6 +312,7 @@ H5_term_library(void)
pending += DOWN(A_top);
pending += DOWN(D_top);
pending += DOWN(G_top);
+ pending += DOWN(M_top);
pending += DOWN(R_top);
pending += DOWN(S_top);
pending += DOWN(T_top);
@@ -329,6 +338,7 @@ H5_term_library(void)
pending += DOWN(A);
pending += DOWN(D);
pending += DOWN(G);
+ pending += DOWN(M);
pending += DOWN(R);
pending += DOWN(S);
pending += DOWN(T);
@@ -343,6 +353,7 @@ H5_term_library(void)
pending += DOWN(AC);
pending += DOWN(Z);
pending += DOWN(FD);
+ pending += DOWN(VL);
pending += DOWN(PL);
/* Don't shut down the error code until other APIs which use it are shut down */
if(pending == 0)
diff --git a/src/H5A.c b/src/H5A.c
index 6f810be..abf8694 100644
--- a/src/H5A.c
+++ b/src/H5A.c
@@ -31,6 +31,7 @@
#include "H5MMprivate.h" /* Memory management */
#include "H5Opkg.h" /* Object headers */
#include "H5Sprivate.h" /* Dataspace functions */
+#include "H5VLprivate.h" /* Virtual Object Layer */
/****************/
@@ -251,10 +252,9 @@ hid_t
H5Acreate2(hid_t loc_id, const char *attr_name, hid_t type_id, hid_t space_id,
hid_t acpl_id, hid_t aapl_id)
{
- H5A_t *attr = NULL; /* Attribute created */
- H5G_loc_t loc; /* Object location */
- H5T_t *type; /* Datatype to use for attribute */
- H5S_t *space; /* Dataspace to use for attribute */
+ void *attr = NULL; /* Attribute created */
+ H5VL_object_t *vol_obj = NULL; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
hid_t ret_value = H5I_INVALID_HID; /* Return value */
FUNC_ENTER_API(H5I_INVALID_HID)
@@ -263,35 +263,39 @@ H5Acreate2(hid_t loc_id, const char *attr_name, hid_t type_id, hid_t space_id,
/* Check arguments */
if(H5I_ATTR == H5I_get_type(loc_id))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "location is not valid for an attribute")
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a location")
- if(0 == (H5F_INTENT(loc.oloc->file) & H5F_ACC_RDWR))
- HGOTO_ERROR(H5E_ARGS, H5E_WRITEERROR, H5I_INVALID_HID, "no write intent on file")
if(!attr_name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "attr_name parameter cannot be NULL")
if(!*attr_name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "attr_name parameter cannot be an empty string")
- if(NULL == (type = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a type")
- if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a dataspace")
+
+ /* Get correct property list */
+ if(H5P_DEFAULT == acpl_id)
+ acpl_id = H5P_ATTRIBUTE_CREATE_DEFAULT;
/* Verify access property list and set up collective metadata if appropriate */
if(H5CX_set_apl(&aapl_id, H5P_CLS_AACC, loc_id, TRUE) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info")
+ /* Get the location object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier")
+
+ /* Set location parameters */
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
/* Create the attribute */
- if(NULL == (attr = H5A__create(&loc, attr_name, type, space, acpl_id)))
+ if(NULL == (attr = H5VL_attr_create(vol_obj, &loc_params, attr_name, type_id, space_id, acpl_id, aapl_id, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, H5I_INVALID_HID, "unable to create attribute")
/* Register the new attribute and get an ID for it */
- if((ret_value = H5I_register(H5I_ATTR, attr, TRUE)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to atomize attribute handle")
+ if((ret_value = H5VL_register(H5I_ATTR, attr, vol_obj->connector, TRUE)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to atomize attribute handle")
done:
/* Cleanup on failure */
if(H5I_INVALID_HID == ret_value)
- if(attr && H5A__close(attr) < 0)
+ if(attr && H5VL_attr_close(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, H5I_INVALID_HID, "can't close attribute")
FUNC_LEAVE_API(ret_value)
@@ -333,10 +337,9 @@ H5Acreate_by_name(hid_t loc_id, const char *obj_name, const char *attr_name,
hid_t type_id, hid_t space_id, hid_t acpl_id, hid_t aapl_id,
hid_t lapl_id)
{
- H5A_t *attr = NULL; /* Attribute created */
- H5G_loc_t loc; /* Object location */
- H5T_t *type; /* Datatype to use for attribute */
- H5S_t *space; /* Dataspace to use for attribute */
+ void *attr = NULL; /* attr token from VOL connector */
+ H5VL_object_t *vol_obj = NULL; /* object token of loc_id */
+ H5VL_loc_params_t loc_params;
hid_t ret_value = H5I_INVALID_HID; /* Return value */
FUNC_ENTER_API(H5I_INVALID_HID)
@@ -346,18 +349,14 @@ H5Acreate_by_name(hid_t loc_id, const char *obj_name, const char *attr_name,
/* Check arguments */
if(H5I_ATTR == H5I_get_type(loc_id))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "location is not valid for an attribute")
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a location")
- if(0 == (H5F_INTENT(loc.oloc->file) & H5F_ACC_RDWR))
- HGOTO_ERROR(H5E_ARGS, H5E_WRITEERROR, H5I_INVALID_HID, "no write intent on file")
if(!obj_name || !*obj_name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "no object name")
if(!attr_name || !*attr_name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "no attribute name")
- if(NULL == (type = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a type")
- if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a dataspace")
+
+ /* Get correct property list */
+ if(H5P_DEFAULT == acpl_id)
+ acpl_id = H5P_ATTRIBUTE_CREATE_DEFAULT;
/* Verify access property list and set up collective metadata if appropriate */
if(H5CX_set_apl(&aapl_id, H5P_CLS_AACC, loc_id, TRUE) < 0)
@@ -369,18 +368,28 @@ H5Acreate_by_name(hid_t loc_id, const char *obj_name, const char *attr_name,
H5CX_set_lapl(lapl_id);
}
+ /* Set up location struct */
+ loc_params.type = H5VL_OBJECT_BY_NAME;
+ loc_params.obj_type = H5I_get_type(loc_id);
+ loc_params.loc_data.loc_by_name.name = obj_name;
+ loc_params.loc_data.loc_by_name.lapl_id = lapl_id;
+
+ /* Get the location object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier")
+
/* Create the attribute */
- if(NULL == (attr = H5A__create_by_name(&loc, obj_name, attr_name, type, space, acpl_id)))
+ if(NULL == (attr = H5VL_attr_create(vol_obj, &loc_params, attr_name, type_id, space_id, acpl_id, aapl_id, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, H5I_INVALID_HID, "unable to create attribute")
/* Register the new attribute and get an ID for it */
- if((ret_value = H5I_register(H5I_ATTR, attr, TRUE)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to atomize attribute handle")
+ if((ret_value = H5VL_register(H5I_ATTR, attr, vol_obj->connector, TRUE)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to atomize attribute handle")
done:
/* Cleanup on failure */
if(H5I_INVALID_HID == ret_value)
- if(attr && H5A__close(attr) < 0)
+ if(attr && H5VL_attr_close(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, H5I_INVALID_HID, "can't close attribute")
FUNC_LEAVE_API(ret_value)
@@ -409,8 +418,9 @@ done:
hid_t
H5Aopen(hid_t loc_id, const char *attr_name, hid_t aapl_id)
{
- H5G_loc_t loc; /* Object location */
- H5A_t *attr = NULL; /* Attribute opened */
+ void *attr = NULL; /* attr token from VOL connector */
+ H5VL_object_t *vol_obj = NULL; /* object token of loc_id */
+ H5VL_loc_params_t loc_params;
hid_t ret_value = H5I_INVALID_HID;
FUNC_ENTER_API(H5I_INVALID_HID)
@@ -419,8 +429,6 @@ H5Aopen(hid_t loc_id, const char *attr_name, hid_t aapl_id)
/* Check arguments */
if(H5I_ATTR == H5I_get_type(loc_id))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "location is not valid for an attribute")
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a location")
if(!attr_name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "name parameter cannot be NULL")
if(!*attr_name)
@@ -430,18 +438,26 @@ H5Aopen(hid_t loc_id, const char *attr_name, hid_t aapl_id)
if(H5CX_set_apl(&aapl_id, H5P_CLS_AACC, loc_id, FALSE) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info")
+ /* Set location struct fields */
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* Get the location object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier")
+
/* Open the attribute */
- if(NULL == (attr = H5A__open(&loc, attr_name)))
+ if(NULL == (attr = H5VL_attr_open(vol_obj, &loc_params, attr_name, aapl_id, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open attribute: '%s'", attr_name)
/* Register the attribute and get an ID for it */
- if((ret_value = H5I_register(H5I_ATTR, attr, TRUE)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to atomize attribute handle")
+ if((ret_value = H5VL_register(H5I_ATTR, attr, vol_obj->connector, TRUE)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to atomize attribute handle")
done:
/* Cleanup on failure */
if(H5I_INVALID_HID == ret_value)
- if(attr && H5A__close(attr) < 0)
+ if(attr && H5VL_attr_close(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, H5I_INVALID_HID, "can't close attribute")
FUNC_LEAVE_API(ret_value)
@@ -473,8 +489,9 @@ hid_t
H5Aopen_by_name(hid_t loc_id, const char *obj_name, const char *attr_name,
hid_t aapl_id, hid_t lapl_id)
{
- H5G_loc_t loc; /* Object location */
- H5A_t *attr = NULL; /* Attribute opened */
+ void *attr = NULL; /* attr token from VOL connector */
+ H5VL_object_t *vol_obj = NULL; /* object token of loc_id */
+ H5VL_loc_params_t loc_params;
hid_t ret_value = H5I_INVALID_HID;
FUNC_ENTER_API(H5I_INVALID_HID)
@@ -483,8 +500,6 @@ H5Aopen_by_name(hid_t loc_id, const char *obj_name, const char *attr_name,
/* Check arguments */
if(H5I_ATTR == H5I_get_type(loc_id))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "location is not valid for an attribute")
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a location")
if(!obj_name || !*obj_name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "no object name")
if(!attr_name || !*attr_name)
@@ -500,19 +515,31 @@ H5Aopen_by_name(hid_t loc_id, const char *obj_name, const char *attr_name,
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not link access property list ID")
H5CX_set_lapl(lapl_id);
}
+ else
+ lapl_id = H5P_LINK_ACCESS_DEFAULT;
+
+ /* Fill in location struct fields */
+ loc_params.type = H5VL_OBJECT_BY_NAME;
+ loc_params.loc_data.loc_by_name.name = obj_name;
+ loc_params.loc_data.loc_by_name.lapl_id = lapl_id;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* Get the location object */
+ if (NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier")
/* Open the attribute */
- if(NULL == (attr = H5A__open_by_name(&loc, obj_name, attr_name)))
+ if(NULL == (attr = H5VL_attr_open(vol_obj, &loc_params, attr_name, aapl_id, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, H5I_INVALID_HID, "can't open attribute")
/* Register the attribute and get an ID for it */
- if((ret_value = H5I_register(H5I_ATTR, attr, TRUE)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to atomize attribute handle")
+ if((ret_value = H5VL_register(H5I_ATTR, attr, vol_obj->connector, TRUE)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to atomize attribute handle")
done:
/* Cleanup on failure */
if(H5I_INVALID_HID == ret_value)
- if(attr && H5A__close(attr) < 0)
+ if(attr && H5VL_attr_close(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, H5I_INVALID_HID, "can't close attribute")
FUNC_LEAVE_API(ret_value)
@@ -547,8 +574,9 @@ hid_t
H5Aopen_by_idx(hid_t loc_id, const char *obj_name, H5_index_t idx_type,
H5_iter_order_t order, hsize_t n, hid_t aapl_id, hid_t lapl_id)
{
- H5A_t *attr = NULL; /* Attribute opened */
- H5G_loc_t loc; /* Object location */
+ void *attr = NULL; /* Attribute opened */
+ H5VL_object_t *vol_obj = NULL; /* object token of loc_id */
+ H5VL_loc_params_t loc_params;
hid_t ret_value = H5I_INVALID_HID; /* Return value */
FUNC_ENTER_API(H5I_INVALID_HID)
@@ -558,8 +586,6 @@ H5Aopen_by_idx(hid_t loc_id, const char *obj_name, H5_index_t idx_type,
/* Check arguments */
if(H5I_ATTR == H5I_get_type(loc_id))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "location is not valid for an attribute")
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a location")
if(!obj_name || !*obj_name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "no object name")
if(idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N)
@@ -577,19 +603,34 @@ H5Aopen_by_idx(hid_t loc_id, const char *obj_name, H5_index_t idx_type,
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not link access property list ID")
H5CX_set_lapl(lapl_id);
}
+ else
+ lapl_id = H5P_LINK_ACCESS_DEFAULT;
+
+ /* Fill in location struct parameters */
+ loc_params.type = H5VL_OBJECT_BY_IDX;
+ loc_params.loc_data.loc_by_idx.name = obj_name;
+ loc_params.loc_data.loc_by_idx.idx_type = idx_type;
+ loc_params.loc_data.loc_by_idx.order = order;
+ loc_params.loc_data.loc_by_idx.n = n;
+ loc_params.loc_data.loc_by_idx.lapl_id = lapl_id;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* Get the location object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier")
/* Open the attribute */
- if(NULL == (attr = H5A__open_by_idx(&loc, obj_name, idx_type, order, n)))
+ if(NULL == (attr = H5VL_attr_open(vol_obj, &loc_params, NULL, aapl_id, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open attribute")
/* Register the attribute and get an ID for it */
- if((ret_value = H5I_register(H5I_ATTR, attr, TRUE)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to atomize attribute handle")
+ if((ret_value = H5VL_register(H5I_ATTR, attr, vol_obj->connector, TRUE)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to atomize attribute handle")
done:
/* Cleanup on failure */
if(H5I_INVALID_HID == ret_value)
- if(attr && H5A__close(attr) < 0)
+ if(attr && H5VL_attr_close(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, H5I_INVALID_HID, "can't close attribute")
FUNC_LEAVE_API(ret_value)
@@ -615,17 +656,16 @@ done:
herr_t
H5Awrite(hid_t attr_id, hid_t dtype_id, const void *buf)
{
- H5A_t *attr; /* Attribute object for ID */
- H5T_t *mem_type; /* Memory datatype */
+ H5VL_object_t *vol_obj; /* Attribute object for ID */
herr_t ret_value; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE3("e", "ii*x", attr_id, dtype_id, buf);
/* Check arguments */
- if(NULL == (attr = (H5A_t *)H5I_object_verify(attr_id, H5I_ATTR)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(attr_id, H5I_ATTR)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an attribute")
- if(NULL == (mem_type = (H5T_t *)H5I_object_verify(dtype_id, H5I_DATATYPE)))
+ if(H5I_DATATYPE != H5I_get_type(dtype_id))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
if(NULL == buf)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "buf parameter can't be NULL")
@@ -635,7 +675,7 @@ H5Awrite(hid_t attr_id, hid_t dtype_id, const void *buf)
HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set collective metadata read")
/* Write the attribute data */
- if((ret_value = H5A__write(attr, mem_type, buf)) < 0)
+ if((ret_value = H5VL_attr_write(vol_obj, dtype_id, buf, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_WRITEERROR, FAIL, "unable to write attribute")
done:
@@ -662,23 +702,22 @@ done:
herr_t
H5Aread(hid_t attr_id, hid_t dtype_id, void *buf)
{
- H5A_t *attr; /* Attribute object for ID */
- H5T_t *mem_type; /* Memory datatype */
+ H5VL_object_t *vol_obj; /* Attribute object for ID */
herr_t ret_value; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE3("e", "ii*x", attr_id, dtype_id, buf);
/* Check arguments */
- if(NULL == (attr = (H5A_t *)H5I_object_verify(attr_id, H5I_ATTR)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(attr_id, H5I_ATTR)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an attribute")
- if(NULL == (mem_type = (H5T_t *)H5I_object_verify(dtype_id, H5I_DATATYPE)))
+ if(H5I_DATATYPE != H5I_get_type(dtype_id))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
if(NULL == buf)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "buf parameter can't be NULL")
/* Read the attribute data */
- if((ret_value = H5A__read(attr, mem_type, buf)) < 0)
+ if((ret_value = H5VL_attr_read(vol_obj, dtype_id, buf, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_READERROR, FAIL, "unable to read attribute")
done:
@@ -705,18 +744,18 @@ done:
hid_t
H5Aget_space(hid_t attr_id)
{
- H5A_t *attr = NULL; /* Attribute object for ID */
+ H5VL_object_t *vol_obj = NULL; /* Attribute object for ID */
hid_t ret_value = H5I_INVALID_HID; /* Return value */
FUNC_ENTER_API(H5I_INVALID_HID)
H5TRACE1("i", "i", attr_id);
/* Check arguments */
- if(NULL == (attr = (H5A_t *)H5I_object_verify(attr_id, H5I_ATTR)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(attr_id, H5I_ATTR)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not an attribute")
/* Get the dataspace */
- if((ret_value = H5A_get_space(attr)) < 0)
+ if(H5VL_attr_get(vol_obj, H5VL_ATTR_GET_SPACE, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &ret_value) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, H5I_INVALID_HID, "unable to get dataspace of attribute")
done:
@@ -743,18 +782,18 @@ done:
hid_t
H5Aget_type(hid_t attr_id)
{
- H5A_t *attr = NULL; /* Attribute object for ID */
+ H5VL_object_t *vol_obj = NULL; /* Attribute object for ID */
hid_t ret_value = H5I_INVALID_HID; /* Return value */
FUNC_ENTER_API(H5I_INVALID_HID)
H5TRACE1("i", "i", attr_id);
/* Check arguments */
- if(NULL == (attr = (H5A_t *)H5I_object_verify(attr_id, H5I_ATTR)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(attr_id, H5I_ATTR)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not an attribute")
/* Get the datatype */
- if((ret_value = H5A__get_type(attr)) < 0)
+ if(H5VL_attr_get(vol_obj, H5VL_ATTR_GET_TYPE, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &ret_value) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, H5I_INVALID_HID, "unable to get datatype of attribute")
done:
@@ -784,7 +823,7 @@ done:
hid_t
H5Aget_create_plist(hid_t attr_id)
{
- H5A_t *attr = NULL; /* Attribute object for ID */
+ H5VL_object_t *vol_obj = NULL; /* Attribute object for ID */
hid_t ret_value = H5I_INVALID_HID; /* Return value */
FUNC_ENTER_API(H5I_INVALID_HID)
@@ -793,11 +832,11 @@ H5Aget_create_plist(hid_t attr_id)
HDassert(H5P_LST_ATTRIBUTE_CREATE_ID_g != -1);
/* Check arguments */
- if(NULL == (attr = (H5A_t *)H5I_object_verify(attr_id, H5I_ATTR)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(attr_id, H5I_ATTR)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not an attribute")
/* Get the acpl */
- if((ret_value = H5A__get_create_plist(attr)) < 0)
+ if(H5VL_attr_get(vol_obj, H5VL_ATTR_GET_ACPL, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &ret_value) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, H5I_INVALID_HID, "unable to get creation property list for attribute")
done:
@@ -829,20 +868,25 @@ done:
ssize_t
H5Aget_name(hid_t attr_id, size_t buf_size, char *buf)
{
- H5A_t *attr = NULL; /* Attribute object for ID */
+ H5VL_object_t *vol_obj = NULL; /* Attribute object for ID */
+ H5VL_loc_params_t loc_params;
ssize_t ret_value = -1;
FUNC_ENTER_API((-1))
H5TRACE3("Zs", "iz*s", attr_id, buf_size, buf);
/* check arguments */
- if(NULL == (attr = (H5A_t *)H5I_object_verify(attr_id, H5I_ATTR)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(attr_id, H5I_ATTR)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "not an attribute")
if(!buf && buf_size)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, (-1), "buf cannot be NULL if buf_size is non-zero")
+ /* Set location struct parameters */
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(attr_id);
+
/* Get the attribute name */
- if((ret_value = H5A__get_name(attr, buf_size, buf)) < 0)
+ if(H5VL_attr_get(vol_obj, H5VL_ATTR_GET_NAME, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &loc_params, buf_size, buf, &ret_value) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, (-1), "unable to get attribute name")
done:
@@ -872,8 +916,8 @@ H5Aget_name_by_idx(hid_t loc_id, const char *obj_name, H5_index_t idx_type,
H5_iter_order_t order, hsize_t n, char *name /*out*/, size_t size,
hid_t lapl_id)
{
- H5G_loc_t loc; /* Object location */
- H5A_t *attr = NULL; /* Attribute object for name */
+ H5VL_object_t *vol_obj;
+ H5VL_loc_params_t loc_params;
ssize_t ret_value; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -883,10 +927,10 @@ H5Aget_name_by_idx(hid_t loc_id, const char *obj_name, H5_index_t idx_type,
/* Check args */
if(H5I_ATTR == H5I_get_type(loc_id))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute")
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!obj_name || !*obj_name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name")
+ if(!name && size)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "name cannot be NULL if size is non-zero")
if(idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index type specified")
if(order <= H5_ITER_UNKNOWN || order >= H5_ITER_N)
@@ -896,25 +940,23 @@ H5Aget_name_by_idx(hid_t loc_id, const char *obj_name, H5_index_t idx_type,
if(H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, FALSE) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set access property list info")
- /* Open the attribute on the object header */
- if(NULL == (attr = H5A__open_by_idx(&loc, obj_name, idx_type, order, n)))
- HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "can't open attribute")
+ /* Get the object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier")
- /* Get the length of the name */
- ret_value = (ssize_t)HDstrlen(attr->shared->name);
+ loc_params.type = H5VL_OBJECT_BY_IDX;
+ loc_params.loc_data.loc_by_idx.name = obj_name;
+ loc_params.loc_data.loc_by_idx.idx_type = idx_type;
+ loc_params.loc_data.loc_by_idx.order = order;
+ loc_params.loc_data.loc_by_idx.n = n;
+ loc_params.loc_data.loc_by_idx.lapl_id = lapl_id;
+ loc_params.obj_type = H5I_get_type(loc_id);
- /* Get the name and store in the user's buffer */
- if(name) {
- HDstrncpy(name, attr->shared->name, MIN((size_t)(ret_value + 1), size));
- if((size_t)ret_value >= size)
- name[size - 1]='\0';
- }
+ /* Get the name */
+ if(H5VL_attr_get(vol_obj, H5VL_ATTR_GET_NAME, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &loc_params, size, name, &ret_value) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "unable to get name")
done:
- /* Release resources */
- if(attr && H5A__close(attr) < 0)
- HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "can't close attribute")
-
FUNC_LEAVE_API(ret_value)
} /* end H5Aget_name_by_idx() */
@@ -939,18 +981,19 @@ done:
hsize_t
H5Aget_storage_size(hid_t attr_id)
{
- H5A_t *attr; /* Attribute object for ID */
+ H5VL_object_t *vol_obj;
hsize_t ret_value; /* Return value */
FUNC_ENTER_API(0)
H5TRACE1("h", "i", attr_id);
/* Check arguments */
- if(NULL == (attr = (H5A_t *)H5I_object_verify(attr_id, H5I_ATTR)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(attr_id, H5I_ATTR)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not an attribute")
/* Get the storage size */
- ret_value = attr->shared->data_size;
+ if(H5VL_attr_get(vol_obj, H5VL_ATTR_GET_STORAGE_SIZE, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &ret_value) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, 0, "unable to get acpl")
done:
FUNC_LEAVE_API(ret_value)
@@ -973,18 +1016,24 @@ done:
herr_t
H5Aget_info(hid_t attr_id, H5A_info_t *ainfo)
{
- H5A_t *attr; /* Attribute object for name */
+ H5VL_object_t *vol_obj;
+ H5VL_loc_params_t loc_params;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE2("e", "i*x", attr_id, ainfo);
/* Check arguments */
- if(NULL == (attr = (H5A_t *)H5I_object_verify(attr_id, H5I_ATTR)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(attr_id, H5I_ATTR)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an attribute")
+ if(!ainfo)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "attribute_info parameter cannot be NULL")
+
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(attr_id);
/* Get the attribute information */
- if(H5A__get_info(attr, ainfo) < 0)
+ if(H5VL_attr_get(vol_obj, H5VL_ATTR_GET_INFO, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &loc_params, ainfo) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "unable to get attribute info")
done:
@@ -1009,8 +1058,8 @@ herr_t
H5Aget_info_by_name(hid_t loc_id, const char *obj_name, const char *attr_name,
H5A_info_t *ainfo, hid_t lapl_id)
{
- H5G_loc_t loc; /* Object location */
- H5A_t *attr = NULL; /* Attribute object for name */
+ H5VL_object_t *vol_obj;
+ H5VL_loc_params_t loc_params;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -1019,8 +1068,6 @@ H5Aget_info_by_name(hid_t loc_id, const char *obj_name, const char *attr_name,
/* Check args */
if(H5I_ATTR == H5I_get_type(loc_id))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute")
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!obj_name || !*obj_name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no object name")
if(!attr_name || !*attr_name)
@@ -1032,19 +1079,20 @@ H5Aget_info_by_name(hid_t loc_id, const char *obj_name, const char *attr_name,
if(H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, FALSE) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set access property list info")
- /* Open the attribute on the object header */
- if(NULL == (attr = H5A__open_by_name(&loc, obj_name, attr_name)))
- HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "can't open attribute")
+ loc_params.type = H5VL_OBJECT_BY_NAME;
+ loc_params.loc_data.loc_by_name.name = obj_name;
+ loc_params.loc_data.loc_by_name.lapl_id = lapl_id;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* Get the object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier")
/* Get the attribute information */
- if(H5A__get_info(attr, ainfo) < 0)
+ if(H5VL_attr_get(vol_obj, H5VL_ATTR_GET_INFO, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &loc_params, ainfo, attr_name) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "unable to get attribute info")
done:
- /* Release resources */
- if(attr && H5A__close(attr) < 0)
- HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "can't close attribute")
-
FUNC_LEAVE_API(ret_value)
} /* end H5Aget_info_by_name() */
@@ -1067,8 +1115,8 @@ herr_t
H5Aget_info_by_idx(hid_t loc_id, const char *obj_name, H5_index_t idx_type,
H5_iter_order_t order, hsize_t n, H5A_info_t *ainfo, hid_t lapl_id)
{
- H5G_loc_t loc; /* Object location */
- H5A_t *attr = NULL; /* Attribute object for name */
+ H5VL_object_t *vol_obj;
+ H5VL_loc_params_t loc_params;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -1078,8 +1126,6 @@ H5Aget_info_by_idx(hid_t loc_id, const char *obj_name, H5_index_t idx_type,
/* Check args */
if(H5I_ATTR == H5I_get_type(loc_id))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute")
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!obj_name || !*obj_name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name")
if(idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N)
@@ -1093,19 +1139,23 @@ H5Aget_info_by_idx(hid_t loc_id, const char *obj_name, H5_index_t idx_type,
if(H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, FALSE) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set access property list info")
- /* Open the attribute on the object header */
- if(NULL == (attr = H5A__open_by_idx(&loc, obj_name, idx_type, order, n)))
- HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "can't open attribute")
+ loc_params.type = H5VL_OBJECT_BY_IDX;
+ loc_params.loc_data.loc_by_idx.name = obj_name;
+ loc_params.loc_data.loc_by_idx.idx_type = idx_type;
+ loc_params.loc_data.loc_by_idx.order = order;
+ loc_params.loc_data.loc_by_idx.n = n;
+ loc_params.loc_data.loc_by_idx.lapl_id = lapl_id;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* Get the object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier")
/* Get the attribute information */
- if(H5A__get_info(attr, ainfo) < 0)
+ if(H5VL_attr_get(vol_obj, H5VL_ATTR_GET_INFO, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &loc_params, ainfo) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "unable to get attribute info")
done:
- /* Release resources */
- if(attr && H5A__close(attr) < 0)
- HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "can't close attribute")
-
FUNC_LEAVE_API(ret_value)
} /* end H5Aget_info_by_idx() */
@@ -1131,16 +1181,27 @@ H5Arename(hid_t loc_id, const char *old_name, const char *new_name)
H5TRACE3("e", "i*s*s", loc_id, old_name, new_name);
/* check arguments */
- if(!old_name || !new_name)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "name is nil")
if(H5I_ATTR == H5I_get_type(loc_id))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute")
+ if(!old_name)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "old attribute name cannot be NULL")
+ if(!*old_name)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "old attribute name cannot be an empty string")
+ if(!new_name)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "new attribute name cannot be NULL")
+ if(!*new_name)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "new attribute name cannot be an empty string")
/* Avoid thrashing things if the names are the same */
if(HDstrcmp(old_name, new_name)) {
- H5G_loc_t loc; /* Object location */
-
- if(H5G_loc(loc_id, &loc) < 0)
+ H5VL_object_t *vol_obj;
+ H5VL_loc_params_t loc_params;
+
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* Get the location object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
/* Set up collective metadata if appropriate */
@@ -1148,9 +1209,9 @@ H5Arename(hid_t loc_id, const char *old_name, const char *new_name)
HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set collective metadata read")
/* Rename the attribute */
- if(H5O__attr_rename(loc.oloc, old_name, new_name) < 0)
+ if(H5VL_attr_specific(vol_obj, &loc_params, H5VL_ATTR_RENAME, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, old_name, new_name) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTRENAME, FAIL, "can't rename attribute")
- }
+ } /* end if */
done:
FUNC_LEAVE_API(ret_value)
@@ -1191,20 +1252,26 @@ H5Arename_by_name(hid_t loc_id, const char *obj_name, const char *old_attr_name,
/* Avoid thrashing things if the names are the same */
if(HDstrcmp(old_attr_name, new_attr_name)) {
- H5G_loc_t loc; /* Object location */
+ H5VL_object_t *vol_obj;
+ H5VL_loc_params_t loc_params;
/* Verify access property list and set up collective metadata if appropriate */
if(H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, TRUE) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set access property list info")
+ loc_params.type = H5VL_OBJECT_BY_NAME;
+ loc_params.loc_data.loc_by_name.name = obj_name;
+ loc_params.loc_data.loc_by_name.lapl_id = lapl_id;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
/* Get the location object */
- if(H5G_loc(loc_id, &loc) < 0)
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
/* Rename the attribute */
- if(H5A__rename_by_name(loc, obj_name, old_attr_name, new_attr_name) < 0)
+ if(H5VL_attr_specific(vol_obj, &loc_params, H5VL_ATTR_RENAME, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, old_attr_name, new_attr_name) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTRENAME, FAIL, "can't rename attribute")
- }
+ } /* end if */
done:
FUNC_LEAVE_API(ret_value)
@@ -1256,6 +1323,8 @@ herr_t
H5Aiterate2(hid_t loc_id, H5_index_t idx_type, H5_iter_order_t order,
hsize_t *idx, H5A_operator2_t op, void *op_data)
{
+ H5VL_object_t *vol_obj = NULL; /* object token of loc_id */
+ H5VL_loc_params_t loc_params;
herr_t ret_value; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -1269,9 +1338,16 @@ H5Aiterate2(hid_t loc_id, H5_index_t idx_type, H5_iter_order_t order,
if(order <= H5_ITER_UNKNOWN || order >= H5_ITER_N)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid iteration order specified")
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* get the loc object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
/* Iterate over attributes */
- if((ret_value = H5A__iterate(loc_id, idx_type, order, idx, op, op_data)) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_BADITER, FAIL, "error iterating over attributes")
+ if((ret_value = H5VL_attr_specific(vol_obj, &loc_params, H5VL_ATTR_ITER, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, (int)idx_type, (int)order, idx, op, op_data)) < 0)
+ HERROR(H5E_ATTR, H5E_BADITER, "error iterating over attributes");
done:
FUNC_LEAVE_API(ret_value)
@@ -1326,7 +1402,8 @@ H5Aiterate_by_name(hid_t loc_id, const char *obj_name, H5_index_t idx_type,
H5_iter_order_t order, hsize_t *idx, H5A_operator2_t op, void *op_data,
hid_t lapl_id)
{
- H5G_loc_t loc; /* Object location */
+ H5VL_object_t *vol_obj = NULL; /* object token of loc_id */
+ H5VL_loc_params_t loc_params;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -1336,8 +1413,6 @@ H5Aiterate_by_name(hid_t loc_id, const char *obj_name, H5_index_t idx_type,
/* check arguments */
if(H5I_ATTR == H5I_get_type(loc_id))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute")
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!obj_name || !*obj_name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no object name")
if(idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N)
@@ -1349,9 +1424,18 @@ H5Aiterate_by_name(hid_t loc_id, const char *obj_name, H5_index_t idx_type,
if(H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, FALSE) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set access property list info")
+ loc_params.type = H5VL_OBJECT_BY_NAME;
+ loc_params.obj_type = H5I_get_type(loc_id);
+ loc_params.loc_data.loc_by_name.name = obj_name;
+ loc_params.loc_data.loc_by_name.lapl_id = lapl_id;
+
+ /* get the loc object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
/* Iterate over attributes */
- if((ret_value = H5A__iterate_by_name(&loc, obj_name, idx_type, order, idx, op, op_data)) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_BADITER, FAIL, "attribute iteration failed");
+ if((ret_value = H5VL_attr_specific(vol_obj, &loc_params, H5VL_ATTR_ITER, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, (int)idx_type, (int)order, idx, op, op_data)) < 0)
+ HERROR(H5E_ATTR, H5E_BADITER, "attribute iteration failed");
done:
FUNC_LEAVE_API(ret_value)
@@ -1375,7 +1459,8 @@ done:
herr_t
H5Adelete(hid_t loc_id, const char *name)
{
- H5G_loc_t loc; /* Object location */
+ H5VL_object_t *vol_obj = NULL;
+ H5VL_loc_params_t loc_params;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -1384,8 +1469,6 @@ H5Adelete(hid_t loc_id, const char *name)
/* Check arguments */
if(H5I_ATTR == H5I_get_type(loc_id))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute")
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "name parameter cannot be NULL")
if(!*name)
@@ -1395,8 +1478,16 @@ H5Adelete(hid_t loc_id, const char *name)
if(H5CX_set_loc(loc_id) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set collective metadata read")
+ /* Fill in location struct fields */
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* Get the object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier")
+
/* Delete the attribute */
- if(H5O__attr_remove(loc.oloc, name) < 0)
+ if(H5VL_attr_specific(vol_obj, &loc_params, H5VL_ATTR_DELETE, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, name) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute")
done:
@@ -1424,7 +1515,8 @@ herr_t
H5Adelete_by_name(hid_t loc_id, const char *obj_name, const char *attr_name,
hid_t lapl_id)
{
- H5G_loc_t loc; /* Object location */
+ H5VL_object_t *vol_obj;
+ H5VL_loc_params_t loc_params;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -1433,8 +1525,6 @@ H5Adelete_by_name(hid_t loc_id, const char *obj_name, const char *attr_name,
/* Check arguments */
if(H5I_ATTR == H5I_get_type(loc_id))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute")
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!obj_name || !*obj_name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no object name")
if(!attr_name || !*attr_name)
@@ -1444,8 +1534,18 @@ H5Adelete_by_name(hid_t loc_id, const char *obj_name, const char *attr_name,
if(H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, TRUE) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set access property list info")
+ /* Fill in location struct fields */
+ loc_params.type = H5VL_OBJECT_BY_NAME;
+ loc_params.loc_data.loc_by_name.name = obj_name;
+ loc_params.loc_data.loc_by_name.lapl_id = lapl_id;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* Get the object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier")
+
/* Delete the attribute */
- if(H5A__delete_by_name(&loc, obj_name, attr_name) < 0)
+ if(H5VL_attr_specific(vol_obj, &loc_params, H5VL_ATTR_DELETE, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, attr_name) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute")
done:
@@ -1481,7 +1581,8 @@ herr_t
H5Adelete_by_idx(hid_t loc_id, const char *obj_name, H5_index_t idx_type,
H5_iter_order_t order, hsize_t n, hid_t lapl_id)
{
- H5G_loc_t loc; /* Object location */
+ H5VL_object_t *vol_obj;
+ H5VL_loc_params_t loc_params;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -1490,8 +1591,6 @@ H5Adelete_by_idx(hid_t loc_id, const char *obj_name, H5_index_t idx_type,
/* check arguments */
if(H5I_ATTR == H5I_get_type(loc_id))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute")
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!obj_name || !*obj_name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no object name")
if(idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N)
@@ -1503,8 +1602,20 @@ H5Adelete_by_idx(hid_t loc_id, const char *obj_name, H5_index_t idx_type,
if(H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, TRUE) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set access property list info")
- /* Delete the attribute from the location */
- if(H5A__delete_by_idx(&loc, obj_name, idx_type, order, n) < 0)
+ loc_params.type = H5VL_OBJECT_BY_IDX;
+ loc_params.loc_data.loc_by_idx.name = obj_name;
+ loc_params.loc_data.loc_by_idx.idx_type = idx_type;
+ loc_params.loc_data.loc_by_idx.order = order;
+ loc_params.loc_data.loc_by_idx.n = n;
+ loc_params.loc_data.loc_by_idx.lapl_id = lapl_id;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* get the object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier")
+
+ /* Delete the attribute through the VOL */
+ if(H5VL_attr_specific(vol_obj, &loc_params, H5VL_ATTR_DELETE, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, NULL) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute")
done:
@@ -1561,7 +1672,8 @@ done:
htri_t
H5Aexists(hid_t obj_id, const char *attr_name)
{
- H5G_loc_t loc; /* Object location */
+ H5VL_object_t *vol_obj;
+ H5VL_loc_params_t loc_params;
htri_t ret_value; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -1570,13 +1682,18 @@ H5Aexists(hid_t obj_id, const char *attr_name)
/* Check arguments */
if(H5I_ATTR == H5I_get_type(obj_id))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute")
- if(H5G_loc(obj_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!attr_name || !*attr_name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no attribute name")
+ /* get the object */
+ if(NULL == (vol_obj = H5VL_vol_object(obj_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier")
+
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(obj_id);
+
/* Check if the attribute exists */
- if((ret_value = H5O__attr_exists(loc.oloc, attr_name)) < 0)
+ if(H5VL_attr_specific(vol_obj, &loc_params, H5VL_ATTR_EXISTS, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, attr_name, &ret_value) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "unable to determine if attribute exists")
done:
@@ -1601,7 +1718,8 @@ htri_t
H5Aexists_by_name(hid_t loc_id, const char *obj_name, const char *attr_name,
hid_t lapl_id)
{
- H5G_loc_t loc; /* Object location */
+ H5VL_object_t *vol_obj;
+ H5VL_loc_params_t loc_params;
htri_t ret_value; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -1610,8 +1728,6 @@ H5Aexists_by_name(hid_t loc_id, const char *obj_name, const char *attr_name,
/* check arguments */
if(H5I_ATTR == H5I_get_type(loc_id))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute")
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!obj_name || !*obj_name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no object name")
if(!attr_name || !*attr_name)
@@ -1621,8 +1737,17 @@ H5Aexists_by_name(hid_t loc_id, const char *obj_name, const char *attr_name,
if(H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, FALSE) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set access property list info")
+ /* get the object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier")
+
+ loc_params.type = H5VL_OBJECT_BY_NAME;
+ loc_params.loc_data.loc_by_name.name = obj_name;
+ loc_params.loc_data.loc_by_name.lapl_id = lapl_id;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
/* Check existence of attribute */
- if((ret_value = H5A__exists_by_name(loc, obj_name, attr_name)) < 0)
+ if(H5VL_attr_specific(vol_obj, &loc_params, H5VL_ATTR_EXISTS, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, attr_name, &ret_value) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "unable to determine if attribute exists")
done:
diff --git a/src/H5AC.c b/src/H5AC.c
index 34b9e1b..a3b35a4 100644
--- a/src/H5AC.c
+++ b/src/H5AC.c
@@ -30,22 +30,24 @@
/****************/
#include "H5ACmodule.h" /* This source code file is part of the H5AC module */
-#define H5F_FRIEND /* Suppress error about including H5Fpkg */
+#define H5C_FRIEND /* Suppress error about including H5Cpkg */
+#define H5F_FRIEND /* Suppress error about including H5Fpkg */
/***********/
/* Headers */
/***********/
-#include "H5private.h" /* Generic Functions */
-#include "H5ACpkg.h" /* Metadata cache */
-#include "H5Cprivate.h" /* Cache */
-#include "H5CXprivate.h" /* API Contexts */
-#include "H5Eprivate.h" /* Error handling */
-#include "H5Fpkg.h" /* Files */
-#include "H5FDprivate.h" /* File drivers */
-#include "H5Iprivate.h" /* IDs */
-#include "H5Pprivate.h" /* Property lists */
-#include "H5SLprivate.h" /* Skip Lists */
+#include "H5private.h" /* Generic Functions */
+#include "H5ACpkg.h" /* Metadata cache */
+#include "H5Clog.h" /* Cache logging */
+#include "H5Cpkg.h" /* Cache */
+#include "H5CXprivate.h" /* API Contexts */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fpkg.h" /* Files */
+#include "H5FDprivate.h" /* File drivers */
+#include "H5Iprivate.h" /* IDs */
+#include "H5Pprivate.h" /* Property lists */
+#include "H5SLprivate.h" /* Skip Lists */
/****************/
@@ -123,17 +125,14 @@ static const H5AC_class_t *const H5AC_class_s[] = {
H5AC_EARRAY_SBLOCK, /* (19) extensible array super block */
H5AC_EARRAY_DBLOCK, /* (20) extensible array data block */
H5AC_EARRAY_DBLK_PAGE, /* (21) extensible array data block page */
- H5AC_FARRAY_HDR, /* (22) fixed array header */
- H5AC_FARRAY_DBLOCK, /* (23) fixed array data block */
- H5AC_FARRAY_DBLK_PAGE, /* (24) fixed array data block page */
- H5AC_SUPERBLOCK, /* (25) file superblock */
- H5AC_DRVRINFO, /* (26) driver info block (supplements */
- /* superblock) */
- H5AC_EPOCH_MARKER, /* (27) epoch marker - always internal */
- /* to cache */
- H5AC_PROXY_ENTRY, /* (28) cache entry proxy */
- H5AC_PREFETCHED_ENTRY /* (29) prefetched entry - always */
- /* internal to cache */
+ H5AC_FARRAY_HDR, /* (22) fixed array header */
+ H5AC_FARRAY_DBLOCK, /* (23) fixed array data block */
+ H5AC_FARRAY_DBLK_PAGE, /* (24) fixed array data block page */
+ H5AC_SUPERBLOCK, /* (25) file superblock */
+ H5AC_DRVRINFO, /* (26) driver info block (supplements superblock) */
+ H5AC_EPOCH_MARKER, /* (27) epoch marker - always internal to cache */
+ H5AC_PROXY_ENTRY, /* (28) cache entry proxy */
+ H5AC_PREFETCHED_ENTRY /* (29) prefetched entry - always internal to cache */
};
@@ -183,13 +182,16 @@ H5AC__init_package(void)
#ifdef H5_HAVE_PARALLEL
/* check whether to enable strict collective function calling
- sanity checks using MPI barriers */
+ * sanity checks using MPI barriers
+ */
{
const char *s; /* String for environment variables */
s = HDgetenv("H5_COLL_API_SANITY_CHECK");
- if(s && HDisdigit(*s))
- H5_coll_api_sanity_check_g = (hbool_t)HDstrtol(s, NULL, 0);
+ if(s && HDisdigit(*s)) {
+ long env_val = HDstrtol(s, NULL, 0);
+ H5_coll_api_sanity_check_g = (0 == env_val) ? FALSE : TRUE;
+ }
}
#endif /* H5_HAVE_PARALLEL */
@@ -354,7 +356,7 @@ H5AC_create(const H5F_t *f, H5AC_cache_config_t *config_ptr, H5AC_cache_image_co
aux_ptr->sync_point_done = NULL;
aux_ptr->p0_image_len = 0;
- sprintf(prefix, "%d:", mpi_rank);
+ HDsprintf(prefix, "%d:", mpi_rank);
if(mpi_rank == 0) {
if(NULL == (aux_ptr->d_slist_ptr = H5SL_create(H5SL_TYPE_HADDR, NULL)))
@@ -413,15 +415,13 @@ H5AC_create(const H5F_t *f, H5AC_cache_config_t *config_ptr, H5AC_cache_image_co
HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "H5C_set_prefix() failed")
#endif /* H5_HAVE_PARALLEL */
- /* Turn on metadata cache logging, if being used */
- if(H5F_USE_MDC_LOGGING(f)) {
- if(H5C_set_up_logging(f->shared->cache, H5F_MDC_LOG_LOCATION(f), H5F_START_MDC_LOG_ON_ACCESS(f)) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTINIT, FAIL, "mdc logging setup failed")
-
- /* Write the log header regardless of current logging status */
- if(H5AC__write_create_cache_log_msg(f->shared->cache) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unable to emit log message")
- } /* end if */
+ /* Turn on metadata cache logging, if being used
+ * This will be JSON until we create a special API call. Trace output
+ * is generated when logging is controlled by the struct.
+ */
+ if(H5F_USE_MDC_LOGGING(f))
+ if(H5C_log_set_up(f->shared->cache, H5F_MDC_LOG_LOCATION(f), H5C_LOG_STYLE_JSON, H5F_START_MDC_LOG_ON_ACCESS(f)) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "mdc logging setup failed")
/* Configure the metadata cache for VFD SWMR reader operation if
* specified.
@@ -458,6 +458,11 @@ H5AC_create(const H5F_t *f, H5AC_cache_config_t *config_ptr, H5AC_cache_image_co
HGOTO_ERROR(H5E_CACHE, H5E_CANTSET, FAIL, "auto resize configuration failed")
done:
+ /* If currently logging, generate a message */
+ if(f->shared->cache->log_info->logging)
+ if(H5C_log_write_create_cache_msg(f->shared->cache, ret_value) < 0)
+ HDONE_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
#ifdef H5_HAVE_PARALLEL
/* if there is a failure, try to tidy up the auxiliary structure */
if(ret_value < 0) {
@@ -496,6 +501,8 @@ done:
herr_t
H5AC_dest(H5F_t *f)
{
+ hbool_t log_enabled; /* TRUE if logging was set up */
+ hbool_t curr_logging; /* TRUE if currently logging */
#ifdef H5_HAVE_PARALLEL
H5AC_aux_t * aux_ptr = NULL;
#endif /* H5_HAVE_PARALLEL */
@@ -513,18 +520,16 @@ H5AC_dest(H5F_t *f)
H5AC_stats(f);
#endif /* H5AC_DUMP_STATS_ON_CLOSE */
-#if H5AC__TRACE_FILE_ENABLED
- if(H5AC__close_trace_file(f->shared->cache) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5AC__close_trace_file() failed")
-#endif /* H5AC__TRACE_FILE_ENABLED */
-
- if(H5F_USE_MDC_LOGGING(f)) {
- /* Write the log footer regardless of current logging status */
- if(H5AC__write_destroy_cache_log_msg(f->shared->cache) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unable to emit log message")
- if(H5C_tear_down_logging(f->shared->cache) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "mdc logging tear-down failed")
- } /* end if */
+ /* Check if log messages are being emitted */
+ if(H5C_get_logging_status(f->shared->cache, &log_enabled, &curr_logging) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to get logging status")
+ if(log_enabled && curr_logging)
+ if(H5C_log_write_destroy_cache_msg(f->shared->cache) < 0)
+ HDONE_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+ /* Tear down logging */
+ if(log_enabled)
+ if(H5C_log_tear_down(f->shared->cache) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "mdc logging tear-down failed")
#ifdef H5_HAVE_PARALLEL
/* destroying the cache, so clear all collective entries */
@@ -592,8 +597,6 @@ done:
herr_t
H5AC_evict(H5F_t *f)
{
- hbool_t log_enabled; /* TRUE if logging was set up */
- hbool_t curr_logging; /* TRUE if currently logging */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
@@ -603,10 +606,6 @@ H5AC_evict(H5F_t *f)
HDassert(f->shared);
HDassert(f->shared->cache);
- /* Check if log messages are being emitted */
- if(H5C_get_logging_status(f->shared->cache, &log_enabled, &curr_logging) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unable to get logging status")
-
/* Evict all entries in the cache except the pinned superblock entry */
if(H5C_evict(f) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFREE, FAIL, "can't evict cache")
@@ -614,9 +613,9 @@ H5AC_evict(H5F_t *f)
done:
/* If currently logging, generate a message */
- if(curr_logging)
- if(H5AC__write_evict_cache_log_msg(f->shared->cache, ret_value) < 0)
- HDONE_ERROR(H5E_CACHE, H5E_LOGFAIL, FAIL, "unable to emit log message")
+ if(f->shared->cache->log_info->logging)
+ if(H5C_log_write_evict_cache_msg(f->shared->cache, ret_value) < 0)
+ HDONE_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
FUNC_LEAVE_NOAPI(ret_value)
} /* H5AC_evict() */
@@ -640,12 +639,6 @@ herr_t
H5AC_expunge_entry(H5F_t *f, const H5AC_class_t *type, haddr_t addr,
unsigned flags)
{
-#if H5AC__TRACE_FILE_ENABLED
- char trace[128] = "";
- FILE * trace_file_ptr = NULL;
-#endif /* H5AC__TRACE_FILE_ENABLED */
- hbool_t log_enabled; /* TRUE if logging was set up */
- hbool_t curr_logging; /* TRUE if currently logging */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
@@ -658,36 +651,14 @@ H5AC_expunge_entry(H5F_t *f, const H5AC_class_t *type, haddr_t addr,
HDassert(type->serialize);
HDassert(H5F_addr_defined(addr));
- /* Check if log messages are being emitted */
- if(H5C_get_logging_status(f->shared->cache, &log_enabled, &curr_logging) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unable to get logging status")
-
-#if H5AC__TRACE_FILE_ENABLED
-{
- H5AC_t * cache_ptr = f->shared->cache;
-
- /* For the expunge entry call, only the addr, and type id are really
- * necessary in the trace file. Write the return value to catch occult
- * errors.
- */
- if(NULL != (trace_file_ptr = H5C_get_trace_file_ptr(cache_ptr)))
- sprintf(trace, "%s 0x%lx %d", FUNC, (unsigned long)addr, (int)(type->id));
-}
-#endif /* H5AC__TRACE_FILE_ENABLED */
-
if(H5C_expunge_entry(f, type, addr, flags) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTEXPUNGE, FAIL, "H5C_expunge_entry() failed")
done:
-#if H5AC__TRACE_FILE_ENABLED
- if(trace_file_ptr != NULL)
- HDfprintf(trace_file_ptr, "%s %d\n", trace, (int)ret_value);
-#endif /* H5AC__TRACE_FILE_ENABLED */
-
/* If currently logging, generate a message */
- if(curr_logging)
- if(H5AC__write_expunge_entry_log_msg(f->shared->cache, addr, type->id, ret_value) < 0)
- HDONE_ERROR(H5E_CACHE, H5E_LOGFAIL, FAIL, "unable to emit log message")
+ if(f->shared->cache->log_info->logging)
+ if(H5C_log_write_expunge_entry_msg(f->shared->cache, addr, type->id, ret_value) < 0)
+ HDONE_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
FUNC_LEAVE_NOAPI(ret_value)
} /* H5AC_expunge_entry() */
@@ -716,12 +687,6 @@ done:
herr_t
H5AC_flush(H5F_t *f)
{
-#if H5AC__TRACE_FILE_ENABLED
- char trace[128] = "";
- FILE * trace_file_ptr = NULL;
-#endif /* H5AC__TRACE_FILE_ENABLED */
- hbool_t log_enabled; /* TRUE if logging was set up */
- hbool_t curr_logging; /* TRUE if currently logging */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
@@ -731,18 +696,6 @@ H5AC_flush(H5F_t *f)
HDassert(f->shared);
HDassert(f->shared->cache);
- /* Check if log messages are being emitted */
- if(H5C_get_logging_status(f->shared->cache, &log_enabled, &curr_logging) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unable to get logging status")
-
-#if H5AC__TRACE_FILE_ENABLED
- /* For the flush, only the flags are really necessary in the trace file.
- * Write the result to catch occult errors.
- */
- if(NULL != (trace_file_ptr = H5C_get_trace_file_ptr(cache_ptr)))
- sprintf(trace, "%s", FUNC);
-#endif /* H5AC__TRACE_FILE_ENABLED */
-
#ifdef H5_HAVE_PARALLEL
/* flushing the cache, so clear all collective entries */
if(H5C_clear_coll_entries(f->shared->cache, FALSE) < 0)
@@ -759,61 +712,16 @@ H5AC_flush(H5F_t *f)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't flush cache")
done:
-#if H5AC__TRACE_FILE_ENABLED
- if(trace_file_ptr != NULL)
- HDfprintf(trace_file_ptr, "%s %d\n", trace, (int)ret_value);
-#endif /* H5AC__TRACE_FILE_ENABLED */
-
/* If currently logging, generate a message */
- if(curr_logging)
- if(H5AC__write_flush_cache_log_msg(f->shared->cache, ret_value) < 0)
- HDONE_ERROR(H5E_CACHE, H5E_LOGFAIL, FAIL, "unable to emit log message")
+ if(f->shared->cache->log_info->logging)
+ if(H5C_log_write_flush_cache_msg(f->shared->cache, ret_value) < 0)
+ HDONE_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
FUNC_LEAVE_NOAPI(ret_value)
} /* H5AC_flush() */
/*-------------------------------------------------------------------------
- * Function: H5AC_force_cache_image_load()
- *
- * Purpose: On rare occasions, it is necessary to run
- * H5MF_tidy_self_referential_fsm_hack() prior to the first
- * metadata cache access. This is a problem as if there is a
- * cache image at the end of the file, that routine will
- * discard it.
- *
- * We solve this issue by calling this function, which will
- * load the cache image and then call
- * H5MF_tidy_self_referential_fsm_hack() to discard it.
- *
- * Return: SUCCEED on success, and FAIL on failure.
- *
- * Programmer: John Mainzer
- * 1/11/17
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5AC_force_cache_image_load(H5F_t *f)
-{
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(FAIL)
-
- /* Sanity checks */
- HDassert(f);
- HDassert(f->shared);
- HDassert(f->shared->cache);
-
- if(H5C_force_cache_image_load(f) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, FAIL, "Can't load cache image")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5AC_force_cache_image_load() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5AC_get_entry_status
*
* Purpose: Given a file address, determine whether the metadata
@@ -900,13 +808,6 @@ herr_t
H5AC_insert_entry(H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *thing,
unsigned int flags)
{
-#if H5AC__TRACE_FILE_ENABLED
- char trace[128] = "";
- size_t trace_entry_size = 0;
- FILE * trace_file_ptr = NULL;
-#endif /* H5AC__TRACE_FILE_ENABLED */
- hbool_t log_enabled; /* TRUE if logging was set up */
- hbool_t curr_logging; /* TRUE if currently logging */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
@@ -920,26 +821,9 @@ H5AC_insert_entry(H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *thing,
HDassert(H5F_addr_defined(addr));
HDassert(thing);
- /* Check if log messages are being emitted */
- if(H5C_get_logging_status(f->shared->cache, &log_enabled, &curr_logging) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unable to get logging status")
-
/* Check for invalid access request */
if(0 == (H5F_INTENT(f) & H5F_ACC_RDWR))
- HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "no write intent on file")
-
-#if H5AC__TRACE_FILE_ENABLED
- /* For the insert, only the addr, size, type id and flags are really
- * necessary in the trace file. Write the result to catch occult
- * errors.
- *
- * Note that some data is not available right now -- put what we can
- * in the trace buffer now, and fill in the rest at the end.
- */
- if(NULL != (trace_file_ptr = H5C_get_trace_file_ptr(cache_ptr)))
- sprintf(trace, "%s 0x%lx %d 0x%x", FUNC, (unsigned long)addr, type->id,
- flags);
-#endif /* H5AC__TRACE_FILE_ENABLED */
+ HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "no write intent on file")
#if H5AC_DO_TAGGING_SANITY_CHECKS
if(!H5C_get_ignore_tags(f->shared->cache) && H5AC__verify_tag(type) < 0)
@@ -950,12 +834,6 @@ H5AC_insert_entry(H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *thing,
if(H5C_insert_entry(f, type, addr, thing, flags) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTINS, FAIL, "H5C_insert_entry() failed")
-#if H5AC__TRACE_FILE_ENABLED
- if(trace_file_ptr != NULL)
- /* make note of the entry size */
- trace_entry_size = ((H5C_cache_entry_t *)thing)->size;
-#endif /* H5AC__TRACE_FILE_ENABLED */
-
#ifdef H5_HAVE_PARALLEL
{
H5AC_aux_t *aux_ptr;
@@ -974,14 +852,10 @@ H5AC_insert_entry(H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *thing,
#endif /* H5_HAVE_PARALLEL */
done:
-#if H5AC__TRACE_FILE_ENABLED
- if(trace_file_ptr != NULL)
- HDfprintf(trace_file_ptr, "%s %d %d\n", trace, (int)trace_entry_size, (int)ret_value);
-#endif /* H5AC__TRACE_FILE_ENABLED */
/* If currently logging, generate a message */
- if(curr_logging)
- if(H5AC__write_insert_entry_log_msg(f->shared->cache, addr, type->id, flags, ((H5C_cache_entry_t *)thing)->size, ret_value) < 0)
- HDONE_ERROR(H5E_CACHE, H5E_LOGFAIL, FAIL, "unable to emit log message")
+ if(f->shared->cache->log_info->logging)
+ if(H5C_log_write_insert_entry_msg(f->shared->cache, addr, type->id, flags, ((H5C_cache_entry_t *)thing)->size, ret_value) < 0)
+ HDONE_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
FUNC_LEAVE_NOAPI(ret_value)
} /* H5AC_insert_entry() */
@@ -1038,12 +912,6 @@ done:
herr_t
H5AC_mark_entry_dirty(void *thing)
{
-#if H5AC__TRACE_FILE_ENABLED
- char trace[128] = "";
- FILE * trace_file_ptr = NULL;
-#endif /* H5AC__TRACE_FILE_ENABLED */
- hbool_t log_enabled; /* TRUE if logging was set up */
- hbool_t curr_logging; /* TRUE if currently logging */
H5AC_info_t *entry_ptr = NULL; /* Pointer to the cache entry */
H5C_t *cache_ptr = NULL; /* Pointer to the entry's associated metadata cache */
herr_t ret_value = SUCCEED; /* Return value */
@@ -1057,19 +925,6 @@ H5AC_mark_entry_dirty(void *thing)
entry_ptr = (H5AC_info_t *)thing;
cache_ptr = entry_ptr->cache_ptr;
-#if H5AC__TRACE_FILE_ENABLED
- /* For the mark pinned or protected entry dirty call, only the addr
- * is really necessary in the trace file. Write the result to catch
- * occult errors.
- */
- if(NULL != (trace_file_ptr = H5C_get_trace_file_ptr_from_entry(thing)))
- sprintf(trace, "%s 0x%lx", FUNC, (unsigned long)(entry_ptr->addr));
-#endif /* H5AC__TRACE_FILE_ENABLED */
-
- /* Check if log messages are being emitted */
- if(H5C_get_logging_status(cache_ptr, &log_enabled, &curr_logging) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unable to get logging status")
-
#ifdef H5_HAVE_PARALLEL
{
H5AC_aux_t *aux_ptr;
@@ -1086,15 +941,10 @@ H5AC_mark_entry_dirty(void *thing)
HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKDIRTY, FAIL, "can't mark pinned or protected entry dirty")
done:
-#if H5AC__TRACE_FILE_ENABLED
- if(trace_file_ptr)
- HDfprintf(trace_file_ptr, "%s %d\n", trace, (int)ret_value);
-#endif /* H5AC__TRACE_FILE_ENABLED */
-
/* If currently logging, generate a message */
- if(curr_logging)
- if(H5AC__write_mark_dirty_entry_log_msg(cache_ptr, entry_ptr, ret_value) < 0)
- HDONE_ERROR(H5E_CACHE, H5E_LOGFAIL, FAIL, "unable to emit log message")
+ if(cache_ptr->log_info->logging)
+ if(H5C_log_write_mark_entry_dirty_msg(cache_ptr, entry_ptr, ret_value) < 0)
+ HDONE_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
FUNC_LEAVE_NOAPI(ret_value)
} /* H5AC_mark_entry_dirty() */
@@ -1103,7 +953,7 @@ done:
/*-------------------------------------------------------------------------
* Function: H5AC_mark_entry_clean
*
- * Purpose: Mark a pinned entry as dirty. The target
+ * Purpose: Mark a pinned entry as clean. The target
* entry MUST be pinned.
*
* Return: Non-negative on success/Negative on failure
@@ -1116,12 +966,6 @@ done:
herr_t
H5AC_mark_entry_clean(void *thing)
{
-#if H5AC__TRACE_FILE_ENABLED
- char trace[128] = "";
- FILE * trace_file_ptr = NULL;
-#endif /* H5AC__TRACE_FILE_ENABLED */
- hbool_t log_enabled; /* TRUE if logging was set up */
- hbool_t curr_logging; /* TRUE if currently logging */
H5AC_info_t *entry_ptr = NULL; /* Pointer to the cache entry */
H5C_t *cache_ptr = NULL; /* Pointer to the entry's associated metadata cache */
herr_t ret_value = SUCCEED; /* Return value */
@@ -1131,23 +975,9 @@ H5AC_mark_entry_clean(void *thing)
/* Sanity check */
HDassert(thing);
-#if H5AC__TRACE_FILE_ENABLED
- /* For the mark pinned or protected entry clean call, only the addr
- * is really necessary in the trace file. Write the result to catch
- * occult errors.
- */
- if(NULL != (trace_file_ptr = H5C_get_trace_file_ptr_from_entry(thing)))
- sprintf(trace, "%s 0x%lx", FUNC,
- (unsigned long)(((H5C_cache_entry_t *)thing)->addr));
-#endif /* H5AC__TRACE_FILE_ENABLED */
-
entry_ptr = (H5AC_info_t *)thing;
cache_ptr = entry_ptr->cache_ptr;
- /* Check if log messages are being emitted */
- if(H5C_get_logging_status(cache_ptr, &log_enabled, &curr_logging) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unable to get logging status")
-
#ifdef H5_HAVE_PARALLEL
{
H5AC_aux_t *aux_ptr;
@@ -1164,15 +994,10 @@ H5AC_mark_entry_clean(void *thing)
HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKCLEAN, FAIL, "can't mark pinned or protected entry clean")
done:
-#if H5AC__TRACE_FILE_ENABLED
- if(trace_file_ptr)
- HDfprintf(trace_file_ptr, "%s %d\n", trace, (int)ret_value);
-#endif /* H5AC__TRACE_FILE_ENABLED */
-
/* If currently logging, generate a message */
- if(curr_logging)
- if(H5AC__write_mark_clean_entry_log_msg(cache_ptr, entry_ptr, ret_value) < 0)
- HDONE_ERROR(H5E_CACHE, H5E_LOGFAIL, FAIL, "unable to emit log message")
+ if(cache_ptr->log_info->logging)
+ if(H5C_log_write_mark_entry_clean_msg(cache_ptr, entry_ptr, ret_value) < 0)
+ HDONE_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
FUNC_LEAVE_NOAPI(ret_value)
} /* H5AC_mark_entry_clean() */
@@ -1194,12 +1019,6 @@ done:
herr_t
H5AC_mark_entry_unserialized(void *thing)
{
-#if H5AC__TRACE_FILE_ENABLED
- char trace[128] = "";
- FILE * trace_file_ptr = NULL;
-#endif /* H5AC__TRACE_FILE_ENABLED */
- hbool_t log_enabled; /* TRUE if logging was set up */
- hbool_t curr_logging; /* TRUE if currently logging */
H5AC_info_t *entry_ptr = NULL; /* Pointer to the cache entry */
H5C_t *cache_ptr = NULL; /* Pointer to the entry's associated metadata cache */
herr_t ret_value = SUCCEED; /* Return value */
@@ -1213,32 +1032,14 @@ H5AC_mark_entry_unserialized(void *thing)
entry_ptr = (H5AC_info_t *)thing;
cache_ptr = entry_ptr->cache_ptr;
-#if H5AC__TRACE_FILE_ENABLED
- /* For the mark entry unserialized call, only the addr
- * is really necessary in the trace file. Write the result to catch
- * occult errors.
- */
- if(NULL != (trace_file_ptr = H5C_get_trace_file_ptr_from_entry(thing)))
- sprintf(trace, "%s 0x%lx", FUNC, (unsigned long)(entry_ptr->addr));
-#endif /* H5AC__TRACE_FILE_ENABLED */
-
- /* Check if log messages are being emitted */
- if(H5C_get_logging_status(cache_ptr, &log_enabled, &curr_logging) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTGET, FAIL, "unable to get logging status")
-
if(H5C_mark_entry_unserialized(thing) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKUNSERIALIZED, FAIL, "can't mark entry unserialized")
done:
-#if H5AC__TRACE_FILE_ENABLED
- if(trace_file_ptr)
- HDfprintf(trace_file_ptr, "%s %d\n", trace, (int)ret_value);
-#endif /* H5AC__TRACE_FILE_ENABLED */
-
/* If currently logging, generate a message */
- if(curr_logging)
- if(H5AC__write_mark_unserialized_entry_log_msg(cache_ptr, entry_ptr, ret_value) < 0)
- HDONE_ERROR(H5E_CACHE, H5E_LOGFAIL, FAIL, "unable to emit log message")
+ if(cache_ptr->log_info->logging)
+ if(H5C_log_write_mark_unserialized_entry_msg(cache_ptr, entry_ptr, ret_value) < 0)
+ HDONE_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
FUNC_LEAVE_NOAPI(ret_value)
} /* H5AC_mark_entry_unserialized() */
@@ -1260,12 +1061,6 @@ done:
herr_t
H5AC_mark_entry_serialized(void *thing)
{
-#if H5AC__TRACE_FILE_ENABLED
- char trace[128] = "";
- FILE * trace_file_ptr = NULL;
-#endif /* H5AC__TRACE_FILE_ENABLED */
- hbool_t log_enabled; /* TRUE if logging was set up */
- hbool_t curr_logging; /* TRUE if currently logging */
H5AC_info_t *entry_ptr = NULL; /* Pointer to the cache entry */
H5C_t *cache_ptr = NULL; /* Pointer to the entry's associated metadata cache */
herr_t ret_value = SUCCEED; /* Return value */
@@ -1275,36 +1070,17 @@ H5AC_mark_entry_serialized(void *thing)
/* Sanity check */
HDassert(thing);
-#if H5AC__TRACE_FILE_ENABLED
- /* For the mark entry serializedn call, only the addr
- * is really necessary in the trace file. Write the result to catch
- * occult errors.
- */
- if(NULL != (trace_file_ptr = H5C_get_trace_file_ptr_from_entry(thing)))
- sprintf(trace, "%s 0x%lx", FUNC,
- (unsigned long)(((H5C_cache_entry_t *)thing)->addr));
-#endif /* H5AC__TRACE_FILE_ENABLED */
-
entry_ptr = (H5AC_info_t *)thing;
cache_ptr = entry_ptr->cache_ptr;
- /* Check if log messages are being emitted */
- if(H5C_get_logging_status(cache_ptr, &log_enabled, &curr_logging) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTGET, FAIL, "unable to get logging status")
-
if(H5C_mark_entry_serialized(thing) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKSERIALIZED, FAIL, "can't mark entry serialized")
done:
-#if H5AC__TRACE_FILE_ENABLED
- if(trace_file_ptr)
- HDfprintf(trace_file_ptr, "%s %d\n", trace, (int)ret_value);
-#endif /* H5AC__TRACE_FILE_ENABLED */
-
/* If currently logging, generate a message */
- if(curr_logging)
- if(H5AC__write_mark_serialized_entry_log_msg(cache_ptr, entry_ptr, ret_value) < 0)
- HDONE_ERROR(H5E_CACHE, H5E_LOGFAIL, FAIL, "unable to emit log message")
+ if(cache_ptr->log_info->logging)
+ if(H5C_log_write_mark_serialized_entry_msg(cache_ptr, entry_ptr, ret_value) < 0)
+ HDONE_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
FUNC_LEAVE_NOAPI(ret_value)
} /* H5AC_mark_entry_serialized() */
@@ -1327,15 +1103,9 @@ done:
herr_t
H5AC_move_entry(H5F_t *f, const H5AC_class_t *type, haddr_t old_addr, haddr_t new_addr)
{
-#if H5AC__TRACE_FILE_ENABLED
- char trace[128] = "";
- FILE * trace_file_ptr = NULL;
-#endif /* H5AC__TRACE_FILE_ENABLED */
#ifdef H5_HAVE_PARALLEL
H5AC_aux_t *aux_ptr;
#endif /* H5_HAVE_PARALLEL */
- hbool_t log_enabled; /* TRUE if logging was set up */
- hbool_t curr_logging; /* TRUE if currently logging */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
@@ -1348,20 +1118,6 @@ H5AC_move_entry(H5F_t *f, const H5AC_class_t *type, haddr_t old_addr, haddr_t ne
HDassert(H5F_addr_defined(new_addr));
HDassert(H5F_addr_ne(old_addr, new_addr));
- /* Check if log messages are being emitted */
- if(H5C_get_logging_status(f->shared->cache, &log_enabled, &curr_logging) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unable to get logging status")
-
-#if H5AC__TRACE_FILE_ENABLED
- /* For the move call, only the old addr and new addr are really
- * necessary in the trace file. Include the type id so we don't have to
- * look it up. Also write the result to catch occult errors.
- */
- if(NULL != (trace_file_ptr = H5C_get_trace_file_ptr(cache_ptr)))
- sprintf(trace, "%s 0x%lx 0x%lx %d", FUNC, (unsigned long)old_addr,
- (unsigned long)new_addr, (int)(type->id));
-#endif /* H5AC__TRACE_FILE_ENABLED */
-
#ifdef H5_HAVE_PARALLEL
/* Log moving the entry */
if(NULL != (aux_ptr = (H5AC_aux_t *)H5C_get_aux_ptr(f->shared->cache)))
@@ -1380,15 +1136,10 @@ H5AC_move_entry(H5F_t *f, const H5AC_class_t *type, haddr_t old_addr, haddr_t ne
#endif /* H5_HAVE_PARALLEL */
done:
-#if H5AC__TRACE_FILE_ENABLED
- if(trace_file_ptr != NULL)
- HDfprintf(trace_file_ptr, "%s %d\n", trace, (int)ret_value);
-#endif /* H5AC__TRACE_FILE_ENABLED */
-
/* If currently logging, generate a message */
- if(curr_logging)
- if(H5AC__write_move_entry_log_msg(f->shared->cache, old_addr, new_addr, type->id, ret_value) < 0)
- HDONE_ERROR(H5E_CACHE, H5E_LOGFAIL, FAIL, "unable to emit log message")
+ if(f->shared->cache->log_info->logging)
+ if(H5C_log_write_move_entry_msg(f->shared->cache, old_addr, new_addr, type->id, ret_value) < 0)
+ HDONE_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
FUNC_LEAVE_NOAPI(ret_value)
} /* H5AC_move_entry() */
@@ -1410,12 +1161,6 @@ done:
herr_t
H5AC_pin_protected_entry(void *thing)
{
-#if H5AC__TRACE_FILE_ENABLED
- char trace[128] = "";
- FILE * trace_file_ptr = NULL;
-#endif /* H5AC__TRACE_FILE_ENABLED */
- hbool_t log_enabled; /* TRUE if logging was set up */
- hbool_t curr_logging; /* TRUE if currently logging */
H5AC_info_t *entry_ptr = NULL; /* Pointer to the cache entry */
H5C_t *cache_ptr = NULL; /* Pointer to the entry's associated metadata cache */
herr_t ret_value = SUCCEED; /* Return value */
@@ -1425,37 +1170,19 @@ H5AC_pin_protected_entry(void *thing)
/* Sanity check */
HDassert(thing);
-#if H5AC__TRACE_FILE_ENABLED
- /* For the pin protected entry call, only the addr is really necessary
- * in the trace file. Also write the result to catch occult errors.
- */
- if(NULL != (trace_file_ptr = H5C_get_trace_file_ptr_from_entry(thing)))
- sprintf(trace, "%s 0x%lx", FUNC,
- (unsigned long)(((H5C_cache_entry_t *)thing)->addr));
-#endif /* H5AC__TRACE_FILE_ENABLED */
-
entry_ptr = (H5AC_info_t *)thing;
cache_ptr = entry_ptr->cache_ptr;
HDassert(cache_ptr);
- /* Check if log messages are being emitted */
- if(H5C_get_logging_status(cache_ptr, &log_enabled, &curr_logging) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unable to get logging status")
-
/* Pin entry */
if(H5C_pin_protected_entry(thing) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTPIN, FAIL, "can't pin entry")
done:
-#if H5AC__TRACE_FILE_ENABLED
- if(trace_file_ptr)
- HDfprintf(trace_file_ptr, "%s %d\n", trace, (int)ret_value);
-#endif /* H5AC__TRACE_FILE_ENABLED */
-
/* If currently logging, generate a message */
- if(curr_logging)
- if(H5AC__write_pin_entry_log_msg(cache_ptr, entry_ptr, ret_value) < 0)
- HDONE_ERROR(H5E_CACHE, H5E_LOGFAIL, FAIL, "unable to emit log message")
+ if(cache_ptr->log_info->logging)
+ if(H5C_log_write_pin_entry_msg(cache_ptr, entry_ptr, ret_value) < 0)
+ HDONE_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
FUNC_LEAVE_NOAPI(ret_value)
} /* H5AC_pin_protected_entry() */
@@ -1515,12 +1242,6 @@ done:
herr_t
H5AC_create_flush_dependency(void * parent_thing, void * child_thing)
{
-#if H5AC__TRACE_FILE_ENABLED
- char trace[128] = "";
- FILE * trace_file_ptr = NULL;
-#endif /* H5AC__TRACE_FILE_ENABLED */
- hbool_t log_enabled; /* TRUE if logging was set up */
- hbool_t curr_logging; /* TRUE if currently logging */
H5AC_info_t *entry_ptr = NULL; /* Pointer to the cache entry */
H5C_t *cache_ptr = NULL; /* Pointer to the entry's associated metadata cache */
herr_t ret_value = SUCCEED; /* Return value */
@@ -1531,35 +1252,19 @@ H5AC_create_flush_dependency(void * parent_thing, void * child_thing)
HDassert(parent_thing);
HDassert(child_thing);
-#if H5AC__TRACE_FILE_ENABLED
- if(NULL != (trace_file_ptr = H5C_get_trace_file_ptr_from_entry(parent_thing)))
- sprintf(trace, "%s %lx %lx", FUNC,
- (unsigned long)(((H5C_cache_entry_t *)parent_thing)->addr),
- (unsigned long)(((H5C_cache_entry_t *)child_thing)->addr));
-#endif /* H5AC__TRACE_FILE_ENABLED */
-
entry_ptr = (H5AC_info_t *)parent_thing;
cache_ptr = entry_ptr->cache_ptr;
HDassert(cache_ptr);
- /* Check if log messages are being emitted */
- if(H5C_get_logging_status(cache_ptr, &log_enabled, &curr_logging) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unable to get logging status")
-
/* Create the flush dependency */
if(H5C_create_flush_dependency(parent_thing, child_thing) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTDEPEND, FAIL, "H5C_create_flush_dependency() failed")
done:
-#if H5AC__TRACE_FILE_ENABLED
- if(trace_file_ptr != NULL)
- HDfprintf(trace_file_ptr, "%s %d\n", trace, (int)ret_value);
-#endif /* H5AC__TRACE_FILE_ENABLED */
-
/* If currently logging, generate a message */
- if(curr_logging)
- if(H5AC__write_create_fd_log_msg(cache_ptr, (H5AC_info_t *)parent_thing, (H5AC_info_t *)child_thing, ret_value) < 0)
- HDONE_ERROR(H5E_CACHE, H5E_LOGFAIL, FAIL, "unable to emit log message")
+ if(cache_ptr->log_info->logging)
+ if(H5C_log_write_create_fd_msg(cache_ptr, (H5AC_info_t *)parent_thing, (H5AC_info_t *)child_thing, ret_value) < 0)
+ HDONE_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
FUNC_LEAVE_NOAPI(ret_value)
} /* H5AC_create_flush_dependency() */
@@ -1593,14 +1298,7 @@ void *
H5AC_protect(H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *udata,
unsigned flags)
{
-#if H5AC__TRACE_FILE_ENABLED
- char trace[128] = "";
- size_t trace_entry_size = 0;
- FILE * trace_file_ptr = NULL;
-#endif /* H5AC__TRACE_FILE_ENABLED */
void * thing = NULL; /* Pointer to native data structure for entry */
- hbool_t log_enabled; /* TRUE if logging was set up */
- hbool_t curr_logging; /* TRUE if currently logging */
void * ret_value = NULL; /* Return value */
FUNC_ENTER_NOAPI(NULL)
@@ -1613,10 +1311,6 @@ H5AC_protect(H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *udata,
HDassert(type->serialize);
HDassert(H5F_addr_defined(addr));
- /* Check if log messages are being emitted */
- if(H5C_get_logging_status(f->shared->cache, &log_enabled, &curr_logging) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, NULL, "unable to get logging status")
-
/* Check for unexpected flags -- H5C__FLUSH_COLLECTIVELY_FLAG
* only permitted in the parallel case.
*/
@@ -1633,16 +1327,6 @@ H5AC_protect(H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *udata,
if((0 == (H5F_INTENT(f) & H5F_ACC_RDWR)) && (0 == (flags & H5C__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, NULL, "no write intent on file")
-#if H5AC__TRACE_FILE_ENABLED
- /* For the protect call, only the addr, size, type id, and flags are
- * necessary in the trace file. Also indicate whether the call was
- * successful to catch occult errors.
- */
- if(NULL != (trace_file_ptr = H5C_get_trace_file_ptr(cache_ptr)))
- sprintf(trace, "%s 0x%lx %d 0x%x", FUNC, (unsigned long)addr,
- (int)(type->id), flags);
-#endif /* H5AC__TRACE_FILE_ENABLED */
-
#if H5AC_DO_TAGGING_SANITY_CHECKS
if(!H5C_get_ignore_tags(f->shared->cache) && H5AC__verify_tag(type) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTTAG, NULL, "Bad tag value")
@@ -1651,28 +1335,18 @@ H5AC_protect(H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *udata,
if(NULL == (thing = H5C_protect(f, type, addr, udata, flags)))
HGOTO_ERROR(H5E_CACHE, H5E_CANTPROTECT, NULL, "H5C_protect() failed")
-#if H5AC__TRACE_FILE_ENABLED
- if(trace_file_ptr != NULL)
- /* Make note of the entry size */
- trace_entry_size = ((H5C_cache_entry_t *)thing)->size;
-#endif /* H5AC__TRACE_FILE_ENABLED */
-
/* Set return value */
ret_value = thing;
done:
-#if H5AC__TRACE_FILE_ENABLED
- if(trace_file_ptr != NULL)
- HDfprintf(trace_file_ptr, "%s %d %d\n", trace, (int)trace_entry_size, (int)(ret_value != NULL));
-#endif /* H5AC__TRACE_FILE_ENABLED */
-
/* If currently logging, generate a message */
- if(curr_logging) {
+ {
herr_t fake_ret_value = (NULL == ret_value) ? FAIL : SUCCEED;
- if(H5AC__write_protect_entry_log_msg(f->shared->cache, (H5AC_info_t *)thing, flags, fake_ret_value) < 0)
- HDONE_ERROR(H5E_CACHE, H5E_LOGFAIL, NULL, "unable to emit log message")
- } /* end if */
+ if(f->shared->cache->log_info->logging)
+ if(H5C_log_write_protect_entry_msg(f->shared->cache, (H5AC_info_t *)thing, type->id, flags, fake_ret_value) < 0)
+ HDONE_ERROR(H5E_CACHE, H5E_LOGGING, NULL, "unable to emit log message")
+ }
FUNC_LEAVE_NOAPI(ret_value)
} /* H5AC_protect() */
@@ -1693,12 +1367,6 @@ done:
herr_t
H5AC_resize_entry(void *thing, size_t new_size)
{
-#if H5AC__TRACE_FILE_ENABLED
- char trace[128] = "";
- FILE * trace_file_ptr = NULL;
-#endif /* H5AC__TRACE_FILE_ENABLED */
- hbool_t log_enabled; /* TRUE if logging was set up */
- hbool_t curr_logging; /* TRUE if currently logging */
H5AC_info_t *entry_ptr = NULL; /* Pointer to the cache entry */
H5C_t *cache_ptr = NULL; /* Pointer to the entry's associated metadata cache */
herr_t ret_value = SUCCEED; /* Return value */
@@ -1708,25 +1376,10 @@ H5AC_resize_entry(void *thing, size_t new_size)
/* Sanity check */
HDassert(thing);
-#if H5AC__TRACE_FILE_ENABLED
- /* For the resize pinned entry call, only the addr, and new_size are
- * really necessary in the trace file. Write the result to catch
- * occult errors.
- */
- if(NULL != (trace_file_ptr = H5C_get_trace_file_ptr_from_entry(thing)))
- sprintf(trace, "%s 0x%lx %d", FUNC,
- (unsigned long)(((H5C_cache_entry_t *)thing)->addr),
- (int)new_size);
-#endif /* H5AC__TRACE_FILE_ENABLED */
-
entry_ptr = (H5AC_info_t *)thing;
cache_ptr = entry_ptr->cache_ptr;
HDassert(cache_ptr);
- /* Check if log messages are being emitted */
- if(H5C_get_logging_status(cache_ptr, &log_enabled, &curr_logging) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unable to get logging status")
-
/* Resize the entry */
if(H5C_resize_entry(thing, new_size) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTRESIZE, FAIL, "can't resize entry")
@@ -1743,15 +1396,10 @@ H5AC_resize_entry(void *thing, size_t new_size)
#endif /* H5_HAVE_PARALLEL */
done:
-#if H5AC__TRACE_FILE_ENABLED
- if(trace_file_ptr)
- HDfprintf(trace_file_ptr, "%s %d\n", trace, (int)ret_value);
-#endif /* H5AC__TRACE_FILE_ENABLED */
-
/* If currently logging, generate a message */
- if(curr_logging)
- if(H5AC__write_resize_entry_log_msg(cache_ptr, entry_ptr, new_size, ret_value) < 0)
- HDONE_ERROR(H5E_CACHE, H5E_LOGFAIL, FAIL, "unable to emit log message")
+ if(cache_ptr->log_info->logging)
+ if(H5C_log_write_resize_entry_msg(cache_ptr, entry_ptr, new_size, ret_value) < 0)
+ HDONE_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
FUNC_LEAVE_NOAPI(ret_value)
} /* H5AC_resize_entry() */
@@ -1773,12 +1421,6 @@ done:
herr_t
H5AC_unpin_entry(void *thing)
{
-#if H5AC__TRACE_FILE_ENABLED
- char trace[128] = "";
- FILE * trace_file_ptr = NULL;
-#endif /* H5AC__TRACE_FILE_ENABLED */
- hbool_t log_enabled; /* TRUE if logging was set up */
- hbool_t curr_logging; /* TRUE if currently logging */
H5AC_info_t *entry_ptr = NULL; /* Pointer to the cache entry */
H5C_t *cache_ptr = NULL; /* Pointer to the entry's associated metadata cache */
herr_t ret_value = SUCCEED; /* Return value */
@@ -1788,37 +1430,19 @@ H5AC_unpin_entry(void *thing)
/* Sanity check */
HDassert(thing);
-#if H5AC__TRACE_FILE_ENABLED
- /* For the unpin entry call, only the addr is really necessary
- * in the trace file. Also write the result to catch occult errors.
- */
- if(NULL != (trace_file_ptr = H5C_get_trace_file_ptr_from_entry(thing)))
- sprintf(trace, "%s 0x%lx", FUNC,
- (unsigned long)(((H5C_cache_entry_t *)thing)->addr));
-#endif /* H5AC__TRACE_FILE_ENABLED */
-
entry_ptr = (H5AC_info_t *)thing;
cache_ptr = entry_ptr->cache_ptr;
HDassert(cache_ptr);
- /* Check if log messages are being emitted */
- if(H5C_get_logging_status(cache_ptr, &log_enabled, &curr_logging) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unable to get logging status")
-
/* Unpin the entry */
if(H5C_unpin_entry(thing) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPIN, FAIL, "can't unpin entry")
done:
-#if H5AC__TRACE_FILE_ENABLED
- if(trace_file_ptr)
- HDfprintf(trace_file_ptr, "%s %d\n", trace, (int)ret_value);
-#endif /* H5AC__TRACE_FILE_ENABLED */
-
/* If currently logging, generate a message */
- if(curr_logging)
- if(H5AC__write_unpin_entry_log_msg(cache_ptr, entry_ptr, ret_value) < 0)
- HDONE_ERROR(H5E_CACHE, H5E_LOGFAIL, FAIL, "unable to emit log message")
+ if(cache_ptr->log_info->logging)
+ if(H5C_log_write_unpin_entry_msg(cache_ptr, entry_ptr, ret_value) < 0)
+ HDONE_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
FUNC_LEAVE_NOAPI(ret_value)
} /* H5AC_unpin_entry() */
@@ -1839,12 +1463,6 @@ done:
herr_t
H5AC_destroy_flush_dependency(void * parent_thing, void * child_thing)
{
-#if H5AC__TRACE_FILE_ENABLED
- char trace[128] = "";
- FILE * trace_file_ptr = NULL;
-#endif /* H5AC__TRACE_FILE_ENABLED */
- hbool_t log_enabled; /* TRUE if logging was set up */
- hbool_t curr_logging; /* TRUE if currently logging */
H5AC_info_t *entry_ptr = NULL; /* Pointer to the cache entry */
H5C_t *cache_ptr = NULL; /* Pointer to the entry's associated metadata cache */
herr_t ret_value = SUCCEED; /* Return value */
@@ -1855,35 +1473,19 @@ H5AC_destroy_flush_dependency(void * parent_thing, void * child_thing)
HDassert(parent_thing);
HDassert(child_thing);
-#if H5AC__TRACE_FILE_ENABLED
- if(NULL != (trace_file_ptr = H5C_get_trace_file_ptr_from_entry(parent_thing)))
- sprintf(trace, "%s %llx %llx", FUNC,
- (unsigned long long)(((H5C_cache_entry_t *)parent_thing)->addr),
- (unsigned long long)(((H5C_cache_entry_t *)child_thing)->addr));
-#endif /* H5AC__TRACE_FILE_ENABLED */
-
entry_ptr = (H5AC_info_t *)parent_thing;
cache_ptr = entry_ptr->cache_ptr;
HDassert(cache_ptr);
- /* Check if log messages are being emitted */
- if(H5C_get_logging_status(cache_ptr, &log_enabled, &curr_logging) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unable to get logging status")
-
/* Destroy the flush dependency */
if(H5C_destroy_flush_dependency(parent_thing, child_thing) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTUNDEPEND, FAIL, "H5C_destroy_flush_dependency() failed")
done:
-#if H5AC__TRACE_FILE_ENABLED
- if(trace_file_ptr != NULL)
- HDfprintf(trace_file_ptr, "%s %d\n", trace, (int)ret_value);
-#endif /* H5AC__TRACE_FILE_ENABLED */
-
/* If currently logging, generate a message */
- if(curr_logging)
- if(H5AC__write_destroy_fd_log_msg(cache_ptr, (H5AC_info_t *)parent_thing, (H5AC_info_t *)child_thing, ret_value) < 0)
- HDONE_ERROR(H5E_CACHE, H5E_LOGFAIL, FAIL, "unable to emit log message")
+ if(cache_ptr->log_info->logging)
+ if(H5C_log_write_destroy_fd_msg(cache_ptr, (H5AC_info_t *)parent_thing, (H5AC_info_t *)child_thing, ret_value) < 0)
+ HDONE_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
FUNC_LEAVE_NOAPI(ret_value)
} /* H5AC_destroy_flush_dependency() */
@@ -1931,17 +1533,11 @@ herr_t
H5AC_unprotect(H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *thing,
unsigned flags)
{
-#if H5AC__TRACE_FILE_ENABLED
- char trace[128] = "";
- FILE * trace_file_ptr = NULL;
-#endif /* H5AC__TRACE_FILE_ENABLED */
hbool_t dirtied;
hbool_t deleted;
#ifdef H5_HAVE_PARALLEL
H5AC_aux_t * aux_ptr = NULL;
#endif /* H5_HAVE_PARALLEL */
- hbool_t log_enabled; /* TRUE if logging was set up */
- hbool_t curr_logging; /* TRUE if currently logging */
herr_t ret_value=SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
@@ -1958,19 +1554,6 @@ H5AC_unprotect(H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *thing,
HDassert( ((H5AC_info_t *)thing)->addr == addr );
HDassert( ((H5AC_info_t *)thing)->type == type );
- /* Check if log messages are being emitted */
- if(H5C_get_logging_status(f->shared->cache, &log_enabled, &curr_logging) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unable to get logging status")
-
-#if H5AC__TRACE_FILE_ENABLED
- /* For the unprotect call, only the addr, type id, flags, and possible
- * new size are really necessary in the trace file. Write the return
- * value to catch occult errors.
- */
- if(NULL != (trace_file_ptr = H5C_get_trace_file_ptr(cache_ptr)))
- sprintf(trace, "%s 0x%lx %d", FUNC, (unsigned long)addr, (int)(type->id));
-#endif /* H5AC__TRACE_FILE_ENABLED */
-
dirtied = (hbool_t)(((flags & H5AC__DIRTIED_FLAG) == H5AC__DIRTIED_FLAG) ||
(((H5AC_info_t *)thing)->dirtied));
deleted = (hbool_t)((flags & H5C__DELETED_FLAG) == H5C__DELETED_FLAG);
@@ -2011,15 +1594,10 @@ H5AC_unprotect(H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *thing,
#endif /* H5_HAVE_PARALLEL */
done:
-#if H5AC__TRACE_FILE_ENABLED
- if(trace_file_ptr != NULL)
- HDfprintf(trace_file_ptr, "%s 0x%x %d\n", trace, (unsigned)flags, (int)ret_value);
-#endif /* H5AC__TRACE_FILE_ENABLED */
-
/* If currently logging, generate a message */
- if(curr_logging)
- if(H5AC__write_unprotect_entry_log_msg(f->shared->cache, (H5AC_info_t *)thing, type->id, flags, ret_value) < 0)
- HDONE_ERROR(H5E_CACHE, H5E_LOGFAIL, FAIL, "unable to emit log message")
+ if(f->shared->cache->log_info->logging)
+ if(H5C_log_write_unprotect_entry_msg(f->shared->cache, addr, type->id, flags, ret_value) < 0)
+ HDONE_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
FUNC_LEAVE_NOAPI(ret_value)
} /* H5AC_unprotect() */
@@ -2150,6 +1728,33 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5AC_get_cache_flush_in_progess
+ *
+ * Purpose: Wrapper function for H5C_get_cache_flush_in_progress().
+ *
+ * Return: SUCCEED on success, and FAIL on failure.
+ *
+ * Programmer: John Mainzer
+ * 3/11/05
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5AC_get_cache_flush_in_progress(H5AC_t *cache_ptr, hbool_t *flush_in_progress_ptr)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ if(H5C_get_cache_flush_in_progress((H5C_t *)cache_ptr, flush_in_progress_ptr) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5C_get_cache_flush_in_progress() failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5AC_get_cache_flush_in_progress() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5AC_get_cache_hit_rate
*
* Purpose: Wrapper function for H5C_get_cache_hit_rate().
@@ -2218,12 +1823,6 @@ done:
herr_t
H5AC_set_cache_auto_resize_config(H5AC_t *cache_ptr, H5AC_cache_config_t *config_ptr)
{
-#if H5AC__TRACE_FILE_ENABLED
- H5AC_cache_config_t trace_config = H5AC__DEFAULT_CACHE_CONFIG;
- FILE * trace_file_ptr = NULL;
-#endif /* H5AC__TRACE_FILE_ENABLED */
- hbool_t log_enabled; /* TRUE if logging was set up */
- hbool_t curr_logging; /* TRUE if currently logging */
H5C_auto_size_ctl_t internal_config;
herr_t ret_value = SUCCEED; /* Return value */
@@ -2232,18 +1831,6 @@ H5AC_set_cache_auto_resize_config(H5AC_t *cache_ptr, H5AC_cache_config_t *config
/* Sanity checks */
HDassert(cache_ptr);
- /* Check if log messages are being emitted */
- if(H5C_get_logging_status(cache_ptr, &log_enabled, &curr_logging) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unable to get logging status")
-
-#if H5AC__TRACE_FILE_ENABLED
- /* Make note of the new configuration. Don't look up the trace file
- * pointer, as that may change before we use it.
- */
- if(config_ptr != NULL)
- trace_config = *config_ptr;
-#endif /* H5AC__TRACE_FILE_ENABLED */
-
if(cache_ptr == NULL)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "bad cache_ptr on entry")
#ifdef H5_HAVE_PARALLEL
@@ -2260,23 +1847,25 @@ H5AC_set_cache_auto_resize_config(H5AC_t *cache_ptr, H5AC_cache_config_t *config
if(H5AC_validate_config(config_ptr) != SUCCEED)
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "Bad cache configuration")
- if(config_ptr->open_trace_file) {
- FILE * file_ptr;
-
- if(NULL == (file_ptr = H5C_get_trace_file_ptr(cache_ptr)))
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5C_get_trace_file_ptr() failed")
-
- if((!(config_ptr->close_trace_file)) && (file_ptr != NULL))
- HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "Trace file already open")
- } /* end if */
-
- /* Close & reopen trace file, if requested */
+ /* If the cache config struct is being used to control logging, perform
+ * the open/close operations. Note that this is the only place where the
+ * struct-based control opens and closes the log files so we also have
+ * to write start/stop messages.
+ */
+ /* close */
if(config_ptr->close_trace_file)
- if(H5AC__close_trace_file(cache_ptr) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5AC__close_trace_file() failed")
- if(config_ptr->open_trace_file)
- if(H5AC__open_trace_file(cache_ptr, config_ptr->trace_file_name) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "H5AC__open_trace_file() failed")
+ if(H5C_log_tear_down((H5C_t *)cache_ptr) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "mdc logging tear-down failed")
+
+ /* open */
+ if(config_ptr->open_trace_file) {
+ /* Turn on metadata cache logging.
+ * This will be trace output until we create a special API call. JSON
+ * output is generated when logging is controlled by the H5P calls.
+ */
+ if(H5C_log_set_up((H5C_t *)cache_ptr, config_ptr->trace_file_name, H5C_LOG_STYLE_TRACE, TRUE) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "mdc logging setup failed")
+ }
/* Convert external configuration to internal representation */
if(H5AC__ext_config_2_int_config(config_ptr, &internal_config) < 0)
@@ -2302,52 +1891,10 @@ H5AC_set_cache_auto_resize_config(H5AC_t *cache_ptr, H5AC_cache_config_t *config
#endif /* H5_HAVE_PARALLEL */
done:
-#if H5AC__TRACE_FILE_ENABLED
- /* For the set cache auto resize config call, only the contents
- * of the config is necessary in the trace file. Write the return
- * value to catch occult errors.
- */
- if(NULL != (trace_file_ptr = H5C_get_trace_file_ptr(cache_ptr)))
- HDfprintf(trace_file_ptr,
- "%s %d %d %d %d \"%s\" %d %d %d %f %d %d %ld %d %f %f %d %f %f %d %d %d %f %f %d %d %d %d %f %zu %d %d\n",
- "H5AC_set_cache_auto_resize_config",
- trace_config.version,
- (int)(trace_config.rpt_fcn_enabled),
- (int)(trace_config.open_trace_file),
- (int)(trace_config.close_trace_file),
- trace_config.trace_file_name,
- (int)(trace_config.evictions_enabled),
- (int)(trace_config.set_initial_size),
- (int)(trace_config.initial_size),
- trace_config.min_clean_fraction,
- (int)(trace_config.max_size),
- (int)(trace_config.min_size),
- trace_config.epoch_length,
- (int)(trace_config.incr_mode),
- trace_config.lower_hr_threshold,
- trace_config.increment,
- (int)(trace_config.flash_incr_mode),
- trace_config.flash_multiple,
- trace_config.flash_threshold,
- (int)(trace_config.apply_max_increment),
- (int)(trace_config.max_increment),
- (int)(trace_config.decr_mode),
- trace_config.upper_hr_threshold,
- trace_config.decrement,
- (int)(trace_config.apply_max_decrement),
- (int)(trace_config.max_decrement),
- trace_config.epochs_before_eviction,
- (int)(trace_config.apply_empty_reserve),
- trace_config.empty_reserve,
- trace_config.dirty_bytes_threshold,
- trace_config.metadata_write_strategy,
- (int)ret_value);
-#endif /* H5AC__TRACE_FILE_ENABLED */
-
/* If currently logging, generate a message */
- if(curr_logging)
- if(H5AC__write_set_cache_config_log_msg(cache_ptr, config_ptr, ret_value) < 0)
- HDONE_ERROR(H5E_CACHE, H5E_LOGFAIL, FAIL, "unable to emit log message")
+ if(cache_ptr->log_info->logging)
+ if(H5C_log_write_set_cache_config_msg(cache_ptr, config_ptr, ret_value) < 0)
+ HDONE_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
FUNC_LEAVE_NOAPI(ret_value)
} /* H5AC_set_cache_auto_resize_config() */
@@ -2393,12 +1940,12 @@ H5AC_validate_config(H5AC_cache_config_t *config_ptr)
if(config_ptr->open_trace_file) {
size_t name_len;
- /* Can't really test the trace_file_name field without trying to
- * open the file, so we will content ourselves with a couple of
- * sanity checks on the length of the file name.
- */
- name_len = HDstrlen(config_ptr->trace_file_name);
- if(name_len == 0)
+ /* Can't really test the trace_file_name field without trying to
+ * open the file, so we will content ourselves with a couple of
+ * sanity checks on the length of the file name.
+ */
+ name_len = HDstrlen(config_ptr->trace_file_name);
+ if(name_len == 0)
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "config_ptr->trace_file_name is empty")
else if(name_len > H5AC__MAX_TRACE_FILE_NAME_LEN)
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "config_ptr->trace_file_name too long")
@@ -2867,8 +2414,18 @@ H5AC_cork(H5F_t *f, haddr_t obj_addr, unsigned action, hbool_t *corked)
HDassert(H5F_addr_defined(obj_addr));
HDassert(action == H5AC__SET_CORK || action == H5AC__UNCORK || action == H5AC__GET_CORKED);
- if(action == H5AC__GET_CORKED)
- HDassert(corked);
+ /* Skip the search on "tag_list" when there are no "corked" objects.
+ * This is done to mitigate the slow down when closing objects.
+ * Re-visit this optimization when we optimize tag info management
+ * in the future.
+ */
+ if(action == H5AC__GET_CORKED) {
+ HDassert(corked);
+ if(H5C_get_num_objs_corked(f->shared->cache) == 0) {
+ *corked = FALSE;
+ HGOTO_DONE(SUCCEED)
+ }
+ }
if(H5C_cork(f->shared->cache, obj_addr, action, corked) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Cannot perform the cork action")
@@ -3089,12 +2646,6 @@ H5AC_remove_entry(void *_entry)
{
H5AC_info_t *entry = (H5AC_info_t *)_entry; /* Entry to remove */
H5C_t *cache = NULL; /* Pointer to the entry's associated metadata cache */
-#if H5AC__TRACE_FILE_ENABLED
- char trace[128] = "";
- FILE * trace_file_ptr = NULL;
-#endif /* H5AC__TRACE_FILE_ENABLED */
- hbool_t log_enabled; /* TRUE if logging was set up */
- hbool_t curr_logging; /* TRUE if currently logging */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
@@ -3104,32 +2655,15 @@ H5AC_remove_entry(void *_entry)
cache = entry->cache_ptr;
HDassert(cache);
-#if H5AC__TRACE_FILE_ENABLED
- /* For the remove entry call, only the addr is really necessary
- * in the trace file. Also write the result to catch occult errors.
- */
- if(NULL != (trace_file_ptr = H5C_get_trace_file_ptr_from_entry(entry)))
- sprintf(trace, "%s 0x%lx", FUNC, (unsigned long)(entry->addr));
-#endif /* H5AC__TRACE_FILE_ENABLED */
-
- /* Check if log messages are being emitted */
- if(H5C_get_logging_status(cache, &log_enabled, &curr_logging) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTGET, FAIL, "unable to get logging status")
-
/* Remove the entry from the cache*/
if(H5C_remove_entry(entry) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTREMOVE, FAIL, "can't remove entry")
done:
-#if H5AC__TRACE_FILE_ENABLED
- if(trace_file_ptr)
- HDfprintf(trace_file_ptr, "%s %d\n", trace, (int)ret_value);
-#endif /* H5AC__TRACE_FILE_ENABLED */
-
/* If currently logging, generate a message */
- if(curr_logging)
- if(H5AC__write_remove_entry_log_msg(cache, entry, ret_value) < 0)
- HDONE_ERROR(H5E_CACHE, H5E_LOGFAIL, FAIL, "unable to emit log message")
+ if(cache->log_info->logging)
+ if(H5C_log_write_remove_entry_msg(cache, entry, ret_value) < 0)
+ HDONE_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
FUNC_LEAVE_NOAPI(ret_value)
} /* H5AC_remove_entry() */
@@ -3159,4 +2693,3 @@ H5AC_get_mdc_image_info(H5AC_t *cache_ptr, haddr_t *image_addr, hsize_t *image_l
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5AC_get_mdc_image_info() */
-
diff --git a/src/H5ACdbg.c b/src/H5ACdbg.c
index c6d71a8..1235206 100644
--- a/src/H5ACdbg.c
+++ b/src/H5ACdbg.c
@@ -136,121 +136,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5AC__close_trace_file()
- *
- * Purpose: If a trace file is open, stop logging calls to the cache,
- * and close the file.
- *
- * Note that the function does nothing if there is no trace
- * file.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: John Mainzer
- * 6/2/06
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5AC__close_trace_file(H5AC_t *cache_ptr)
-{
- FILE * trace_file_ptr;
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_PACKAGE
-
- if(cache_ptr == NULL)
- HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "NULL cache_ptr on entry.")
-
- if(NULL == (trace_file_ptr = H5C_get_trace_file_ptr(cache_ptr)))
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5C_get_trace_file_ptr() failed.")
-
- if(trace_file_ptr != NULL) {
- if(H5C_set_trace_file_ptr(cache_ptr, NULL) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5C_set_trace_file_ptr() failed.")
-
- if(HDfclose(trace_file_ptr) != 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close metadata cache trace file")
- } /* end if */
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5AC__close_trace_file() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5AC__open_trace_file()
- *
- * Purpose: Open a trace file, and start logging calls to the cache.
- *
- * This logging is done at the H5C level, and will only take
- * place if H5C_TRACE_FILE_ENABLED (defined in H5Cprivate.h)
- * is TRUE.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: John Mainzer
- * 6/1/06
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5AC__open_trace_file(H5AC_t *cache_ptr, const char *trace_file_name)
-{
- char file_name[H5AC__MAX_TRACE_FILE_NAME_LEN + H5C__PREFIX_LEN + 2];
- FILE * file_ptr;
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_PACKAGE
-
- HDassert(cache_ptr);
-
- /* Check args */
- if(cache_ptr == NULL)
- HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "cache_ptr NULL on entry.")
- if(trace_file_name == NULL)
- HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "NULL trace_file_name on entry.")
- if(HDstrlen(trace_file_name) > H5AC__MAX_TRACE_FILE_NAME_LEN)
- HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "trace file name too long.")
- if(NULL != (file_ptr = H5C_get_trace_file_ptr(cache_ptr)))
- HGOTO_ERROR(H5E_CACHE, H5E_FILEOPEN, FAIL, "trace file already open.")
-
-#ifdef H5_HAVE_PARALLEL
-{
- H5AC_aux_t * aux_ptr;
-
- aux_ptr = (H5AC_aux_t *)H5C_get_aux_ptr(cache_ptr);
- if(aux_ptr == NULL)
- sprintf(file_name, "%s", trace_file_name);
- else {
- if(aux_ptr->magic != H5AC__H5AC_AUX_T_MAGIC)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Bad aux_ptr->magic.")
-
- sprintf(file_name, "%s.%d", trace_file_name, aux_ptr->mpi_rank);
- } /* end else */
-
- if(HDstrlen(file_name) > H5AC__MAX_TRACE_FILE_NAME_LEN + H5C__PREFIX_LEN + 1)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "cooked trace file name too long.")
-}
-#else /* H5_HAVE_PARALLEL */
- HDsnprintf(file_name, (size_t)(H5AC__MAX_TRACE_FILE_NAME_LEN + H5C__PREFIX_LEN + 1),
- "%s", trace_file_name);
-#endif /* H5_HAVE_PARALLEL */
-
- if((file_ptr = HDfopen(file_name, "w")) == NULL)
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "trace file open failed.")
-
- HDfprintf(file_ptr, "### HDF5 metadata cache trace file version 1 ###\n");
-
- if(H5C_set_trace_file_ptr(cache_ptr, file_ptr) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5C_set_trace_file_ptr() failed.")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5AC__open_trace_file() */
-
-
-/*-------------------------------------------------------------------------
*
* Function: H5AC_get_entry_ptr_from_addr()
*
diff --git a/src/H5AClog.c b/src/H5AClog.c
deleted file mode 100644
index 51a2050..0000000
--- a/src/H5AClog.c
+++ /dev/null
@@ -1,1105 +0,0 @@
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * 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 COPYING file, which can be found at the root of the source code *
- * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
- * If you do not have access to either file, you may request a copy from *
- * help@hdfgroup.org. *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-/*-------------------------------------------------------------------------
- *
- * Created: H5AClog.c
- *
- * Purpose: Functions for metadata cache logging in JSON format
- *
- *-------------------------------------------------------------------------
- */
-
-/****************/
-/* Module Setup */
-/****************/
-#include "H5ACmodule.h" /* This source code file is part of the H5AC module */
-
-/***********/
-/* Headers */
-/***********/
-#include "H5private.h" /* Generic Functions */
-#include "H5ACpkg.h" /* Metadata cache */
-#include "H5Cprivate.h" /* Cache */
-#include "H5Eprivate.h" /* Error handling */
-
-
-/****************/
-/* Local Macros */
-/****************/
-
-#define MSG_SIZE 128
-
-
-/******************/
-/* Local Typedefs */
-/******************/
-
-
-/********************/
-/* Package Typedefs */
-/********************/
-
-
-/********************/
-/* Local Prototypes */
-/********************/
-
-
-/*********************/
-/* Package Variables */
-/*********************/
-
-
-/*****************************/
-/* Library Private Variables */
-/*****************************/
-
-
-/*******************/
-/* Local Variables */
-/*******************/
-
-
-
-/*-------------------------------------------------------------------------
- * Function: H5AC__write_create_cache_log_msg
- *
- * Purpose: Write a log message for cache creation.
- *
- * Return: Success: SUCCEED
- * Failure: FAIL
- *
- * Programmer: Dana Robinson
- * Sunday, March 16, 2014
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5AC__write_create_cache_log_msg(H5AC_t *cache)
-{
- char msg[MSG_SIZE];
- hbool_t log_enabled; /* TRUE if logging was set up */
- hbool_t curr_logging; /* TRUE if currently logging */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(FAIL)
-
- /* Sanity checks */
- HDassert(cache);
-
- /* Check if log messages are being emitted */
- if(H5C_get_logging_status(cache, &log_enabled, &curr_logging) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unable to get logging status")
-
- /* Since we're about to override the current logging flag,
- * check the "log enabled" flag to see if we didn't get here
- * by mistake.
- */
- if(!log_enabled)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "attempt to write opening log message when logging is disabled")
-
- /* Create the log message string */
- HDsnprintf(msg, MSG_SIZE,
-"\
-{\n\
-\"create_time\":%lld,\n\
-\"messages\":\n\
-[\n\
-"
- , (long long)HDtime(NULL));
-
- /* Have to temporarily enable logging, if it isn't currently */
- if(!curr_logging)
- if(H5C_start_logging(cache) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_LOGFAIL, FAIL, "unable to start mdc logging")
-
- /* Write the log message to the file */
- if(H5C_write_log_message(cache, msg) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unable to emit log message")
-
- /* Stop logging, if it wasn't started originally */
- if(!curr_logging)
- if(H5C_stop_logging(cache) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_LOGFAIL, FAIL, "unable to stop mdc logging")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5AC__write_create_cache_log_msg() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5AC__write_destroy_cache_log_msg
- *
- * Purpose: Write a log message for cache destruction.
- *
- * Return: Success: SUCCEED
- * Failure: FAIL
- *
- * Programmer: Dana Robinson
- * Sunday, March 16, 2014
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5AC__write_destroy_cache_log_msg(H5AC_t *cache)
-{
- char msg[MSG_SIZE];
- hbool_t log_enabled; /* TRUE if logging was set up */
- hbool_t curr_logging; /* TRUE if currently logging */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(FAIL)
-
- /* Sanity checks */
- HDassert(cache);
-
- /* Check if log messages are being emitted */
- if(H5C_get_logging_status(cache, &log_enabled, &curr_logging) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unable to get logging status")
-
- /* Since we're about to override the current logging flag,
- * check the "log enabled" flag to see if we didn't get here
- * by mistake.
- */
- if(!log_enabled)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "attempt to write closing log message when logging is disabled")
-
- /* Create the log message string */
- HDsnprintf(msg, MSG_SIZE,
-"\
-],\n\
-\"close_time\":%lld,\n\
-}\n\
-"
- , (long long)HDtime(NULL));
-
- /* Have to temporarily enable logging, if it isn't currently */
- if(!curr_logging)
- if(H5C_start_logging(cache) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_LOGFAIL, FAIL, "unable to start mdc logging")
-
- /* Write the log message to the file */
- if(H5C_write_log_message(cache, msg) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unable to emit log message")
-
- /* Stop logging, if it wasn't started originally */
- if(!curr_logging)
- if(H5C_stop_logging(cache) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_LOGFAIL, FAIL, "unable to stop mdc logging")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5AC__write_destroy_cache_log_msg() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5AC__write_evict_cache_log_msg
- *
- * Purpose: Write a log message for eviction of cache entries.
- *
- * Return: Success: SUCCEED
- * Failure: FAIL
- *
- * Programmer: Dana Robinson
- * Sunday, March 16, 2014
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5AC__write_evict_cache_log_msg(const H5AC_t *cache,
- herr_t fxn_ret_value)
-{
- char msg[MSG_SIZE];
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI(FAIL)
-
- /* Sanity checks */
- HDassert(cache);
-
- /* Create the log message string */
- HDsnprintf(msg, MSG_SIZE,
-"\
-{\
-\"timestamp\":%lld,\
-\"action\":\"evict\",\
-\"returned\":%d\
-},\n\
-"
- , (long long)HDtime(NULL), (int)fxn_ret_value);
-
- /* Write the log message to the file */
- if(H5C_write_log_message(cache, msg) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unable to emit log message")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5AC__write_evict_cache_log_msg() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5AC__write_expunge_entry_log_msg
- *
- * Purpose: Write a log message for expunge of cache entries.
- *
- * Return: Success: SUCCEED
- * Failure: FAIL
- *
- * Programmer: Dana Robinson
- * Sunday, March 16, 2014
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5AC__write_expunge_entry_log_msg(const H5AC_t *cache,
- haddr_t address,
- int type_id,
- herr_t fxn_ret_value)
-{
- char msg[MSG_SIZE];
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI(FAIL)
-
- /* Sanity checks */
- HDassert(cache);
-
- /* Create the log message string */
- HDsnprintf(msg, MSG_SIZE,
-"\
-{\
-\"timestamp\":%lld,\
-\"action\":\"expunge\",\
-\"address\":0x%lx,\
-\"type_id\":%d,\
-\"returned\":%d\
-},\n\
-"
- , (long long)HDtime(NULL), (unsigned long)address, (int)type_id, (int)fxn_ret_value);
-
-
- /* Write the log message to the file */
- if(H5C_write_log_message(cache, msg) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unable to emit log message")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5AC__write_expunge_entry_log_msg() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5AC__write_flush_cache_log_msg
- *
- * Purpose: Write a log message for cache flushes.
- *
- * Return: Success: SUCCEED
- * Failure: FAIL
- *
- * Programmer: Dana Robinson
- * Sunday, March 16, 2014
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5AC__write_flush_cache_log_msg(const H5AC_t *cache,
- herr_t fxn_ret_value)
-{
- char msg[MSG_SIZE];
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI(FAIL)
-
- /* Sanity checks */
- HDassert(cache);
-
- /* Create the log message string */
- HDsnprintf(msg, MSG_SIZE,
-"\
-{\
-\"timestamp\":%lld,\
-\"action\":\"flush\",\
-\"returned\":%d\
-},\n\
-"
- , (long long)HDtime(NULL), (int)fxn_ret_value);
-
- /* Write the log message to the file */
- if(H5C_write_log_message(cache, msg) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unable to emit log message")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5AC__write_flush_cache_log_msg() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5AC__write_insert_entry_log_msg
- *
- * Purpose: Write a log message for insertion of cache entries.
- *
- * Return: Success: SUCCEED
- * Failure: FAIL
- *
- * Programmer: Dana Robinson
- * Sunday, March 16, 2014
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5AC__write_insert_entry_log_msg(const H5AC_t *cache,
- haddr_t address,
- int type_id,
- unsigned flags,
- size_t size,
- herr_t fxn_ret_value)
-{
- char msg[MSG_SIZE];
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI(FAIL)
-
- /* Sanity checks */
- HDassert(cache);
-
-
- /* Create the log message string */
- HDsnprintf(msg, MSG_SIZE,
-"\
-{\
-\"timestamp\":%lld,\
-\"action\":\"insert\",\
-\"address\":0x%lx,\
-\"flags\":0x%x,\
-\"type_id\":%d,\
-\"size\":%d,\
-\"returned\":%d\
-},\n\
-"
- , (long long)HDtime(NULL), (unsigned long)address, flags, type_id,
- (int)size, (int)fxn_ret_value);
-
- /* Write the log message to the file */
- if(H5C_write_log_message(cache, msg) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unable to emit log message")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5AC__write_insert_entry_log_msg() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5AC__write_mark_dirty_entry_log_msg
- *
- * Purpose: Write a log message for marking cache entries as dirty.
- *
- * Return: Success: SUCCEED
- * Failure: FAIL
- *
- * Programmer: Dana Robinson
- * Sunday, March 16, 2014
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5AC__write_mark_dirty_entry_log_msg(const H5AC_t *cache,
- const H5AC_info_t *entry,
- herr_t fxn_ret_value)
-{
- char msg[MSG_SIZE];
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI(FAIL)
-
- /* Sanity checks */
- HDassert(cache);
- HDassert(entry);
-
- /* Create the log message string */
- HDsnprintf(msg, MSG_SIZE,
-"\
-{\
-\"timestamp\":%lld,\
-\"action\":\"dirty\",\
-\"address\":0x%lx,\
-\"returned\":%d\
-},\n\
-"
- , (long long)HDtime(NULL), (unsigned long)entry->addr, (int)fxn_ret_value);
-
- /* Write the log message to the file */
- if(H5C_write_log_message(cache, msg) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unable to emit log message")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5AC__write_mark_dirty_entry_log_msg() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5AC__write_mark_clean_entry_log_msg
- *
- * Purpose: Write a log message for marking cache entries as clean.
- *
- * Return: Success: SUCCEED
- * Failure: FAIL
- *
- * Programmer: Quincey Koziol
- * Saturday, July 23, 2016
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5AC__write_mark_clean_entry_log_msg(const H5AC_t *cache, const H5AC_info_t *entry,
- herr_t fxn_ret_value)
-{
- char msg[MSG_SIZE]; /* Log message buffer */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(FAIL)
-
- /* Sanity checks */
- HDassert(cache);
- HDassert(entry);
-
- /* Create the log message string */
- HDsnprintf(msg, MSG_SIZE,
-"\
-{\
-\"timestamp\":%lld,\
-\"action\":\"clean\",\
-\"address\":0x%lx,\
-\"returned\":%d\
-},\n\
-"
- , (long long)HDtime(NULL), (unsigned long)entry->addr, (int)fxn_ret_value);
-
- /* Write the log message to the file */
- if(H5C_write_log_message(cache, msg) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unable to emit log message")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5AC__write_mark_clean_entry_log_msg() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5AC__write_mark_unserialized_entry_log_msg
- *
- * Purpose: Write a log message for marking cache entries as unserialized.
- *
- * Return: Success: SUCCEED
- * Failure: FAIL
- *
- * Programmer: Quincey Koziol
- * Thursday, December 22, 2016
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5AC__write_mark_unserialized_entry_log_msg(const H5AC_t *cache,
- const H5AC_info_t *entry,
- herr_t fxn_ret_value)
-{
- char msg[MSG_SIZE];
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI(FAIL)
-
- /* Sanity checks */
- HDassert(cache);
- HDassert(entry);
-
- /* Create the log message string */
- HDsnprintf(msg, MSG_SIZE,
-"\
-{\
-\"timestamp\":%lld,\
-\"action\":\"unserialized\",\
-\"address\":0x%lx,\
-\"returned\":%d\
-},\n\
-"
- , (long long)HDtime(NULL), (unsigned long)entry->addr, (int)fxn_ret_value);
-
- /* Write the log message to the file */
- if(H5C_write_log_message(cache, msg) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unable to emit log message")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5AC__write_mark_unserialized_entry_log_msg() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5AC__write_mark_serialize_entry_log_msg
- *
- * Purpose: Write a log message for marking cache entries as serialize.
- *
- * Return: Success: SUCCEED
- * Failure: FAIL
- *
- * Programmer: Quincey Koziol
- * Thursday, December 22, 2016
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5AC__write_mark_serialized_entry_log_msg(const H5AC_t *cache, const H5AC_info_t *entry,
- herr_t fxn_ret_value)
-{
- char msg[MSG_SIZE]; /* Log message buffer */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(FAIL)
-
- /* Sanity checks */
- HDassert(cache);
- HDassert(entry);
-
- /* Create the log message string */
- HDsnprintf(msg, MSG_SIZE,
-"\
-{\
-\"timestamp\":%lld,\
-\"action\":\"serialized\",\
-\"address\":0x%lx,\
-\"returned\":%d\
-},\n\
-"
- , (long long)HDtime(NULL), (unsigned long)entry->addr, (int)fxn_ret_value);
-
- /* Write the log message to the file */
- if(H5C_write_log_message(cache, msg) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unable to emit log message")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5AC__write_mark_serialized_entry_log_msg() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5AC__write_move_entry_log_msg
- *
- * Purpose: Write a log message for moving a cache entry.
- *
- * Return: Success: SUCCEED
- * Failure: FAIL
- *
- * Programmer: Dana Robinson
- * Sunday, March 16, 2014
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5AC__write_move_entry_log_msg(const H5AC_t *cache,
- haddr_t old_addr,
- haddr_t new_addr,
- int type_id,
- herr_t fxn_ret_value)
-{
- char msg[MSG_SIZE];
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI(FAIL)
-
- /* Sanity checks */
- HDassert(cache);
-
- /* Create the log message string */
- HDsnprintf(msg, MSG_SIZE,
-"\
-{\
-\"timestamp\":%lld,\
-\"action\":\"move\",\
-\"old_address\":0x%lx,\
-\"new_address\":0x%lx,\
-\"type_id\":%d,\
-\"returned\":%d\
-},\n\
-"
- , (long long)HDtime(NULL), (unsigned long)old_addr,
- (unsigned long)new_addr, type_id, (int)fxn_ret_value);
-
- /* Write the log message to the file */
- if(H5C_write_log_message(cache, msg) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unable to emit log message")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5AC__write_move_entry_log_msg() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5AC__write_pin_entry_log_msg
- *
- * Purpose: Write a log message for pinning a cache entry.
- *
- * Return: Success: SUCCEED
- * Failure: FAIL
- *
- * Programmer: Dana Robinson
- * Sunday, March 16, 2014
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5AC__write_pin_entry_log_msg(const H5AC_t *cache,
- const H5AC_info_t *entry,
- herr_t fxn_ret_value)
-{
- char msg[MSG_SIZE];
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI(FAIL)
-
- /* Sanity checks */
- HDassert(cache);
- HDassert(entry);
-
- /* Create the log message string */
- HDsnprintf(msg, MSG_SIZE,
-"\
-{\
-\"timestamp\":%lld,\
-\"action\":\"pin\",\
-\"address\":0x%lx,\
-\"returned\":%d\
-},\n\
-"
- , (long long)HDtime(NULL), (unsigned long)entry->addr,
- (int)fxn_ret_value);
-
- /* Write the log message to the file */
- if(H5C_write_log_message(cache, msg) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unable to emit log message")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5AC__write_pin_entry_log_msg() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5AC__write_create_fd_log_msg
- *
- * Purpose: Write a log message for creating a flush dependency between
- * two cache entries.
- *
- * Return: Success: SUCCEED
- * Failure: FAIL
- *
- * Programmer: Dana Robinson
- * Sunday, March 16, 2014
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5AC__write_create_fd_log_msg(const H5AC_t *cache,
- const H5AC_info_t *parent,
- const H5AC_info_t *child,
- herr_t fxn_ret_value)
-{
- char msg[MSG_SIZE];
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI(FAIL)
-
- /* Sanity checks */
- HDassert(cache);
- HDassert(parent);
- HDassert(child);
-
- /* Create the log message string */
- HDsnprintf(msg, MSG_SIZE,
-"\
-{\
-\"timestamp\":%lld,\
-\"action\":\"create_fd\",\
-\"parent_addr\":0x%lx,\
-\"child_addr\":0x%lx,\
-\"returned\":%d\
-},\n\
-"
- , (long long)HDtime(NULL), (unsigned long)parent->addr,
- (unsigned long)child->addr, (int)fxn_ret_value);
-
- /* Write the log message to the file */
- if(H5C_write_log_message(cache, msg) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unable to emit log message")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5AC__write_create_fd_log_msg() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5AC__write_protect_entry_log_msg
- *
- * Purpose: Write a log message for protecting a cache entry.
- *
- * Return: Success: SUCCEED
- * Failure: FAIL
- *
- * Programmer: Dana Robinson
- * Sunday, March 16, 2014
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5AC__write_protect_entry_log_msg(const H5AC_t *cache,
- const H5AC_info_t *entry,
- unsigned flags,
- herr_t fxn_ret_value)
-{
- char msg[MSG_SIZE];
- char rw_s[16];
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI(FAIL)
-
- /* Sanity checks */
- HDassert(cache);
- HDassert(entry);
-
- if(H5AC__READ_ONLY_FLAG == flags)
- HDstrcpy(rw_s, "READ");
- else
- HDstrcpy(rw_s, "WRITE");
-
- /* Create the log message string */
- HDsnprintf(msg, MSG_SIZE,
-"\
-{\
-\"timestamp\":%lld,\
-\"action\":\"protect\",\
-\"address\":0x%lx,\
-\"readwrite\":\"%s\",\
-\"size\":%d,\
-\"returned\":%d\
-},\n\
-"
- , (long long)HDtime(NULL), (unsigned long)entry->addr,
- rw_s, (int)entry->size, (int)fxn_ret_value);
-
- /* Write the log message to the file */
- if(H5C_write_log_message(cache, msg) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unable to emit log message")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5AC__write_protect_entry_log_msg() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5AC__write_resize_entry_log_msg
- *
- * Purpose: Write a log message for resizing a cache entry.
- *
- * Return: Success: SUCCEED
- * Failure: FAIL
- *
- * Programmer: Dana Robinson
- * Sunday, March 16, 2014
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5AC__write_resize_entry_log_msg(const H5AC_t *cache,
- const H5AC_info_t *entry,
- size_t new_size,
- herr_t fxn_ret_value)
-{
- char msg[MSG_SIZE];
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI(FAIL)
-
- /* Sanity checks */
- HDassert(cache);
- HDassert(entry);
-
- /* Create the log message string */
- HDsnprintf(msg, MSG_SIZE,
-"\
-{\
-\"timestamp\":%lld,\
-\"action\":\"resize\",\
-\"address\":0x%lx,\
-\"new_size\":%d,\
-\"returned\":%d\
-},\n\
-"
- , (long long)HDtime(NULL), (unsigned long)entry->addr,
- (int)new_size, (int)fxn_ret_value);
-
- /* Write the log message to the file */
- if(H5C_write_log_message(cache, msg) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unable to emit log message")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5AC__write_resize_entry_log_msg() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5AC__write_unpin_entry_log_msg
- *
- * Purpose: Write a log message for unpinning a cache entry.
- *
- * Return: Success: SUCCEED
- * Failure: FAIL
- *
- * Programmer: Dana Robinson
- * Sunday, March 16, 2014
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5AC__write_unpin_entry_log_msg(const H5AC_t *cache,
- const H5AC_info_t *entry,
- herr_t fxn_ret_value)
-{
- char msg[MSG_SIZE];
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI(FAIL)
-
- /* Sanity checks */
- HDassert(cache);
- HDassert(entry);
-
- /* Create the log message string */
- HDsnprintf(msg, MSG_SIZE,
-"\
-{\
-\"timestamp\":%lld,\
-\"action\":\"unpin\",\
-\"address\":0x%lx,\
-\"returned\":%d\
-},\n\
-"
- , (long long)HDtime(NULL), (unsigned long)entry->addr,
- (int)fxn_ret_value);
-
- /* Write the log message to the file */
- if(H5C_write_log_message(cache, msg) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unable to emit log message")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5AC__write_unpin_entry_log_msg() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5AC__write_destroy_fd_log_msg
- *
- * Purpose: Write a log message for destroying a flush dependency
- * between two cache entries.
- *
- * Return: Success: SUCCEED
- * Failure: FAIL
- *
- * Programmer: Dana Robinson
- * Sunday, March 16, 2014
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5AC__write_destroy_fd_log_msg(const H5AC_t *cache,
- const H5AC_info_t *parent,
- const H5AC_info_t *child,
- herr_t fxn_ret_value)
-{
- char msg[MSG_SIZE];
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI(FAIL)
-
- /* Sanity checks */
- HDassert(cache);
- HDassert(parent);
- HDassert(child);
-
- /* Create the log message string */
- HDsnprintf(msg, MSG_SIZE,
-"\
-{\
-\"timestamp\":%lld,\
-\"action\":\"destroy_fd\",\
-\"parent_addr\":0x%lx,\
-\"child_addr\":0x%lx,\
-\"returned\":%d\
-},\n\
-"
- , (long long)HDtime(NULL), (unsigned long)parent->addr,
- (unsigned long)child->addr, (int)fxn_ret_value);
-
- /* Write the log message to the file */
- if(H5C_write_log_message(cache, msg) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unable to emit log message")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5AC__write_destroy_fd_log_msg() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5AC__write_unprotect_entry_log_msg
- *
- * Purpose: Write a log message for unprotecting a cache entry.
- *
- * Return: Success: SUCCEED
- * Failure: FAIL
- *
- * Programmer: Dana Robinson
- * Sunday, March 16, 2014
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5AC__write_unprotect_entry_log_msg(const H5AC_t *cache,
- const H5AC_info_t *entry,
- int type_id,
- unsigned flags,
- herr_t fxn_ret_value)
-{
- char msg[MSG_SIZE];
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI(FAIL)
-
- /* Sanity checks */
- HDassert(cache);
- HDassert(entry);
-
- /* Create the log message string */
- HDsnprintf(msg, MSG_SIZE,
-"\
-{\
-\"timestamp\":%lld,\
-\"action\":\"unprotect\",\
-\"address\":0x%lx,\
-\"id\":%d,\
-\"flags\":%x,\
-\"returned\":%d\
-},\n\
-"
- , (long long)HDtime(NULL), (unsigned long)entry->addr,
- type_id, flags, (int)fxn_ret_value);
-
- HDsnprintf(msg, MSG_SIZE, " ");
-
- /* Write the log message to the file */
- if(H5C_write_log_message(cache, msg) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unable to emit log message")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5AC__write_unprotect_entry_log_msg() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5AC__write_set_cache_config_log_msg
- *
- * Purpose: Write a log message for setting the cache configuration.
- *
- * Return: Success: SUCCEED
- * Failure: FAIL
- *
- * Programmer: Dana Robinson
- * Sunday, March 16, 2014
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5AC__write_set_cache_config_log_msg(const H5AC_t *cache,
- const H5AC_cache_config_t *config,
- herr_t fxn_ret_value)
-{
- char msg[MSG_SIZE];
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI(FAIL)
-
- /* Sanity checks */
- HDassert(cache);
- HDassert(config);
-
- /* Create the log message string */
- HDsnprintf(msg, MSG_SIZE,
-"\
-{\
-\"timestamp\":%lld,\
-\"action\":\"set_config\",\
-\"returned\":%d\
-},\n\
-"
- , (long long)HDtime(NULL), (int)fxn_ret_value);
-
-
- /* Write the log message to the file */
- if(H5C_write_log_message(cache, msg) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unable to emit log message")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5AC__write_set_cache_config_log_msg() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5AC__write_remove_entry_log_msg
- *
- * Purpose: Write a log message for removing a cache entry.
- *
- * Return: Success: SUCCEED
- * Failure: FAIL
- *
- * Programmer: Quincey Koziol
- * September 17, 2016
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5AC__write_remove_entry_log_msg(const H5AC_t *cache, const H5AC_info_t *entry,
- herr_t fxn_ret_value)
-{
- char msg[MSG_SIZE];
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI(FAIL)
-
- /* Sanity checks */
- HDassert(cache);
- HDassert(entry);
-
- /* Create the log message string */
- HDsnprintf(msg, MSG_SIZE,
-"\
-{\
-\"timestamp\":%lld,\
-\"action\":\"remove\",\
-\"address\":0x%lx,\
-\"returned\":%d\
-},\n\
-"
- , (long long)HDtime(NULL), (unsigned long)entry->addr,
- (int)fxn_ret_value);
-
- /* Write the log message to the file */
- if(H5C_write_log_message(cache, msg) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "unable to emit log message")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5AC__write_remove_entry_log_msg() */
-
diff --git a/src/H5ACmpio.c b/src/H5ACmpio.c
index b60b933..e4b81fa 100644
--- a/src/H5ACmpio.c
+++ b/src/H5ACmpio.c
@@ -821,9 +821,8 @@ H5AC__log_cleaned_entry(const H5AC_info_t *entry_ptr)
{
H5AC_t * cache_ptr;
H5AC_aux_t * aux_ptr;
- herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_PACKAGE
+ FUNC_ENTER_PACKAGE_NOERR
/* Sanity check */
HDassert(entry_ptr);
@@ -853,8 +852,7 @@ H5AC__log_cleaned_entry(const H5AC_info_t *entry_ptr)
/* Decrement the dirty byte count */
aux_ptr->dirty_bytes -= entry_ptr->size;
-done:
- FUNC_LEAVE_NOAPI(ret_value)
+ FUNC_LEAVE_NOAPI(SUCCEED)
} /* H5AC__log_cleaned_entry() */
diff --git a/src/H5ACpkg.h b/src/H5ACpkg.h
index 9bf84bf..8997382 100644
--- a/src/H5ACpkg.h
+++ b/src/H5ACpkg.h
@@ -433,74 +433,5 @@ H5_DLL herr_t H5AC__set_write_done_callback(H5C_t * cache_ptr,
void (* write_done)(void));
#endif /* H5_HAVE_PARALLEL */
-/* Trace file routines */
-H5_DLL herr_t H5AC__close_trace_file(H5AC_t *cache_ptr);
-H5_DLL herr_t H5AC__open_trace_file(H5AC_t *cache_ptr, const char *trace_file_name);
-
-/* Cache logging routines */
-H5_DLL herr_t H5AC__write_create_cache_log_msg(H5AC_t *cache);
-H5_DLL herr_t H5AC__write_destroy_cache_log_msg(H5AC_t *cache);
-H5_DLL herr_t H5AC__write_evict_cache_log_msg(const H5AC_t *cache,
- herr_t fxn_ret_value);
-H5_DLL herr_t H5AC__write_expunge_entry_log_msg(const H5AC_t *cache,
- haddr_t address,
- int type_id,
- herr_t fxn_ret_value);
-H5_DLL herr_t H5AC__write_flush_cache_log_msg(const H5AC_t *cache,
- herr_t fxn_ret_value);
-H5_DLL herr_t H5AC__write_insert_entry_log_msg(const H5AC_t *cache,
- haddr_t address,
- int type_id,
- unsigned flags,
- size_t size,
- herr_t fxn_ret_value);
-H5_DLL herr_t H5AC__write_mark_dirty_entry_log_msg(const H5AC_t *cache,
- const H5AC_info_t *entry,
- herr_t fxn_ret_value);
-H5_DLL herr_t H5AC__write_mark_clean_entry_log_msg(const H5AC_t *cache,
- const H5AC_info_t *entry, herr_t fxn_ret_value);
-H5_DLL herr_t H5AC__write_mark_unserialized_entry_log_msg(const H5AC_t *cache,
- const H5AC_info_t *entry, herr_t fxn_ret_value);
-H5_DLL herr_t H5AC__write_mark_serialized_entry_log_msg(const H5AC_t *cache,
- const H5AC_info_t *entry, herr_t fxn_ret_value);
-H5_DLL herr_t H5AC__write_move_entry_log_msg(const H5AC_t *cache,
- haddr_t old_addr,
- haddr_t new_addr,
- int type_id,
- herr_t fxn_ret_value);
-H5_DLL herr_t H5AC__write_pin_entry_log_msg(const H5AC_t *cache,
- const H5AC_info_t *entry,
- herr_t fxn_ret_value);
-H5_DLL herr_t H5AC__write_create_fd_log_msg(const H5AC_t *cache,
- const H5AC_info_t *parent,
- const H5AC_info_t *child,
- herr_t fxn_ret_value);
-H5_DLL herr_t H5AC__write_protect_entry_log_msg(const H5AC_t *cache,
- const H5AC_info_t *entry,
- unsigned flags,
- herr_t fxn_ret_value);
-H5_DLL herr_t H5AC__write_resize_entry_log_msg(const H5AC_t *cache,
- const H5AC_info_t *entry,
- size_t new_size,
- herr_t fxn_ret_value);
-H5_DLL herr_t H5AC__write_unpin_entry_log_msg(const H5AC_t *cache,
- const H5AC_info_t *entry,
- herr_t fxn_ret_value);
-H5_DLL herr_t H5AC__write_destroy_fd_log_msg(const H5AC_t *cache,
- const H5AC_info_t *parent,
- const H5AC_info_t *child,
- herr_t fxn_ret_value);
-H5_DLL herr_t H5AC__write_unprotect_entry_log_msg(const H5AC_t *cache,
- const H5AC_info_t *entry,
- int type_id,
- unsigned flags,
- herr_t fxn_ret_value);
-H5_DLL herr_t H5AC__write_set_cache_config_log_msg(const H5AC_t *cache,
- const H5AC_cache_config_t *config,
- herr_t fxn_ret_value);
-H5_DLL herr_t H5AC__write_remove_entry_log_msg(const H5AC_t *cache,
- const H5AC_info_t *entry,
- herr_t fxn_ret_value);
-
#endif /* _H5ACpkg_H */
diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h
index a7e8493..b1d3049 100644
--- a/src/H5ACprivate.h
+++ b/src/H5ACprivate.h
@@ -35,12 +35,6 @@
#include "H5Pprivate.h" /* Property lists */
#include "H5SLprivate.h" /* Skip lists */
-#ifdef H5_METADATA_TRACE_FILE
-#define H5AC__TRACE_FILE_ENABLED 1
-#else /* H5_METADATA_TRACE_FILE */
-#define H5AC__TRACE_FILE_ENABLED 0
-#endif /* H5_METADATA_TRACE_FILE */
-
/* Global metadata tag values */
#define H5AC__INVALID_TAG (haddr_t)0
#define H5AC__IGNORE_TAG (haddr_t)1
@@ -417,6 +411,7 @@ H5_DLL herr_t H5AC_get_cache_auto_resize_config(const H5AC_t * cache_ptr,
H5AC_cache_config_t *config_ptr);
H5_DLL herr_t H5AC_get_cache_size(H5AC_t *cache_ptr, size_t *max_size_ptr,
size_t *min_clean_size_ptr, size_t *cur_size_ptr, uint32_t *cur_num_entries_ptr);
+H5_DLL herr_t H5AC_get_cache_flush_in_progress(H5AC_t *cache_ptr, hbool_t *flush_in_progress_ptr);
H5_DLL herr_t H5AC_get_cache_hit_rate(H5AC_t *cache_ptr, double *hit_rate_ptr);
H5_DLL herr_t H5AC_reset_cache_hit_rate_stats(H5AC_t *cache_ptr);
H5_DLL herr_t H5AC_set_cache_auto_resize_config(H5AC_t *cache_ptr,
diff --git a/src/H5Abtree2.c b/src/H5Abtree2.c
index 07da8e2..3377aa2 100644
--- a/src/H5Abtree2.c
+++ b/src/H5Abtree2.c
@@ -35,6 +35,7 @@
#include "H5private.h" /* Generic Functions */
#include "H5Apkg.h" /* Attributes */
#include "H5Eprivate.h" /* Error handling */
+#include "H5MMprivate.h" /* Memory management */
#include "H5SMprivate.h" /* Shared object header messages */
@@ -318,7 +319,7 @@ H5A__dense_btree2_name_encode(uint8_t *raw, const void *_nrecord, void H5_ATTR_U
FUNC_ENTER_STATIC_NOERR
/* Encode the record's fields */
- HDmemcpy(raw, nrecord->id.id, (size_t)H5O_FHEAP_ID_LEN);
+ H5MM_memcpy(raw, nrecord->id.id, (size_t)H5O_FHEAP_ID_LEN);
raw += H5O_FHEAP_ID_LEN;
*raw++ = nrecord->flags;
UINT32ENCODE(raw, nrecord->corder)
@@ -349,7 +350,7 @@ H5A__dense_btree2_name_decode(const uint8_t *raw, void *_nrecord, void H5_ATTR_U
FUNC_ENTER_STATIC_NOERR
/* Decode the record's fields */
- HDmemcpy(nrecord->id.id, raw, (size_t)H5O_FHEAP_ID_LEN);
+ H5MM_memcpy(nrecord->id.id, raw, (size_t)H5O_FHEAP_ID_LEN);
raw += H5O_FHEAP_ID_LEN;
nrecord->flags = *raw++;
UINT32DECODE(raw, nrecord->corder)
@@ -477,7 +478,7 @@ H5A__dense_btree2_corder_encode(uint8_t *raw, const void *_nrecord, void H5_ATTR
FUNC_ENTER_STATIC_NOERR
/* Encode the record's fields */
- HDmemcpy(raw, nrecord->id.id, (size_t)H5O_FHEAP_ID_LEN);
+ H5MM_memcpy(raw, nrecord->id.id, (size_t)H5O_FHEAP_ID_LEN);
raw += H5O_FHEAP_ID_LEN;
*raw++ = nrecord->flags;
UINT32ENCODE(raw, nrecord->corder)
@@ -507,7 +508,7 @@ H5A__dense_btree2_corder_decode(const uint8_t *raw, void *_nrecord, void H5_ATTR
FUNC_ENTER_STATIC_NOERR
/* Decode the record's fields */
- HDmemcpy(nrecord->id.id, raw, (size_t)H5O_FHEAP_ID_LEN);
+ H5MM_memcpy(nrecord->id.id, raw, (size_t)H5O_FHEAP_ID_LEN);
raw += H5O_FHEAP_ID_LEN;
nrecord->flags = *raw++;
UINT32DECODE(raw, nrecord->corder)
diff --git a/src/H5Adense.c b/src/H5Adense.c
index 5bed82d..7491dd2 100644
--- a/src/H5Adense.c
+++ b/src/H5Adense.c
@@ -299,19 +299,48 @@ done:
static herr_t
H5A__dense_fnd_cb(const H5A_t *attr, hbool_t *took_ownership, void *_user_attr)
{
- H5A_t const **user_attr = (H5A_t const **)_user_attr; /* User data from v2 B-tree attribute lookup */
+ const H5A_t **user_attr = (const H5A_t **)_user_attr; /* User data from v2 B-tree attribute lookup */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_STATIC_NOERR
+ FUNC_ENTER_STATIC
/* Check arguments */
HDassert(attr);
HDassert(user_attr);
+ HDassert(took_ownership);
+
+ /*
+ * If there is an attribute already stored in "user_attr",
+ * we need to free the dynamially allocated spaces for the
+ * attribute, otherwise we got infinite loop closing library due to
+ * outstanding allocation. (HDFFV-10659)
+ *
+ * This callback is used by H5A__dense_remove() to close/free the
+ * attribute stored in "user_attr" (via H5O__msg_free_real()) after
+ * the attribute node is deleted from the name index v2 B-tree.
+ * The issue is:
+ * When deleting the attribute node from the B-tree,
+ * if the attribute is found in the intermediate B-tree nodes,
+ * which may be merged/redistributed, we need to free the dynamically
+ * allocated spaces for the intermediate decoded attribute.
+ */
+ if(*user_attr != NULL) {
+ H5A_t *old_attr = *(H5A_t **)_user_attr;
+
+ /* Free any dynamically allocated items */
+ if(old_attr->shared)
+ if(H5A__shared_free(old_attr) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release attribute info")
+
+ old_attr = H5FL_FREE(H5A_t, old_attr);
+ } /* end if */
/* Take over attribute ownership */
*user_attr = attr;
*took_ownership = TRUE;
- FUNC_LEAVE_NOAPI(SUCCEED)
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5A__dense_fnd_cb() */
@@ -868,6 +897,7 @@ H5A__dense_rename(H5F_t *f, const H5O_ainfo_t *ainfo, const char *old_name,
H5HF_t *fheap = NULL; /* Fractal heap handle */
H5HF_t *shared_fheap = NULL; /* Fractal heap handle for shared header messages */
H5B2_t *bt2_name = NULL; /* v2 B-tree handle for name index */
+ H5B2_t *bt2_corder = NULL; /* v2 B-tree handle for creation order ndex */
H5A_t *attr_copy = NULL; /* Copy of attribute to rename */
htri_t attr_sharable; /* Flag indicating attributes are sharable */
htri_t shared_mesg; /* Should this message be stored in the Shared Message table? */
@@ -945,6 +975,33 @@ H5A__dense_rename(H5F_t *f, const H5O_ainfo_t *ainfo, const char *old_name,
if(H5A__set_version(f, attr_copy) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "unable to update attribute version")
+ /* Need to remove the attribute from the creation order index v2 B-tree */
+ if(ainfo->index_corder) {
+ htri_t corder_attr_exists; /* Attribute exists in v2 B-tree */
+
+ /* Open the creation order index v2 B-tree */
+ HDassert(H5F_addr_defined(ainfo->corder_bt2_addr));
+ if(NULL == (bt2_corder = H5B2_open(f, ainfo->corder_bt2_addr, NULL)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for creation index")
+
+ /* Set up the creation order to search for */
+ udata.corder = attr_copy->shared->crt_idx;
+
+ if((corder_attr_exists = H5B2_find(bt2_corder, &udata, NULL, NULL)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "can't search for attribute in name index")
+
+ if(corder_attr_exists) {
+ H5A_bt2_ud_rm_t rm_udata;
+
+ /* Set up the creation order in user data for the v2 B-tree 'record remove' callback */
+ rm_udata.common.corder = attr_copy->shared->crt_idx;
+
+ /* Remove the record from the creation order index v2 B-tree */
+ if(H5B2_remove(bt2_corder, &rm_udata, NULL, NULL) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTREMOVE, FAIL, "unable to remove attribute from creation order index v2 B-tree")
+ }
+ }
+
/* Insert renamed attribute back into dense storage */
/* (Possibly making it shared) */
if(H5A__dense_insert(f, ainfo, attr_copy) < 0)
@@ -992,6 +1049,8 @@ done:
HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
if(bt2_name && H5B2_close(bt2_name) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close v2 B-tree for name index")
+ if(bt2_corder && H5B2_close(bt2_corder) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close v2 B-tree for creation order index")
if(attr_copy)
H5O_msg_free(H5O_ATTR_ID, attr_copy);
diff --git a/src/H5Adeprec.c b/src/H5Adeprec.c
index e88c8c3..8d0e33c 100644
--- a/src/H5Adeprec.c
+++ b/src/H5Adeprec.c
@@ -43,6 +43,9 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5Iprivate.h" /* IDs */
#include "H5Opkg.h" /* Object headers */
+#include "H5VLprivate.h" /* Virtual object layer */
+
+#include "H5VLnative_private.h" /* Native VOL connector */
/****************/
@@ -113,10 +116,9 @@ hid_t
H5Acreate1(hid_t loc_id, const char *name, hid_t type_id, hid_t space_id,
hid_t acpl_id)
{
- H5A_t *attr = NULL; /* Attribute created */
- H5G_loc_t loc; /* Object location */
- H5T_t *type; /* Datatype to use for attribute */
- H5S_t *space; /* Dataspace to use for attribute */
+ void *attr = NULL; /* attr token from VOL connector */
+ H5VL_object_t *vol_obj = NULL; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
hid_t ret_value = H5I_INVALID_HID; /* Return value */
FUNC_ENTER_API(H5I_INVALID_HID)
@@ -125,33 +127,37 @@ H5Acreate1(hid_t loc_id, const char *name, hid_t type_id, hid_t space_id,
/* Check arguments */
if(H5I_ATTR == H5I_get_type(loc_id))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "location is not valid for an attribute")
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a location")
- if(0 == (H5F_INTENT(loc.oloc->file) & H5F_ACC_RDWR))
- HGOTO_ERROR(H5E_ARGS, H5E_WRITEERROR, H5I_INVALID_HID, "no write intent on file")
if(!name || !*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "no name")
- if(NULL == (type = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a type")
- if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a dataspace")
/* Set up collective metadata if appropriate */
if(H5CX_set_loc(loc_id) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, H5I_INVALID_HID, "can't set collective metadata read")
+ /* Get correct property list */
+ if(H5P_DEFAULT == acpl_id)
+ acpl_id = H5P_ATTRIBUTE_CREATE_DEFAULT;
+
+ /* Set location parameters */
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* Get the location object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier")
+
/* Create the attribute */
- if(NULL == (attr = H5A__create(&loc, name, type, space, acpl_id)))
+ if(NULL == (attr = H5VL_attr_create(vol_obj, &loc_params, name, type_id, space_id, acpl_id, H5P_DEFAULT, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, H5I_INVALID_HID, "unable to create attribute")
/* Register the new attribute and get an ID for it */
- if((ret_value = H5I_register(H5I_ATTR, attr, TRUE)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register attribute for ID")
+ if((ret_value = H5VL_register(H5I_ATTR, attr, vol_obj->connector, TRUE)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register attribute for ID")
done:
/* Clean up on failure */
if(H5I_INVALID_HID == ret_value)
- if(attr && H5A__close(attr) < 0)
+ if(attr && H5VL_attr_close(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, H5I_INVALID_HID, "can't close attribute")
FUNC_LEAVE_API(ret_value)
@@ -183,8 +189,9 @@ done:
hid_t
H5Aopen_name(hid_t loc_id, const char *name)
{
- H5G_loc_t loc; /* Object location */
- H5A_t *attr = NULL; /* Attribute opened */
+ void *attr = NULL; /* attr token from VOL connector */
+ H5VL_object_t *vol_obj = NULL; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
hid_t ret_value = H5I_INVALID_HID; /* Return value */
FUNC_ENTER_API(H5I_INVALID_HID)
@@ -193,23 +200,29 @@ H5Aopen_name(hid_t loc_id, const char *name)
/* Check arguments */
if(H5I_ATTR == H5I_get_type(loc_id))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "location is not valid for an attribute")
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a location")
if(!name || !*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "no name")
+ /* Set location parameters */
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* Get the location object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier")
+
/* Open the attribute */
- if(NULL == (attr = H5A__open_by_name(&loc, ".", name)))
- HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, H5I_INVALID_HID, "can't open attribute: '%s'", name)
+ if(NULL == (attr = H5VL_attr_open(vol_obj, &loc_params, name, H5P_DEFAULT, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open attribute")
/* Register the attribute and get an ID for it */
- if((ret_value = H5I_register(H5I_ATTR, attr, TRUE)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register attribute for ID")
+ if((ret_value = H5VL_register(H5I_ATTR, attr, vol_obj->connector, TRUE)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to atomize attribute handle")
done:
/* Clean up on failure */
if(H5I_INVALID_HID == ret_value)
- if(attr && H5A__close(attr) < 0)
+ if(attr && H5VL_attr_close(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, H5I_INVALID_HID, "can't close attribute")
FUNC_LEAVE_API(ret_value)
@@ -241,8 +254,9 @@ done:
hid_t
H5Aopen_idx(hid_t loc_id, unsigned idx)
{
- H5G_loc_t loc; /* Object location */
- H5A_t *attr = NULL; /* Attribute opened */
+ void *attr = NULL; /* attr token from VOL connector */
+ H5VL_object_t *vol_obj = NULL; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
hid_t ret_value = H5I_INVALID_HID; /* Return value */
FUNC_ENTER_API(H5I_INVALID_HID)
@@ -250,22 +264,33 @@ H5Aopen_idx(hid_t loc_id, unsigned idx)
/* Check arguments */
if(H5I_ATTR == H5I_get_type(loc_id))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute")
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "location is not valid for an attribute")
+
+ /* Set location parameters */
+ loc_params.type = H5VL_OBJECT_BY_IDX;
+ loc_params.loc_data.loc_by_idx.name = ".";
+ loc_params.loc_data.loc_by_idx.idx_type = H5_INDEX_CRT_ORDER;
+ loc_params.loc_data.loc_by_idx.order = H5_ITER_INC;
+ loc_params.loc_data.loc_by_idx.n = (hsize_t)idx;
+ loc_params.loc_data.loc_by_idx.lapl_id = H5P_LINK_ACCESS_DEFAULT;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* Get the location object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier")
/* Open the attribute */
- if(NULL == (attr = H5A__open_by_idx(&loc, ".", H5_INDEX_CRT_ORDER, H5_ITER_INC, (hsize_t)idx)))
+ if(NULL == (attr = H5VL_attr_open(vol_obj, &loc_params, NULL, H5P_DEFAULT, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open attribute")
/* Register the attribute and get an ID for it */
- if((ret_value = H5I_register(H5I_ATTR, attr, TRUE)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register attribute for ID")
+ if((ret_value = H5VL_register(H5I_ATTR, attr, vol_obj->connector, TRUE)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to atomize attribute handle")
done:
/* Clean up on failure */
if(H5I_INVALID_HID == ret_value)
- if(attr && H5A__close(attr) < 0)
+ if(attr && H5VL_attr_close(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, H5I_INVALID_HID, "can't close attribute")
FUNC_LEAVE_API(ret_value)
@@ -293,56 +318,26 @@ done:
int
H5Aget_num_attrs(hid_t loc_id)
{
- H5O_loc_t *loc; /* Object location for attribute */
- void *obj;
+ H5VL_object_t *vol_obj = NULL; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
+ H5O_info_t oinfo;
int ret_value = -1;
FUNC_ENTER_API((-1))
H5TRACE1("Is", "i", loc_id);
- if(H5I_BADID == H5I_get_type(loc_id))
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, (-1), "bad location ID")
- if(H5I_FILE == H5I_get_type(loc_id) || H5I_ATTR == H5I_get_type(loc_id))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "location is not valid for an attribute")
- if(NULL == (obj = H5I_object(loc_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADATOM, (-1), "illegal object atom")
-
- switch(H5I_get_type (loc_id)) {
- case H5I_DATASET:
- if(NULL == (loc = H5D_oloc((H5D_t*)obj)))
- HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, (-1), "can't get location for object")
- break;
-
- case H5I_DATATYPE:
- if(NULL == (loc = H5T_oloc((H5T_t*)obj)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "target datatype is not committed")
- break;
-
- case H5I_GROUP:
- if(NULL == (loc = H5G_oloc((H5G_t*)obj)))
- HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, (-1), "can't get location for object")
- break;
-
- case H5I_UNINIT:
- case H5I_BADID:
- case H5I_FILE:
- case H5I_DATASPACE:
- case H5I_ATTR:
- case H5I_REFERENCE:
- case H5I_VFL:
- case H5I_GENPROP_CLS:
- case H5I_GENPROP_LST:
- case H5I_ERROR_CLASS:
- case H5I_ERROR_MSG:
- case H5I_ERROR_STACK:
- case H5I_NTYPES:
- default:
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "inappropriate attribute target")
- }
-
- /* Look up the # of attributes for the object */
- if((ret_value = H5O__attr_count(loc)) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTCOUNT, (-1), "can't get attribute count for object")
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* Get the location object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "invalid location identifier")
+
+ /* Get the number of attributes for the object */
+ if(H5VL_object_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_OBJECT_GET_INFO, &loc_params, &oinfo, H5O_INFO_ALL) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, (-1), "unable to get attribute count for object")
+
+ H5_CHECKED_ASSIGN(ret_value, int, oinfo.num_attrs, hsize_t);
done:
FUNC_LEAVE_API(ret_value)
@@ -389,18 +384,23 @@ done:
herr_t
H5Aiterate1(hid_t loc_id, unsigned *attr_num, H5A_operator1_t op, void *op_data)
{
- herr_t ret_value; /* Return value */
+ H5VL_object_t *vol_obj = NULL; /* Object token of loc_id */
+ herr_t ret_value; /* Return value */
- FUNC_ENTER_API(FAIL)
+ FUNC_ENTER_API(H5_ITER_ERROR)
H5TRACE4("e", "i*Iux*x", loc_id, attr_num, op, op_data);
/* check arguments */
if(H5I_ATTR == H5I_get_type(loc_id))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute")
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5_ITER_ERROR, "location is not valid for an attribute")
+
+ /* Get the location object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_VOL, H5E_BADTYPE, H5_ITER_ERROR, "invalid location identifier")
/* Call attribute iteration routine */
- if((ret_value = H5A__iterate_old(loc_id, attr_num, op, op_data)) < 0)
- HERROR(H5E_ATTR, H5E_BADITER, "error iterating over attributes");
+ if((ret_value = H5VL_attr_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_ATTR_ITERATE_OLD, loc_id, attr_num, op, op_data)) < 0)
+ HERROR(H5E_VOL, H5E_BADITER, "error iterating over attributes");
done:
FUNC_LEAVE_API(ret_value)
diff --git a/src/H5Aint.c b/src/H5Aint.c
index 8268a01..2b43a64 100644
--- a/src/H5Aint.c
+++ b/src/H5Aint.c
@@ -13,11 +13,11 @@
/*-------------------------------------------------------------------------
*
- * Created: H5Aint.c
- * Dec 18 2006
- * Quincey Koziol <koziol@hdfgroup.org>
+ * Created: H5Aint.c
+ * Dec 18 2006
+ * Quincey Koziol <koziol@hdfgroup.org>
*
- * Purpose: Internal routines for managing attributes.
+ * Purpose: Internal routines for managing attributes.
*
*-------------------------------------------------------------------------
*/
@@ -27,7 +27,7 @@
/****************/
#include "H5Amodule.h" /* This source code file is part of the H5A module */
-#define H5O_FRIEND /*suppress error about including H5Opkg */
+#define H5O_FRIEND /*suppress error about including H5Opkg */
/***********/
@@ -42,6 +42,7 @@
#include "H5MMprivate.h" /* Memory management */
#include "H5Opkg.h" /* Object headers */
#include "H5SMprivate.h" /* Shared Object Header Messages */
+#include "H5VLprivate.h" /* Virtual Object Layer */
/****************/
@@ -107,6 +108,8 @@ static herr_t H5A__iterate_common(hid_t loc_id, H5_index_t idx_type,
const unsigned H5O_attr_ver_bounds[] = {
H5O_ATTR_VERSION_1, /* H5F_LIBVER_EARLIEST */
H5O_ATTR_VERSION_3, /* H5F_LIBVER_V18 */
+ H5O_ATTR_VERSION_3, /* H5F_LIBVER_V110 */
+ H5O_ATTR_VERSION_3, /* H5F_LIBVER_V112 */
H5O_ATTR_VERSION_LATEST /* H5F_LIBVER_LATEST */
};
@@ -119,19 +122,19 @@ const unsigned H5O_attr_ver_bounds[] = {
/* Local Variables */
/*******************/
-typedef H5A_t* H5A_t_ptr;
+typedef H5A_t* H5A_t_ptr;
H5FL_SEQ_DEFINE(H5A_t_ptr);
-
+
/*-------------------------------------------------------------------------
- * Function: H5A__create
+ * Function: H5A__create
*
* Purpose: This is the guts of creating an attribute.
*
* Return: Attribute structure on success, NULL on Failure.
*
- * Programmer: Quincey Koziol
- * April 2, 1998
+ * Programmer: Quincey Koziol
+ * April 2, 1998
*
*-------------------------------------------------------------------------
*/
@@ -139,11 +142,11 @@ H5A_t *
H5A__create(const H5G_loc_t *loc, const char *attr_name, const H5T_t *type,
const H5S_t *space, hid_t acpl_id)
{
- H5A_t *attr = NULL; /* Attribute created */
- hssize_t snelmts; /* elements in attribute */
- size_t nelmts; /* elements in attribute */
+ H5A_t *attr = NULL; /* Attribute created */
+ hssize_t snelmts; /* elements in attribute */
+ size_t nelmts; /* elements in attribute */
htri_t exists; /* Whether attribute exists */
- H5A_t *ret_value = NULL; /* Return value */
+ H5A_t *ret_value = NULL; /* Return value */
FUNC_ENTER_PACKAGE_TAG(loc->oloc->addr)
@@ -284,16 +287,16 @@ done:
FUNC_LEAVE_NOAPI_TAG(ret_value)
} /* H5A__create() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5A__create_by_name
+ * Function: H5A__create_by_name
*
- * Purpose: Create an attribute on object, according to it's name
+ * Purpose: Create an attribute on object, according to it's name
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Quincey Koziol
- * December 6, 2017
+ * Programmer: Quincey Koziol
+ * December 6, 2017
*
*-------------------------------------------------------------------------
*/
@@ -302,8 +305,8 @@ H5A__create_by_name(const H5G_loc_t *loc, const char *obj_name, const char *attr
const H5T_t *type, const H5S_t *space, hid_t acpl_id)
{
H5G_loc_t obj_loc; /* Location used to open group */
- H5G_name_t obj_path; /* Opened object group hier. path */
- H5O_loc_t obj_oloc; /* Opened object object location */
+ H5G_name_t obj_path; /* Opened object group hier. path */
+ H5O_loc_t obj_oloc; /* Opened object object location */
hbool_t loc_found = FALSE; /* Entry at 'obj_name' found */
H5A_t *attr = NULL; /* Attribute from object header */
H5A_t *ret_value = NULL; /* Return value */
@@ -345,9 +348,9 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5A__create_by_name() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5A__open_common
+ * Function: H5A__open_common
*
* Purpose:
* Finishes initializing an attributes the open
@@ -359,8 +362,8 @@ done:
*
* Return: Non-negative on success/Negative on failure
*
- * Programmer: Quincey Koziol
- * December 18, 2006
+ * Programmer: Quincey Koziol
+ * December 18, 2006
*
*-------------------------------------------------------------------------
*/
@@ -402,16 +405,16 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5A__open_common() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5A__open
+ * Function: H5A__open
*
- * Purpose: Open an attribute in an object header
+ * Purpose: Open an attribute in an object header
*
- * Return: Non-negative on success/Negative on failure
+ * Return: SUCCEED/FAIL
*
- * Programmer: Quincey Koziol
- * December 9, 2017
+ * Programmer: Quincey Koziol
+ * December 9, 2017
*
*-------------------------------------------------------------------------
*/
@@ -447,16 +450,16 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5A__open() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5A__open_by_idx
+ * Function: H5A__open_by_idx
*
- * Purpose: Open an attribute according to its index order
+ * Purpose: Open an attribute according to its index order
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Quincey Koziol
- * April 2, 1998
+ * Programmer: Quincey Koziol
+ * April 2, 1998
*
*-------------------------------------------------------------------------
*/
@@ -465,8 +468,8 @@ H5A__open_by_idx(const H5G_loc_t *loc, const char *obj_name, H5_index_t idx_type
H5_iter_order_t order, hsize_t n)
{
H5G_loc_t obj_loc; /* Location used to open group */
- H5G_name_t obj_path; /* Opened object group hier. path */
- H5O_loc_t obj_oloc; /* Opened object object location */
+ H5G_name_t obj_path; /* Opened object group hier. path */
+ H5O_loc_t obj_oloc; /* Opened object object location */
hbool_t loc_found = FALSE; /* Entry at 'obj_name' found */
H5A_t *attr = NULL; /* Attribute from object header */
H5A_t *ret_value = NULL; /* Return value */
@@ -511,7 +514,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5A__open_by_idx() */
-
+
/*-------------------------------------------------------------------------
* Function: H5A__open_by_name
*
@@ -519,8 +522,8 @@ done:
*
* Return: SUCCEED/FAIL
*
- * Programmer: Quincey Koziol
- * December 11, 2006
+ * Programmer: Quincey Koziol
+ * December 11, 2006
*
*-------------------------------------------------------------------------
*/
@@ -528,8 +531,8 @@ H5A_t *
H5A__open_by_name(const H5G_loc_t *loc, const char *obj_name, const char *attr_name)
{
H5G_loc_t obj_loc; /* Location used to open group */
- H5G_name_t obj_path; /* Opened object group hier. path */
- H5O_loc_t obj_oloc; /* Opened object object location */
+ H5G_name_t obj_path; /* Opened object group hier. path */
+ H5O_loc_t obj_oloc; /* Opened object object location */
hbool_t loc_found = FALSE; /* Entry at 'obj_name' found */
H5A_t *attr = NULL; /* Attribute from object header */
H5A_t *ret_value = NULL; /* Return value */
@@ -575,7 +578,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5A__open_by_name() */
-
+
/*--------------------------------------------------------------------------
NAME
H5A__read
@@ -595,16 +598,16 @@ done:
herr_t
H5A__read(const H5A_t *attr, const H5T_t *mem_type, void *buf)
{
- uint8_t *tconv_buf = NULL; /* datatype conv buffer*/
- uint8_t *bkg_buf = NULL; /* background buffer */
- hssize_t snelmts; /* elements in attribute */
- size_t nelmts; /* elements in attribute*/
- H5T_path_t *tpath = NULL; /* type conversion info */
- hid_t src_id = -1, dst_id = -1;/* temporary type atoms*/
- size_t src_type_size; /* size of source type */
- size_t dst_type_size; /* size of destination type */
- size_t buf_size; /* desired buffer size */
- herr_t ret_value = SUCCEED;
+ uint8_t *tconv_buf = NULL; /* datatype conv buffer*/
+ uint8_t *bkg_buf = NULL; /* background buffer */
+ hssize_t snelmts; /* elements in attribute */
+ size_t nelmts; /* elements in attribute*/
+ H5T_path_t *tpath = NULL; /* type conversion info */
+ hid_t src_id = -1, dst_id = -1;/* temporary type atoms*/
+ size_t src_type_size; /* size of source type */
+ size_t dst_type_size; /* size of destination type */
+ size_t buf_size; /* desired buffer size */
+ herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE_TAG(attr->oloc.addr)
@@ -645,21 +648,21 @@ H5A__read(const H5A_t *attr, const H5T_t *mem_type, void *buf)
HGOTO_ERROR(H5E_ATTR, H5E_NOSPACE, FAIL, "memory allocation failed")
/* Copy the attribute data into the buffer for conversion */
- HDmemcpy(tconv_buf, attr->shared->data, (src_type_size * nelmts));
+ H5MM_memcpy(tconv_buf, attr->shared->data, (src_type_size * nelmts));
/* Perform datatype conversion. */
if(H5T_convert(tpath, src_id, dst_id, nelmts, (size_t)0, (size_t)0, tconv_buf, bkg_buf) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "datatype conversion failed")
/* Copy the converted data into the user's buffer */
- HDmemcpy(buf, tconv_buf, (dst_type_size * nelmts));
+ H5MM_memcpy(buf, tconv_buf, (dst_type_size * nelmts));
} /* end if */
/* No type conversion necessary */
else {
HDassert(dst_type_size == src_type_size);
/* Copy the attribute data into the user's buffer */
- HDmemcpy(buf, attr->shared->data, (dst_type_size * nelmts));
+ H5MM_memcpy(buf, attr->shared->data, (dst_type_size * nelmts));
} /* end else */
} /* end else */
} /* end if */
@@ -673,12 +676,12 @@ done:
if(tconv_buf)
tconv_buf = H5FL_BLK_FREE(attr_buf, tconv_buf);
if(bkg_buf)
- bkg_buf = H5FL_BLK_FREE(attr_buf, bkg_buf);
+ bkg_buf = H5FL_BLK_FREE(attr_buf, bkg_buf);
FUNC_LEAVE_NOAPI_TAG(ret_value)
} /* H5A__read() */
-
+
/*--------------------------------------------------------------------------
NAME
H5A__write
@@ -698,17 +701,17 @@ done:
herr_t
H5A__write(H5A_t *attr, const H5T_t *mem_type, const void *buf)
{
- uint8_t *tconv_buf = NULL; /* datatype conv buffer */
+ uint8_t *tconv_buf = NULL; /* datatype conv buffer */
hbool_t tconv_owned = FALSE; /* Whether the datatype conv buffer is owned by attribute */
- uint8_t *bkg_buf = NULL; /* temp conversion buffer */
- hssize_t snelmts; /* elements in attribute */
- size_t nelmts; /* elements in attribute */
- H5T_path_t *tpath = NULL; /* conversion information*/
- hid_t src_id = -1, dst_id = -1;/* temporary type atoms */
- size_t src_type_size; /* size of source type */
- size_t dst_type_size; /* size of destination type*/
- size_t buf_size; /* desired buffer size */
- herr_t ret_value = SUCCEED;
+ uint8_t *bkg_buf = NULL; /* temp conversion buffer */
+ hssize_t snelmts; /* elements in attribute */
+ size_t nelmts; /* elements in attribute */
+ H5T_path_t *tpath = NULL; /* conversion information*/
+ hid_t src_id = -1, dst_id = -1;/* temporary type atoms */
+ size_t src_type_size; /* size of source type */
+ size_t dst_type_size; /* size of destination type*/
+ size_t buf_size; /* desired buffer size */
+ herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE_TAG(attr->oloc.addr)
@@ -746,7 +749,7 @@ H5A__write(H5A_t *attr, const H5T_t *mem_type, const void *buf)
HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, FAIL, "memory allocation failed")
/* Copy the user's data into the buffer for conversion */
- HDmemcpy(tconv_buf, buf, (src_type_size * nelmts));
+ H5MM_memcpy(tconv_buf, buf, (src_type_size * nelmts));
/* Perform datatype conversion */
if(H5T_convert(tpath, src_id, dst_id, nelmts, (size_t)0, (size_t)0, tconv_buf, bkg_buf) < 0)
@@ -769,8 +772,8 @@ H5A__write(H5A_t *attr, const H5T_t *mem_type, const void *buf)
if(NULL == (attr->shared->data = H5FL_BLK_MALLOC(attr_buf, dst_type_size * nelmts)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
- /* Copy the attribute data into the user's buffer */
- HDmemcpy(attr->shared->data, buf, (dst_type_size * nelmts));
+ /* Copy the attribute data into the attribute data buffer */
+ H5MM_memcpy(attr->shared->data, buf, (dst_type_size * nelmts));
} /* end else */
/* Modify the attribute in the object header */
@@ -792,7 +795,7 @@ done:
FUNC_LEAVE_NOAPI_TAG(ret_value)
} /* H5A__write() */
-
+
/*--------------------------------------------------------------------------
NAME
H5A__get_name
@@ -813,7 +816,7 @@ ssize_t
H5A__get_name(H5A_t *attr, size_t buf_size, char *buf)
{
size_t copy_len, nbytes;
- ssize_t ret_value = -1; /* Return value */
+ ssize_t ret_value = -1; /* Return value */
FUNC_ENTER_PACKAGE_NOERR
@@ -826,7 +829,7 @@ H5A__get_name(H5A_t *attr, size_t buf_size, char *buf)
/* Copy all/some of the name */
if(buf && copy_len > 0) {
- HDmemcpy(buf, attr->shared->name, copy_len);
+ H5MM_memcpy(buf, attr->shared->name, copy_len);
/* Terminate the string */
buf[copy_len]='\0';
@@ -838,7 +841,7 @@ H5A__get_name(H5A_t *attr, size_t buf_size, char *buf)
FUNC_LEAVE_NOAPI(ret_value)
} /* H5A__get_name() */
-
+
/*-------------------------------------------------------------------------
* Function: H5A_get_space
*
@@ -875,7 +878,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5A_get_space() */
-
+
/*-------------------------------------------------------------------------
* Function: H5A__get_type
*
@@ -883,7 +886,7 @@ done:
*
* Return: Success: A valid ID for the datatype of an attribute
*
- * Failure: H5I_INVALID_HID
+ * Failure: H5I_INVALID_HID
*
*-------------------------------------------------------------------------
*/
@@ -917,8 +920,18 @@ H5A__get_type(H5A_t *attr)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5I_INVALID_HID, "unable to lock transient datatype")
/* Atomize */
- if ((ret_value = H5I_register(H5I_DATATYPE, dt, TRUE)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register datatype")
+ if (H5T_is_named(dt)) {
+ /* If this is a committed datatype, we need to recreate the
+ * two level IDs, where the VOL object is a copy of the
+ * returned datatype
+ */
+ if ((ret_value = H5VL_wrap_register(H5I_DATATYPE, dt, TRUE)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to atomize file handle")
+ }
+ else {
+ if ((ret_value = H5I_register(H5I_DATATYPE, dt, TRUE)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register datatype")
+ }
done:
if(H5I_INVALID_HID == ret_value)
@@ -928,7 +941,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5A__get_type() */
-
+
/*--------------------------------------------------------------------------
NAME
H5A__get_create_plist
@@ -960,7 +973,7 @@ H5A__get_create_plist(H5A_t* attr)
/* Create the property list object to return */
if((new_plist_id = H5P_copy_plist(plist, TRUE)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "unable to copy attribute creation properties")
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "unable to copy attribute creation properties")
if(NULL == (new_plist = (H5P_genplist_t *)H5I_object(new_plist_id)))
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "can't get property list")
@@ -974,16 +987,16 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5A__get_create_plist() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5A__get_info
+ * Function: H5A__get_info
*
- * Purpose: Retrieve information about an attribute.
+ * Purpose: Retrieve information about an attribute.
*
- * Return: Success: Non-negative
- * Failure: Negative
+ * Return: Success: Non-negative
+ * Failure: Negative
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* February 6, 2007
*
*-------------------------------------------------------------------------
@@ -1015,7 +1028,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5A__get_info() */
-
+
/*-------------------------------------------------------------------------
* Function: H5A__copy
*
@@ -1025,17 +1038,17 @@ done:
*
* Failure: NULL
*
- * Programmer: Robb Matzke
- * Thursday, December 4, 1997
+ * Programmer: Robb Matzke
+ * Thursday, December 4, 1997
*
*-------------------------------------------------------------------------
*/
H5A_t *
H5A__copy(H5A_t *_new_attr, const H5A_t *old_attr)
{
- H5A_t *new_attr = NULL;
+ H5A_t *new_attr = NULL;
hbool_t allocated_attr = FALSE; /* Whether the attribute was allocated */
- H5A_t *ret_value = NULL; /* Return value */
+ H5A_t *ret_value = NULL; /* Return value */
FUNC_ENTER_PACKAGE
@@ -1078,52 +1091,59 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5A__copy() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5A__free
+ * Function: H5A__shared_free
+ *
+ * Purpose: Cleans up the shared attribute data. This will free
+ * the attribute's shared structure as well.
*
- * Purpose: Frees all memory associated with an attribute, but does not
- * free the H5A_t structure (which should be done in H5T_close).
+ * attr and attr->shared must not be NULL
*
* Return: SUCCEED/FAIL
*
- * Programmer: Quincey Koziol
- * Monday, November 15, 2004
+ * Programmer: Quincey Koziol
+ * Monday, November 15, 2004
*
*-------------------------------------------------------------------------
*/
herr_t
-H5A__free(H5A_t *attr)
+H5A__shared_free(H5A_t *attr)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
HDassert(attr);
+ HDassert(attr->shared);
- /* Free dynamically allocated items */
+ /* Free dynamically allocated items.
+ * When possible, keep trying to shut things down (via HDONE_ERROR).
+ */
if(attr->shared->name) {
H5MM_xfree(attr->shared->name);
attr->shared->name = NULL;
}
if(attr->shared->dt) {
if(H5T_close_real(attr->shared->dt) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release datatype info")
+ HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release datatype info")
attr->shared->dt = NULL;
}
if(attr->shared->ds) {
if(H5S_close(attr->shared->ds) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release dataspace info")
+ HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release dataspace info")
attr->shared->ds = NULL;
}
if(attr->shared->data)
attr->shared->data = H5FL_BLK_FREE(attr_buf, attr->shared->data);
-done:
+ /* Destroy shared attribute struct */
+ attr->shared = H5FL_FREE(H5A_shared_t, attr->shared);
+
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5A__free() */
+} /* end H5A__shared_free() */
+
-
/*-------------------------------------------------------------------------
* Function: H5A__close_cb
*
@@ -1134,25 +1154,28 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5A__close_cb(H5A_t *attr)
+H5A__close_cb(H5VL_object_t *attr_vol_obj)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
/* Sanity check */
- HDassert(attr);
- HDassert(attr->shared);
+ HDassert(attr_vol_obj);
/* Close the attribute */
- if(H5A__close(attr) < 0)
+ if((ret_value = H5VL_attr_close(attr_vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "problem closing attribute")
+ /* Free the VOL object */
+ if(H5VL_free_object(attr_vol_obj) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTDEC, FAIL, "unable to free VOL object")
+
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5A__close_cb() */
-
+
/*-------------------------------------------------------------------------
* Function: H5A__close
*
@@ -1160,8 +1183,8 @@ done:
*
* Return: SUCCEED/FAIL
*
- * Programmer: Robb Matzke
- * Monday, December 8, 1997
+ * Programmer: Robb Matzke
+ * Monday, December 8, 1997
*
*-------------------------------------------------------------------------
*/
@@ -1182,11 +1205,9 @@ H5A__close(H5A_t *attr)
/* Reference count can be 0. It only happens when H5A__create fails. */
if(attr->shared->nrefs <= 1) {
/* Free dynamically allocated items */
- if(H5A__free(attr) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release attribute info")
-
- /* Destroy shared attribute struct */
- attr->shared = H5FL_FREE(H5A_shared_t, attr->shared);
+ if(attr->shared)
+ if(H5A__shared_free(attr) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release attribute info")
} /* end if */
else {
/* There are other references to the shared part of the attribute.
@@ -1205,18 +1226,18 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5A__close() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5A_oloc
+ * Function: H5A_oloc
*
- * Purpose: Return the object location for an attribute. It's the
- * object location for the object to which the attribute
- * belongs, not the attribute itself.
+ * Purpose: Return the object location for an attribute. It's the
+ * object location for the object to which the attribute
+ * belongs, not the attribute itself.
*
- * Return: Success: Ptr to entry
- * Failure: NULL
+ * Return: Success: Ptr to entry
+ * Failure: NULL
*
- * Programmer: Robb Matzke
+ * Programmer: Robb Matzke
* Thursday, August 6, 1998
*
*-------------------------------------------------------------------------
@@ -1237,18 +1258,18 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5A_oloc() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5A_nameof
+ * Function: H5A_nameof
*
- * Purpose: Return the group hier. path for an attribute. It's the
- * group hier. path for the object to which the attribute
- * belongs, not the attribute itself.
+ * Purpose: Return the group hier. path for an attribute. It's the
+ * group hier. path for the object to which the attribute
+ * belongs, not the attribute itself.
*
- * Return: Success: Ptr to entry
- * Failure: NULL
+ * Return: Success: Ptr to entry
+ * Failure: NULL
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* Monday, September 12, 2005
*
*-------------------------------------------------------------------------
@@ -1269,7 +1290,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5A_nameof() */
-
+
/*-------------------------------------------------------------------------
* Function: H5A_type
*
@@ -1299,7 +1320,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5A_type() */
-
+
/*-------------------------------------------------------------------------
* Function: H5A__exists_by_name
*
@@ -1307,7 +1328,7 @@ done:
*
* Return: TRUE/FALSE/FAIL
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* Thursday, November 1, 2007
*
*-------------------------------------------------------------------------
@@ -1316,10 +1337,10 @@ htri_t
H5A__exists_by_name(H5G_loc_t loc, const char *obj_name, const char *attr_name)
{
H5G_loc_t obj_loc; /* Location used to open group */
- H5G_name_t obj_path; /* Opened object group hier. path */
- H5O_loc_t obj_oloc; /* Opened object object location */
+ H5G_name_t obj_path; /* Opened object group hier. path */
+ H5O_loc_t obj_oloc; /* Opened object object location */
hbool_t loc_found = FALSE; /* Entry at 'obj_name' found */
- htri_t ret_value = FAIL; /* Return value */
+ htri_t ret_value = FAIL; /* Return value */
FUNC_ENTER_PACKAGE
@@ -1345,18 +1366,18 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5A__exists_by_name() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5A__compact_build_table_cb
+ * Function: H5A__compact_build_table_cb
*
- * Purpose: Object header iterator callback routine to copy attribute
+ * Purpose: Object header iterator callback routine to copy attribute
* into table.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Dec 18 2006
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Dec 18 2006
*
* Modification:Raymond Lu
* 24 June 2008
@@ -1406,9 +1427,9 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5A__compact_build_table_cb() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5A__compact_build_table
+ * Function: H5A__compact_build_table
*
* Purpose: Builds a table containing a sorted list of attributes for
* an object
@@ -1418,8 +1439,8 @@ done:
*
* Return: SUCCEED/FAIL
*
- * Programmer: Quincey Koziol
- * Dec 18, 2006
+ * Programmer: Quincey Koziol
+ * Dec 18, 2006
*
*-------------------------------------------------------------------------
*/
@@ -1469,19 +1490,19 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5A__compact_build_table() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5A__dense_build_table_cb
+ * Function: H5A__dense_build_table_cb
*
- * Purpose: Callback routine for building table of attributes from dense
+ * Purpose: Callback routine for building table of attributes from dense
* attribute storage.
*
- * Return: Success: Non-negative
- * Failure: Negative
+ * Return: Success: Non-negative
+ * Failure: Negative
*
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Dec 11 2006
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Dec 11 2006
*
*-------------------------------------------------------------------------
*/
@@ -1513,7 +1534,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5A__dense_build_table_cb() */
-
+
/*-------------------------------------------------------------------------
* Function: H5A__dense_build_table
*
@@ -1526,8 +1547,8 @@ done:
*
* Return: SUCCEED/FAIL
*
- * Programmer: Quincey Koziol
- * Dec 11, 2006
+ * Programmer: Quincey Koziol
+ * Dec 11, 2006
*
*-------------------------------------------------------------------------
*/
@@ -1598,22 +1619,22 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5A__dense_build_table() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5A__attr_cmp_name_inc
+ * Function: H5A__attr_cmp_name_inc
*
- * Purpose: Callback routine for comparing two attribute names, in
+ * Purpose: Callback routine for comparing two attribute names, in
* increasing alphabetic order
*
- * Return: An integer less than, equal to, or greater than zero if the
+ * Return: An integer less than, equal to, or greater than zero if the
* first argument is considered to be respectively less than,
* equal to, or greater than the second. If two members compare
* as equal, their order in the sorted array is undefined.
* (i.e. same as strcmp())
*
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Dec 11 2006
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Dec 11 2006
*
*-------------------------------------------------------------------------
*/
@@ -1626,22 +1647,22 @@ H5A__attr_cmp_name_inc(const void *attr1, const void *attr2)
(*(const H5A_t * const *)attr2)->shared->name))
} /* end H5A__attr_cmp_name_inc() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5A__attr_cmp_name_dec
+ * Function: H5A__attr_cmp_name_dec
*
- * Purpose: Callback routine for comparing two attribute names, in
+ * Purpose: Callback routine for comparing two attribute names, in
* decreasing alphabetic order
*
- * Return: An integer less than, equal to, or greater than zero if the
+ * Return: An integer less than, equal to, or greater than zero if the
* second argument is considered to be respectively less than,
* equal to, or greater than the first. If two members compare
* as equal, their order in the sorted array is undefined.
* (i.e. opposite of strcmp())
*
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Feb 8 2007
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Feb 8 2007
*
*-------------------------------------------------------------------------
*/
@@ -1654,21 +1675,21 @@ H5A__attr_cmp_name_dec(const void *attr1, const void *attr2)
(*(const H5A_t * const *)attr1)->shared->name))
} /* end H5A__attr_cmp_name_dec() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5A__attr_cmp_corder_inc
+ * Function: H5A__attr_cmp_corder_inc
*
- * Purpose: Callback routine for comparing two attributes, in
+ * Purpose: Callback routine for comparing two attributes, in
* increasing creation order
*
- * Return: An integer less than, equal to, or greater than zero if the
+ * Return: An integer less than, equal to, or greater than zero if the
* first argument is considered to be respectively less than,
* equal to, or greater than the second. If two members compare
* as equal, their order in the sorted array is undefined.
*
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Feb 8 2007
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Feb 8 2007
*
*-------------------------------------------------------------------------
*/
@@ -1689,21 +1710,21 @@ H5A__attr_cmp_corder_inc(const void *attr1, const void *attr2)
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5A__attr_cmp_corder_inc() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5A__attr_cmp_corder_dec
+ * Function: H5A__attr_cmp_corder_dec
*
- * Purpose: Callback routine for comparing two attributes, in
+ * Purpose: Callback routine for comparing two attributes, in
* decreasing creation order
*
- * Return: An integer less than, equal to, or greater than zero if the
+ * Return: An integer less than, equal to, or greater than zero if the
* second argument is considered to be respectively less than,
* equal to, or greater than the first. If two members compare
* as equal, their order in the sorted array is undefined.
*
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Feb 8 2007
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Feb 8 2007
*
*-------------------------------------------------------------------------
*/
@@ -1724,17 +1745,17 @@ H5A__attr_cmp_corder_dec(const void *attr1, const void *attr2)
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5A__attr_cmp_corder_dec() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5A__attr_sort_table
+ * Function: H5A__attr_sort_table
*
* Purpose: Sort table containing a list of attributes for an object
*
- * Return: Success: Non-negative
- * Failure: Negative
+ * Return: Success: Non-negative
+ * Failure: Negative
*
- * Programmer: Quincey Koziol
- * Dec 11, 2006
+ * Programmer: Quincey Koziol
+ * Dec 11, 2006
*
*-------------------------------------------------------------------------
*/
@@ -1769,7 +1790,7 @@ H5A__attr_sort_table(H5A_attr_table_t *atable, H5_index_t idx_type,
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5A__attr_sort_table() */
-
+
/*-------------------------------------------------------------------------
* Function: H5A__attr_iterate_table
*
@@ -1778,8 +1799,8 @@ H5A__attr_sort_table(H5A_attr_table_t *atable, H5_index_t idx_type,
*
* Return: SUCCEED/FAIL
*
- * Programmer: Quincey Koziol
- * Dec 18, 2006
+ * Programmer: Quincey Koziol
+ * Dec 18, 2006
*
*-------------------------------------------------------------------------
*/
@@ -1851,7 +1872,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5A__attr_iterate_table() */
-
+
/*-------------------------------------------------------------------------
* Function: H5A__attr_release_table
*
@@ -1859,15 +1880,15 @@ done:
*
* Return: SUCCEED/FAIL
*
- * Programmer: Quincey Koziol
- * Dec 11, 2006
+ * Programmer: Quincey Koziol
+ * Dec 11, 2006
*
*-------------------------------------------------------------------------
*/
herr_t
H5A__attr_release_table(H5A_attr_table_t *atable)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
@@ -1892,7 +1913,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5A__attr_release_table() */
-
+
/*-------------------------------------------------------------------------
* Function: H5A__get_ainfo
*
@@ -1923,11 +1944,11 @@ H5A__get_ainfo(H5F_t *f, H5O_t *oh, H5O_ainfo_t *ainfo)
/* Check if the "attribute info" message exists */
if((ret_value = H5O_msg_exists_oh(oh, H5O_AINFO_ID)) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "unable to check object header")
+ HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "unable to check object header")
if(ret_value > 0) {
/* Retrieve the "attribute info" structure */
if(NULL == H5O_msg_read_oh(f, oh, H5O_AINFO_ID, ainfo))
- HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't read AINFO message")
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't read AINFO message")
/* Check if we don't know how many attributes there are */
if(ainfo->nattrs == HSIZET_MAX) {
@@ -1956,7 +1977,7 @@ done:
FUNC_LEAVE_NOAPI_TAG(ret_value)
} /* end H5A__get_ainfo() */
-
+
/*-------------------------------------------------------------------------
* Function: H5A__set_version
*
@@ -2018,7 +2039,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5A__set_version() */
-
+
/*-------------------------------------------------------------------------
* Function: H5A__attr_copy_file
*
@@ -2049,11 +2070,11 @@ H5A__attr_copy_file(const H5A_t *attr_src, H5F_t *file_dst, hbool_t *recompute_s
hid_t tid_mem = -1; /* Datatype ID for memory datatype */
void *buf = NULL; /* Buffer for copying data */
void *reclaim_buf = NULL; /* Buffer for reclaiming data */
- void *bkg_buf = NULL; /* Background buffer */
+ void *bkg_buf = NULL; /* Background buffer */
hid_t buf_sid = -1; /* ID for buffer dataspace */
- hssize_t sdst_nelmts; /* # of elements in destination attribute (signed) */
- size_t dst_nelmts; /* # of elements in destination attribute */
- size_t dst_dt_size; /* Size of destination attribute datatype */
+ hssize_t sdst_nelmts; /* # of elements in destination attribute (signed) */
+ size_t dst_nelmts; /* # of elements in destination attribute */
+ size_t dst_dt_size; /* Size of destination attribute datatype */
H5A_t *ret_value = NULL; /* Return value */
FUNC_ENTER_PACKAGE
@@ -2226,35 +2247,35 @@ H5A__attr_copy_file(const H5A_t *attr_src, H5F_t *file_dst, hbool_t *recompute_s
if(NULL == (buf = H5FL_BLK_MALLOC(attr_buf, buf_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation NULLed for raw data chunk")
- HDmemcpy(buf, attr_src->shared->data, attr_src->shared->data_size);
+ H5MM_memcpy(buf, attr_src->shared->data, attr_src->shared->data_size);
- /* Allocate background memory */
- if(H5T_path_bkg(tpath_src_mem) || H5T_path_bkg(tpath_mem_dst))
- if(NULL == (bkg_buf = H5FL_BLK_CALLOC(attr_buf, buf_size)))
- HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, NULL, "memory allocation failed")
+ /* Allocate background memory */
+ if(H5T_path_bkg(tpath_src_mem) || H5T_path_bkg(tpath_mem_dst))
+ if(NULL == (bkg_buf = H5FL_BLK_CALLOC(attr_buf, buf_size)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, NULL, "memory allocation failed")
/* Convert from source file to memory */
if(H5T_convert(tpath_src_mem, tid_src, tid_mem, nelmts, (size_t)0, (size_t)0, buf, bkg_buf) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "datatype conversion NULLed")
- HDmemcpy(reclaim_buf, buf, buf_size);
+ H5MM_memcpy(reclaim_buf, buf, buf_size);
- /* Set background buffer to all zeros */
- if(bkg_buf)
- HDmemset(bkg_buf, 0, buf_size);
+ /* Set background buffer to all zeros */
+ if(bkg_buf)
+ HDmemset(bkg_buf, 0, buf_size);
/* Convert from memory to destination file */
if(H5T_convert(tpath_mem_dst, tid_mem, tid_dst, nelmts, (size_t)0, (size_t)0, buf, bkg_buf) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "datatype conversion NULLed")
- HDmemcpy(attr_dst->shared->data, buf, attr_dst->shared->data_size);
+ H5MM_memcpy(attr_dst->shared->data, buf, attr_dst->shared->data_size);
- if(H5D_vlen_reclaim(tid_mem, buf_space, reclaim_buf) < 0)
+ if(H5T_reclaim(tid_mem, buf_space, reclaim_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_BADITER, NULL, "unable to reclaim variable-length data")
} /* end if */
else {
HDassert(attr_dst->shared->data_size == attr_src->shared->data_size);
- HDmemcpy(attr_dst->shared->data, attr_src->shared->data, attr_src->shared->data_size);
+ H5MM_memcpy(attr_dst->shared->data, attr_src->shared->data, attr_src->shared->data_size);
} /* end else */
} /* end if(attr_src->shared->data) */
@@ -2301,7 +2322,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5A__attr_copy_file() */
-
+
/*-------------------------------------------------------------------------
* Function: H5A__attr_post_copy_file
*
@@ -2339,7 +2360,7 @@ H5A__attr_post_copy_file(const H5O_loc_t *src_oloc, const H5A_t *attr_src,
HDassert(file_src);
HDassert(file_dst);
- if(H5T_is_named(attr_src->shared->dt)) {
+ if (H5T_is_named(attr_src->shared->dt)) {
H5O_loc_t *src_oloc_dt; /* Pointer to source datatype's object location */
H5O_loc_t *dst_oloc_dt; /* Pointer to dest. datatype's object location */
@@ -2380,13 +2401,9 @@ H5A__attr_post_copy_file(const H5O_loc_t *src_oloc, const H5A_t *attr_src,
/* Check for expanding references */
if(cpy_info->expand_ref) {
- size_t ref_count;
-
- /* Determine # of reference elements to copy */
- ref_count = attr_dst->shared->data_size / H5T_get_size(attr_dst->shared->dt);
-
/* Copy objects referenced in source buffer to destination file and set destination elements */
- if(H5O_copy_expand_ref(file_src, attr_dst->shared->data, file_dst, attr_dst->shared->data, ref_count, H5T_get_ref_type(attr_dst->shared->dt), cpy_info) < 0)
+ if(H5O_copy_expand_ref(file_src, H5I_INVALID_HID, attr_src->shared->dt,
+ attr_src->shared->data, attr_src->shared->data_size, file_dst, attr_dst->shared->data, cpy_info) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, FAIL, "unable to copy reference attribute")
} /* end if */
else
@@ -2398,7 +2415,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5A__attr_post_copy_file() */
-
+
/*-------------------------------------------------------------------------
* Function: H5A__dense_post_copy_file_cb
*
@@ -2456,7 +2473,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5A__dense_post_copy_file_cb() */
-
+
/*-------------------------------------------------------------------------
* Function: H5A__dense_post_copy_file_all
*
@@ -2503,7 +2520,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5A__dense_post_copy_file_all */
-
+
/*-------------------------------------------------------------------------
* Function: H5A__rename_by_name
*
@@ -2511,7 +2528,7 @@ done:
*
* Return: SUCCEED/FAIL
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* February 20, 2007
*
*-------------------------------------------------------------------------
@@ -2521,10 +2538,10 @@ H5A__rename_by_name(H5G_loc_t loc, const char *obj_name, const char *old_attr_na
const char *new_attr_name)
{
H5G_loc_t obj_loc; /* Location used to open group */
- H5G_name_t obj_path; /* Opened object group hier. path */
- H5O_loc_t obj_oloc; /* Opened object object location */
+ H5G_name_t obj_path; /* Opened object group hier. path */
+ H5O_loc_t obj_oloc; /* Opened object object location */
hbool_t loc_found = FALSE; /* Entry at 'obj_name' found */
- herr_t ret_value = SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
@@ -2553,7 +2570,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5A__rename_by_name() */
-
+
/*-------------------------------------------------------------------------
* Function: H5A__iterate_common
*
@@ -2561,7 +2578,7 @@ done:
*
* Return: SUCCEED/FAIL
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* December 6, 2017
*
*-------------------------------------------------------------------------
@@ -2588,7 +2605,7 @@ H5A__iterate_common(hid_t loc_id, H5_index_t idx_type, H5_iter_order_t order,
FUNC_LEAVE_NOAPI(ret_value)
} /* H5A__iterate_common() */
-
+
/*-------------------------------------------------------------------------
* Function: H5A__iterate
*
@@ -2596,16 +2613,20 @@ H5A__iterate_common(hid_t loc_id, H5_index_t idx_type, H5_iter_order_t order,
*
* Return: SUCCEED/FAIL
*
- * Programmer: Quincey Koziol
- * December 6, 2017
- *
*-------------------------------------------------------------------------
*/
herr_t
-H5A__iterate(hid_t loc_id, H5_index_t idx_type, H5_iter_order_t order,
+H5A__iterate(const H5G_loc_t *loc, const char *obj_name, H5_index_t idx_type, H5_iter_order_t order,
hsize_t *idx, H5A_operator2_t op, void *op_data)
{
+ H5G_loc_t obj_loc; /* Location used to open group */
+ H5G_name_t obj_path; /* Opened object group hier. path */
+ H5O_loc_t obj_oloc; /* Opened object object location */
+ hbool_t loc_found = FALSE; /* Entry at 'obj_name' found */
+ hid_t obj_loc_id = H5I_INVALID_HID; /* ID for object located */
H5A_attr_iter_op_t attr_op; /* Attribute operator */
+ void *temp_obj = NULL;
+ H5I_type_t obj_type;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
@@ -2614,16 +2635,42 @@ H5A__iterate(hid_t loc_id, H5_index_t idx_type, H5_iter_order_t order,
attr_op.op_type = H5A_ATTR_OP_APP2;
attr_op.u.app_op2 = op;
+ /* Set up opened group location to fill in */
+ obj_loc.oloc = &obj_oloc;
+ obj_loc.path = &obj_path;
+ H5G_loc_reset(&obj_loc);
+
+ /* Find the object's location */
+ if(H5G_loc_find(loc, obj_name, &obj_loc) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "object not found");
+ loc_found = TRUE;
+
+ /* Open the object */
+ if(NULL == (temp_obj = H5O_open_by_loc(&obj_loc, &obj_type)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open object");
+
+ /* Get an ID for the object */
+ if((obj_loc_id = H5VL_wrap_register(obj_type, temp_obj, TRUE)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register datatype");
+
/* Call internal attribute iteration routine */
- if((ret_value = H5A__iterate_common(loc_id, idx_type, order, idx, &attr_op, op_data)) < 0)
+ if((ret_value = H5A__iterate_common(obj_loc_id, idx_type, order, idx, &attr_op, op_data)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_BADITER, FAIL, "error iterating over attributes")
done:
+ /* Release resources */
+ if(obj_loc_id != H5I_INVALID_HID) {
+ if(H5I_dec_app_ref(obj_loc_id) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_CANTDEC, FAIL, "unable to close temporary object");
+ } /* end if */
+ else if(loc_found && H5G_loc_free(&obj_loc) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't free location");
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5A__iterate() */
#ifndef H5_NO_DEPRECATED_SYMBOLS
-
+
/*-------------------------------------------------------------------------
* Function: H5A__iterate_old
*
@@ -2631,7 +2678,7 @@ done:
*
* Return: SUCCEED/FAIL
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* December 6, 2017
*
*-------------------------------------------------------------------------
@@ -2644,7 +2691,7 @@ H5A__iterate_old(hid_t loc_id, unsigned *attr_num, H5A_operator1_t op,
hsize_t idx; /* Index of attribute to start iterating at */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_PACKAGE
+ FUNC_ENTER_PACKAGE_NOERR
/* Build attribute operator info */
attr_op.op_type = H5A_ATTR_OP_APP;
@@ -2655,87 +2702,25 @@ H5A__iterate_old(hid_t loc_id, unsigned *attr_num, H5A_operator1_t op,
/* Call internal attribute iteration routine */
if((ret_value = H5A__iterate_common(loc_id, H5_INDEX_CRT_ORDER, H5_ITER_INC, &idx, &attr_op, op_data)) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_BADITER, FAIL, "error iterating over attributes")
+ HERROR(H5E_ATTR, H5E_BADITER, "error iterating over attributes");
/* Translate hsize_t index value to legacy unsigned index value*/
if(attr_num)
*attr_num = (unsigned)idx;
-done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5A__iterate_old() */
#endif /* H5_NO_DEPRECATED_SYMBOLS */
-
-/*-------------------------------------------------------------------------
- * Function: H5A__iterate_by_name
- *
- * Purpose: Private version of H5Aiterate_by_name
- *
- * Return: SUCCEED/FAIL
- *
- * Programmer: Quincey Koziol
- * December 6, 2017
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5A__iterate_by_name(const H5G_loc_t *loc, const char *obj_name, H5_index_t idx_type, H5_iter_order_t order, hsize_t *idx, H5A_operator2_t op,
- void *op_data)
-{
- H5G_loc_t obj_loc; /* Location used to open group */
- H5G_name_t obj_path; /* Opened object group hier. path */
- H5O_loc_t obj_oloc; /* Opened object object location */
- hbool_t loc_found = FALSE; /* Entry at 'obj_name' found */
- hid_t obj_loc_id = (-1); /* ID for object located */
- H5A_attr_iter_op_t attr_op; /* Attribute operator */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_PACKAGE
-
- /* Set up opened group location to fill in */
- obj_loc.oloc = &obj_oloc;
- obj_loc.path = &obj_path;
- H5G_loc_reset(&obj_loc);
-
- /* Find the object's location */
- if(H5G_loc_find(loc, obj_name, &obj_loc/*out*/) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "object not found")
- loc_found = TRUE;
-
- /* Open the object */
- if((obj_loc_id = H5O_open_by_loc(&obj_loc, TRUE)) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open object")
- /* Build attribute operator info */
- attr_op.op_type = H5A_ATTR_OP_APP2;
- attr_op.u.app_op2 = op;
-
- /* Call attribute iteration routine */
- if((ret_value = H5A__iterate_common(obj_loc_id, idx_type, order, idx, &attr_op, op_data)) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_BADITER, FAIL, "error iterating over attributes")
-
-done:
- /* Release resources */
- if(obj_loc_id > 0) {
- if(H5I_dec_app_ref(obj_loc_id) < 0)
- HDONE_ERROR(H5E_ATTR, H5E_CANTDEC, FAIL, "unable to close temporary object")
- }
- else if(loc_found && H5G_loc_free(&obj_loc) < 0)
- HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't free location")
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5A__iterate_by_name() */
-
-
/*-------------------------------------------------------------------------
- * Function: H5A__delete_by_name
+ * Function: H5A__delete_by_name
*
* Purpose: Private version of H5Adelete_by_name
*
* Return: SUCCEED/FAIL
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* December 6, 2017
*
*-------------------------------------------------------------------------
@@ -2744,8 +2729,8 @@ herr_t
H5A__delete_by_name(const H5G_loc_t *loc, const char *obj_name, const char *attr_name)
{
H5G_loc_t obj_loc; /* Location used to open group */
- H5G_name_t obj_path; /* Opened object group hier. path */
- H5O_loc_t obj_oloc; /* Opened object object location */
+ H5G_name_t obj_path; /* Opened object group hier. path */
+ H5O_loc_t obj_oloc; /* Opened object object location */
hbool_t loc_found = FALSE; /* Entry at 'obj_name' found */
herr_t ret_value = SUCCEED; /* Return value */
@@ -2773,15 +2758,15 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5A__delete_by_name() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5A__delete_by_idx
+ * Function: H5A__delete_by_idx
*
* Purpose: Private version of H5Adelete_by_idx
*
* Return: SUCCEED/FAIL
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* December 6, 2017
*
*-------------------------------------------------------------------------
@@ -2791,8 +2776,8 @@ H5A__delete_by_idx(const H5G_loc_t *loc, const char *obj_name, H5_index_t idx_ty
H5_iter_order_t order, hsize_t n)
{
H5G_loc_t obj_loc; /* Location used to open group */
- H5G_name_t obj_path; /* Opened object group hier. path */
- H5O_loc_t obj_oloc; /* Opened object object location */
+ H5G_name_t obj_path; /* Opened object group hier. path */
+ H5O_loc_t obj_oloc; /* Opened object object location */
hbool_t loc_found = FALSE; /* Entry at 'obj_name' found */
herr_t ret_value = SUCCEED; /* Return value */
diff --git a/src/H5Apkg.h b/src/H5Apkg.h
index 85f0254..f3870c0 100644
--- a/src/H5Apkg.h
+++ b/src/H5Apkg.h
@@ -196,18 +196,15 @@ H5_DLL H5A_t *H5A__copy(H5A_t *new_attr, const H5A_t *old_attr);
H5_DLL hid_t H5A__get_type(H5A_t *attr);
H5_DLL herr_t H5A__get_info(const H5A_t *attr, H5A_info_t *ainfo);
H5_DLL hid_t H5A__get_create_plist(H5A_t* attr);
-H5_DLL herr_t H5A__free(H5A_t *attr);
+H5_DLL herr_t H5A__shared_free(H5A_t *attr);
H5_DLL herr_t H5A__close(H5A_t *attr);
-H5_DLL herr_t H5A__close_cb(H5A_t *attr);
+H5_DLL herr_t H5A__close_cb(H5VL_object_t *attr_vol_obj);
H5_DLL htri_t H5A__get_ainfo(H5F_t *f, H5O_t *oh, H5O_ainfo_t *ainfo);
H5_DLL herr_t H5A__set_version(const H5F_t *f, H5A_t *attr);
H5_DLL herr_t H5A__rename_by_name(H5G_loc_t loc, const char *obj_name, const char *old_attr_name,
const char *new_attr_name);
-H5_DLL herr_t H5A__iterate(hid_t loc_id, H5_index_t idx_type, H5_iter_order_t order,
+H5_DLL herr_t H5A__iterate(const H5G_loc_t *loc, const char *obj_name,H5_index_t idx_type, H5_iter_order_t order,
hsize_t *idx, H5A_operator2_t op, void *op_data);
-H5_DLL herr_t H5A__iterate_by_name(const H5G_loc_t *loc, const char *obj_name,
- H5_index_t idx_type, H5_iter_order_t order, hsize_t *idx, H5A_operator2_t op,
- void *op_data);
#ifndef H5_NO_DEPRECATED_SYMBOLS
H5_DLL herr_t H5A__iterate_old(hid_t loc_id, unsigned *attr_num,
H5A_operator1_t op, void *op_data);
diff --git a/src/H5Apublic.h b/src/H5Apublic.h
index 586940b..7162f6e 100644
--- a/src/H5Apublic.h
+++ b/src/H5Apublic.h
@@ -22,10 +22,6 @@
#include "H5Opublic.h" /* Object Headers */
#include "H5Tpublic.h" /* Datatypes */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
/* Information struct for attribute (for H5Aget_info/H5Aget_info_by_idx) */
typedef struct {
hbool_t corder_valid; /* Indicate if creation order is valid */
@@ -38,7 +34,19 @@ typedef struct {
typedef herr_t (*H5A_operator2_t)(hid_t location_id/*in*/,
const char *attr_name/*in*/, const H5A_info_t *ainfo/*in*/, void *op_data/*in,out*/);
-/* Public function prototypes */
+
+/********************/
+/* Public Variables */
+/********************/
+
+
+/*********************/
+/* Public Prototypes */
+/*********************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
H5_DLL hid_t H5Acreate2(hid_t loc_id, const char *attr_name, hid_t type_id,
hid_t space_id, hid_t acpl_id, hid_t aapl_id);
H5_DLL hid_t H5Acreate_by_name(hid_t loc_id, const char *obj_name, const char *attr_name,
diff --git a/src/H5Atest.c b/src/H5Atest.c
index 36c3d35..6fc1cbf 100644
--- a/src/H5Atest.c
+++ b/src/H5Atest.c
@@ -38,6 +38,7 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5Iprivate.h" /* IDs */
#include "H5SMprivate.h" /* Shared object header messages */
+#include "H5VLprivate.h" /* Virtual Object Layer */
/****************/
@@ -96,7 +97,7 @@ H5A__is_shared_test(hid_t attr_id)
FUNC_ENTER_PACKAGE
/* Check arguments */
- if(NULL == (attr = (H5A_t *)H5I_object_verify(attr_id, H5I_ATTR)))
+ if(NULL == (attr = (H5A_t *)H5VL_object_verify(attr_id, H5I_ATTR)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an attribute")
/* Check if attribute is shared */
@@ -129,7 +130,7 @@ H5A__get_shared_rc_test(hid_t attr_id, hsize_t *ref_count)
FUNC_ENTER_PACKAGE
/* Check arguments */
- if(NULL == (attr = (H5A_t *)H5I_object_verify(attr_id, H5I_ATTR)))
+ if(NULL == (attr = (H5A_t *)H5VL_object_verify(attr_id, H5I_ATTR)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an attribute")
/* Push API context */
diff --git a/src/H5B.c b/src/H5B.c
index 71b9020..2a34fae 100644
--- a/src/H5B.c
+++ b/src/H5B.c
@@ -107,6 +107,7 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5Iprivate.h" /* IDs */
#include "H5MFprivate.h" /* File memory management */
+#include "H5MMprivate.h" /* Memory management */
#include "H5Pprivate.h" /* Property lists */
@@ -436,8 +437,8 @@ H5B__split(H5F_t *f, H5B_ins_ud_t *bt_ud, unsigned idx,
side = "LEFT";
else
side = "MIDDLE";
- fprintf(H5DEBUG(B), "H5B__split: %3u {%5.3f,%5.3f,%5.3f} %6s",
- shared->two_k, split_ratios[0], split_ratios[1], split_ratios[2], side);
+ HDfprintf(H5DEBUG(B), "H5B__split: %3u {%5.3f,%5.3f,%5.3f} %6s",
+ shared->two_k, split_ratios[0], split_ratios[1], split_ratios[2], side);
}
#endif
@@ -464,7 +465,7 @@ H5B__split(H5F_t *f, H5B_ins_ud_t *bt_ud, unsigned idx,
nright = shared->two_k - nleft;
#ifdef H5B_DEBUG
if(H5DEBUG(B))
- fprintf(H5DEBUG(B), " split %3d/%-3d\n", nleft, nright);
+ HDfprintf(H5DEBUG(B), " split %3d/%-3d\n", nleft, nright);
#endif
/*
@@ -484,10 +485,10 @@ H5B__split(H5F_t *f, H5B_ins_ud_t *bt_ud, unsigned idx,
*/
split_bt_ud->cache_flags = H5AC__DIRTIED_FLAG;
- HDmemcpy(split_bt_ud->bt->native,
+ H5MM_memcpy(split_bt_ud->bt->native,
bt_ud->bt->native + nleft * shared->type->sizeof_nkey,
(nright + 1) * shared->type->sizeof_nkey);
- HDmemcpy(split_bt_ud->bt->child,
+ H5MM_memcpy(split_bt_ud->bt->child,
&bt_ud->bt->child[nleft],
nright * sizeof(haddr_t));
@@ -612,9 +613,9 @@ H5B_insert(H5F_t *f, const H5B_class_t *type, haddr_t addr, void *udata)
/* update left and right keys */
if(!lt_key_changed)
- HDmemcpy(lt_key, H5B_NKEY(bt_ud.bt,shared,0), type->sizeof_nkey);
+ H5MM_memcpy(lt_key, H5B_NKEY(bt_ud.bt,shared,0), type->sizeof_nkey);
if(!rt_key_changed)
- HDmemcpy(rt_key, H5B_NKEY(split_bt_ud.bt,shared,split_bt_ud.bt->nchildren), type->sizeof_nkey);
+ H5MM_memcpy(rt_key, H5B_NKEY(split_bt_ud.bt,shared,split_bt_ud.bt->nchildren), type->sizeof_nkey);
/*
* Copy the old root node to some other file location and make the new root
@@ -657,11 +658,11 @@ H5B_insert(H5F_t *f, const H5B_class_t *type, haddr_t addr, void *udata)
new_root_bt->nchildren = 2;
new_root_bt->child[0] = bt_ud.addr;
- HDmemcpy(H5B_NKEY(new_root_bt, shared, 0), lt_key, shared->type->sizeof_nkey);
+ H5MM_memcpy(H5B_NKEY(new_root_bt, shared, 0), lt_key, shared->type->sizeof_nkey);
new_root_bt->child[1] = split_bt_ud.addr;
- HDmemcpy(H5B_NKEY(new_root_bt, shared, 1), md_key, shared->type->sizeof_nkey);
- HDmemcpy(H5B_NKEY(new_root_bt, shared, 2), rt_key, shared->type->sizeof_nkey);
+ H5MM_memcpy(H5B_NKEY(new_root_bt, shared, 1), md_key, shared->type->sizeof_nkey);
+ H5MM_memcpy(H5B_NKEY(new_root_bt, shared, 2), rt_key, shared->type->sizeof_nkey);
/* Insert the modified copy of the old root into the file again */
if(H5AC_insert_entry(f, H5AC_BT, addr, new_root_bt, H5AC__NO_FLAGS_SET) < 0)
@@ -726,9 +727,9 @@ H5B__insert_child(H5B_t *bt, unsigned *bt_flags, unsigned idx,
base = H5B_NKEY(bt, shared, (idx + 1));
if((idx + 1) == bt->nchildren) {
/* Make room for the new key */
- HDmemcpy(base + shared->type->sizeof_nkey, base,
+ H5MM_memcpy(base + shared->type->sizeof_nkey, base,
shared->type->sizeof_nkey); /* No overlap possible - memcpy() OK */
- HDmemcpy(base, md_key, shared->type->sizeof_nkey);
+ H5MM_memcpy(base, md_key, shared->type->sizeof_nkey);
/* The MD_KEY is the left key of the new node */
if(H5B_INS_RIGHT == anchor)
@@ -741,7 +742,7 @@ H5B__insert_child(H5B_t *bt, unsigned *bt_flags, unsigned idx,
/* Make room for the new key */
HDmemmove(base + shared->type->sizeof_nkey, base,
(bt->nchildren - idx) * shared->type->sizeof_nkey);
- HDmemcpy(base, md_key, shared->type->sizeof_nkey);
+ H5MM_memcpy(base, md_key, shared->type->sizeof_nkey);
/* The MD_KEY is the left key of the new node */
if(H5B_INS_RIGHT == anchor)
@@ -915,7 +916,7 @@ H5B__insert_helper(H5F_t *f, H5B_ins_ud_t *bt_ud, const H5B_class_t *type,
* node. This node is not empty (handled above).
*/
my_ins = H5B_INS_LEFT;
- HDmemcpy(md_key, H5B_NKEY(bt,shared,idx), type->sizeof_nkey);
+ H5MM_memcpy(md_key, H5B_NKEY(bt,shared,idx), type->sizeof_nkey);
if((type->new_node)(f, H5B_INS_LEFT, H5B_NKEY(bt, shared, idx), udata,
md_key, &new_child_bt_ud.addr/*out*/) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, H5B_INS_ERROR, "can't insert minimum leaf node")
@@ -963,7 +964,7 @@ H5B__insert_helper(H5F_t *f, H5B_ins_ud_t *bt_ud, const H5B_class_t *type,
*/
idx = bt->nchildren - 1;
my_ins = H5B_INS_RIGHT;
- HDmemcpy(md_key, H5B_NKEY(bt, shared, idx + 1), type->sizeof_nkey);
+ H5MM_memcpy(md_key, H5B_NKEY(bt, shared, idx + 1), type->sizeof_nkey);
if((type->new_node)(f, H5B_INS_RIGHT, md_key, udata,
H5B_NKEY(bt, shared, idx + 1), &new_child_bt_ud.addr/*out*/) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, H5B_INS_ERROR, "can't insert maximum leaf node")
@@ -1021,7 +1022,7 @@ H5B__insert_helper(H5F_t *f, H5B_ins_ud_t *bt_ud, const H5B_class_t *type,
*lt_key_changed = FALSE;
} /* end if */
else
- HDmemcpy(lt_key, H5B_NKEY(bt, shared, idx), type->sizeof_nkey);
+ H5MM_memcpy(lt_key, H5B_NKEY(bt, shared, idx), type->sizeof_nkey);
} /* end if */
if(*rt_key_changed) {
bt_ud->cache_flags |= H5AC__DIRTIED_FLAG;
@@ -1031,7 +1032,7 @@ H5B__insert_helper(H5F_t *f, H5B_ins_ud_t *bt_ud, const H5B_class_t *type,
*rt_key_changed = FALSE;
} /* end if */
else
- HDmemcpy(rt_key, H5B_NKEY(bt, shared, idx + 1), type->sizeof_nkey);
+ H5MM_memcpy(rt_key, H5B_NKEY(bt, shared, idx + 1), type->sizeof_nkey);
} /* end if */
/*
@@ -1080,7 +1081,7 @@ H5B__insert_helper(H5F_t *f, H5B_ins_ud_t *bt_ud, const H5B_class_t *type,
* by the left and right node).
*/
if(split_bt_ud->bt) {
- HDmemcpy(md_key, H5B_NKEY(split_bt_ud->bt, shared, 0), type->sizeof_nkey);
+ H5MM_memcpy(md_key, H5B_NKEY(split_bt_ud->bt, shared, 0), type->sizeof_nkey);
ret_value = H5B_INS_RIGHT;
#ifdef H5B_DEBUG
/*
@@ -1339,7 +1340,7 @@ H5B__remove_helper(H5F_t *f, haddr_t addr, const H5B_class_t *type, int level,
/* Don't propagate change out of this B-tree node */
*lt_key_changed = FALSE;
else
- HDmemcpy(lt_key, H5B_NKEY(bt, shared, idx), type->sizeof_nkey);
+ H5MM_memcpy(lt_key, H5B_NKEY(bt, shared, idx), type->sizeof_nkey);
} /* end if */
if(*rt_key_changed) {
HDassert(type->critical_key == H5B_RIGHT);
@@ -1348,7 +1349,7 @@ H5B__remove_helper(H5F_t *f, haddr_t addr, const H5B_class_t *type, int level,
/* Don't propagate change out of this B-tree node */
*rt_key_changed = FALSE;
else
- HDmemcpy(rt_key, H5B_NKEY(bt, shared, idx + 1), type->sizeof_nkey);
+ H5MM_memcpy(rt_key, H5B_NKEY(bt, shared, idx + 1), type->sizeof_nkey);
} /* end if */
/*
@@ -1383,7 +1384,7 @@ H5B__remove_helper(H5F_t *f, haddr_t addr, const H5B_class_t *type, int level,
* in its left neighbor, but only if it is not the critical
* key for the right-most child of the left neighbor */
if(type->critical_key == H5B_LEFT)
- HDmemcpy(H5B_NKEY(sibling, shared, sibling->nchildren),
+ H5MM_memcpy(H5B_NKEY(sibling, shared, sibling->nchildren),
H5B_NKEY(bt, shared, 1), type->sizeof_nkey);
sibling->right = bt->right;
@@ -1400,7 +1401,7 @@ H5B__remove_helper(H5F_t *f, haddr_t addr, const H5B_class_t *type, int level,
* its right neighbor, but only if it is not the critical
* key for the left-most child of the right neighbor */
if(type->critical_key == H5B_RIGHT)
- HDmemcpy(H5B_NKEY(sibling, shared, 0),
+ H5MM_memcpy(H5B_NKEY(sibling, shared, 0),
H5B_NKEY(bt, shared, 0), type->sizeof_nkey);
sibling->left = bt->left;
@@ -1442,7 +1443,7 @@ H5B__remove_helper(H5F_t *f, haddr_t addr, const H5B_class_t *type, int level,
/* Slide all keys down 1, update lt_key */
HDmemmove(H5B_NKEY(bt, shared, 0), H5B_NKEY(bt, shared, 1),
bt->nchildren * type->sizeof_nkey);
- HDmemcpy(lt_key, H5B_NKEY(bt, shared, 0), type->sizeof_nkey);
+ H5MM_memcpy(lt_key, H5B_NKEY(bt, shared, 0), type->sizeof_nkey);
*lt_key_changed = TRUE;
} else
/* Slide all but the leftmost 2 keys down, leaving the leftmost
@@ -1471,7 +1472,7 @@ H5B__remove_helper(H5F_t *f, haddr_t addr, const H5B_class_t *type, int level,
H5B_NKEY(bt, shared, bt->nchildren), type->sizeof_nkey);
else {
/* Just update rt_key */
- HDmemcpy(rt_key, H5B_NKEY(bt, shared, bt->nchildren - 1),
+ H5MM_memcpy(rt_key, H5B_NKEY(bt, shared, bt->nchildren - 1),
type->sizeof_nkey);
*rt_key_changed = TRUE;
} /* end else */
@@ -1516,7 +1517,7 @@ H5B__remove_helper(H5F_t *f, haddr_t addr, const H5B_class_t *type, int level,
if(NULL == (sibling = (H5B_t *)H5AC_protect(f, H5AC_BT, bt->left, &cache_udata, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, H5B_INS_ERROR, "unable to protect node")
- HDmemcpy(H5B_NKEY(sibling, shared, sibling->nchildren),
+ H5MM_memcpy(H5B_NKEY(sibling, shared, sibling->nchildren),
H5B_NKEY(bt, shared, 0), type->sizeof_nkey);
if(H5AC_unprotect(f, H5AC_BT, bt->left, sibling, H5AC__DIRTIED_FLAG) < 0)
@@ -1531,7 +1532,7 @@ H5B__remove_helper(H5F_t *f, haddr_t addr, const H5B_class_t *type, int level,
if(NULL == (sibling = (H5B_t *)H5AC_protect(f, H5AC_BT, bt->right, &cache_udata, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, H5B_INS_ERROR, "unable to protect node")
- HDmemcpy(H5B_NKEY(sibling, shared, 0),
+ H5MM_memcpy(H5B_NKEY(sibling, shared, 0),
H5B_NKEY(bt, shared, bt->nchildren), type->sizeof_nkey);
if(H5AC_unprotect(f, H5AC_BT, bt->right, sibling, H5AC__DIRTIED_FLAG) < 0)
@@ -1811,7 +1812,7 @@ H5B__copy(const H5B_t *old_bt)
HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, NULL, "memory allocation failed for B-tree root node")
/* Copy the main structure */
- HDmemcpy(new_node, old_bt, sizeof(H5B_t));
+ H5MM_memcpy(new_node, old_bt, sizeof(H5B_t));
/* Reset cache info */
HDmemset(&new_node->cache_info, 0, sizeof(H5AC_info_t));
@@ -1821,8 +1822,8 @@ H5B__copy(const H5B_t *old_bt)
HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, NULL, "memory allocation failed for B-tree root node")
/* Copy the other structures */
- HDmemcpy(new_node->native, old_bt->native, shared->sizeof_keys);
- HDmemcpy(new_node->child, old_bt->child, (sizeof(haddr_t) * shared->two_k));
+ H5MM_memcpy(new_node->native, old_bt->native, shared->sizeof_keys);
+ H5MM_memcpy(new_node->child, old_bt->child, (sizeof(haddr_t) * shared->two_k));
/* Increment the ref-count on the raw page */
H5UC_INC(new_node->rc_shared);
diff --git a/src/H5B2.c b/src/H5B2.c
index cf8e4a9..6b0d7a3 100644
--- a/src/H5B2.c
+++ b/src/H5B2.c
@@ -662,7 +662,7 @@ H5B2_find(H5B2_t *bt2, void *udata, H5B2_found_t op, void *op_data)
if(hdr->min_native_rec == NULL)
if(NULL == (hdr->min_native_rec = H5MM_malloc(hdr->cls->nrec_size)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, FAIL, "memory allocation failed for v2 B-tree min record info")
- HDmemcpy(hdr->min_native_rec, H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size);
+ H5MM_memcpy(hdr->min_native_rec, H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size);
} /* end if */
} /* end if */
if(idx == (unsigned)(leaf->nrec - 1)) {
@@ -670,7 +670,7 @@ H5B2_find(H5B2_t *bt2, void *udata, H5B2_found_t op, void *op_data)
if(hdr->max_native_rec == NULL)
if(NULL == (hdr->max_native_rec = H5MM_malloc(hdr->cls->nrec_size)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, FAIL, "memory allocation failed for v2 B-tree max record info")
- HDmemcpy(hdr->max_native_rec, H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size);
+ H5MM_memcpy(hdr->max_native_rec, H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size);
} /* end if */
} /* end if */
} /* end if */
@@ -1343,7 +1343,7 @@ H5B2_modify(H5B2_t *bt2, void *udata, H5B2_modify_t op, void *op_data)
if(hdr->min_native_rec == NULL)
if(NULL == (hdr->min_native_rec = H5MM_malloc(hdr->cls->nrec_size)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, FAIL, "memory allocation failed for v2 B-tree min record info")
- HDmemcpy(hdr->min_native_rec, H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size);
+ H5MM_memcpy(hdr->min_native_rec, H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size);
} /* end if */
} /* end if */
if(idx == (unsigned)(leaf->nrec - 1)) {
@@ -1351,7 +1351,7 @@ H5B2_modify(H5B2_t *bt2, void *udata, H5B2_modify_t op, void *op_data)
if(hdr->max_native_rec == NULL)
if(NULL == (hdr->max_native_rec = H5MM_malloc(hdr->cls->nrec_size)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, FAIL, "memory allocation failed for v2 B-tree max record info")
- HDmemcpy(hdr->max_native_rec, H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size);
+ H5MM_memcpy(hdr->max_native_rec, H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size);
} /* end if */
} /* end if */
} /* end if */
diff --git a/src/H5B2cache.c b/src/H5B2cache.c
index 8b89d5b..6efacee 100644
--- a/src/H5B2cache.c
+++ b/src/H5B2cache.c
@@ -394,7 +394,7 @@ H5B2__cache_hdr_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_UNUSED le
HDassert(hdr);
/* Magic number */
- HDmemcpy(image, H5B2_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ H5MM_memcpy(image, H5B2_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
image += H5_SIZEOF_MAGIC;
/* Version # */
@@ -814,7 +814,7 @@ H5B2__cache_int_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_UNUSED le
HDassert(internal->hdr);
/* Magic number */
- HDmemcpy(image, H5B2_INT_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ H5MM_memcpy(image, H5B2_INT_MAGIC, (size_t)H5_SIZEOF_MAGIC);
image += H5_SIZEOF_MAGIC;
/* Version # */
@@ -1215,7 +1215,7 @@ H5B2__cache_leaf_serialize(const H5F_t H5_ATTR_UNUSED *f, void *_image, size_t H
HDassert(leaf->hdr);
/* magic number */
- HDmemcpy(image, H5B2_LEAF_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ H5MM_memcpy(image, H5B2_LEAF_MAGIC, (size_t)H5_SIZEOF_MAGIC);
image += H5_SIZEOF_MAGIC;
/* version # */
diff --git a/src/H5B2int.c b/src/H5B2int.c
index b3f855f..2d77276 100644
--- a/src/H5B2int.c
+++ b/src/H5B2int.c
@@ -35,6 +35,7 @@
#include "H5private.h" /* Generic Functions */
#include "H5B2pkg.h" /* v2 B-trees */
#include "H5Eprivate.h" /* Error handling */
+#include "H5MMprivate.h" /* Memory management */
#include "H5VMprivate.h" /* Vectors and arrays */
@@ -241,17 +242,17 @@ H5B2__split1(H5B2_hdr_t *hdr, uint16_t depth, H5B2_node_ptr_t *curr_node_ptr,
mid_record = old_node_nrec / 2;
/* Copy "upper half" of records to new child */
- HDmemcpy(H5B2_NAT_NREC(right_native, hdr, 0),
+ H5MM_memcpy(H5B2_NAT_NREC(right_native, hdr, 0),
H5B2_NAT_NREC(left_native, hdr, mid_record + (unsigned)1),
hdr->cls->nrec_size * (old_node_nrec - (mid_record + (unsigned)1)));
/* Copy "upper half" of node pointers, if the node is an internal node */
if(depth > 1)
- HDmemcpy(&(right_node_ptrs[0]), &(left_node_ptrs[mid_record + (unsigned)1]),
+ H5MM_memcpy(&(right_node_ptrs[0]), &(left_node_ptrs[mid_record + (unsigned)1]),
sizeof(H5B2_node_ptr_t) * (size_t)(old_node_nrec - mid_record));
/* Copy "middle" record to internal node */
- HDmemcpy(H5B2_INT_NREC(internal, hdr, idx), H5B2_NAT_NREC(left_native, hdr, mid_record), hdr->cls->nrec_size);
+ H5MM_memcpy(H5B2_INT_NREC(internal, hdr, idx), H5B2_NAT_NREC(left_native, hdr, mid_record), hdr->cls->nrec_size);
/* Mark nodes as dirty */
left_child_flags |= H5AC__DIRTIED_FLAG;
@@ -510,14 +511,14 @@ H5B2__redistribute2(H5B2_hdr_t *hdr, uint16_t depth, H5B2_internal_t *internal,
uint16_t move_nrec = (uint16_t)(*right_nrec - new_right_nrec); /* Number of records to move from right node to left */
/* Copy record from parent node down into left child */
- HDmemcpy(H5B2_NAT_NREC(left_native, hdr, *left_nrec), H5B2_INT_NREC(internal, hdr, idx), hdr->cls->nrec_size);
+ H5MM_memcpy(H5B2_NAT_NREC(left_native, hdr, *left_nrec), H5B2_INT_NREC(internal, hdr, idx), hdr->cls->nrec_size);
/* See if we need to move records from right node */
if(move_nrec > 1)
- HDmemcpy(H5B2_NAT_NREC(left_native, hdr, (*left_nrec + 1)), H5B2_NAT_NREC(right_native, hdr, 0), hdr->cls->nrec_size * (size_t)(move_nrec - 1));
+ H5MM_memcpy(H5B2_NAT_NREC(left_native, hdr, (*left_nrec + 1)), H5B2_NAT_NREC(right_native, hdr, 0), hdr->cls->nrec_size * (size_t)(move_nrec - 1));
/* Move record from right node into parent node */
- HDmemcpy(H5B2_INT_NREC(internal, hdr, idx), H5B2_NAT_NREC(right_native, hdr, (move_nrec - 1)), hdr->cls->nrec_size);
+ H5MM_memcpy(H5B2_INT_NREC(internal, hdr, idx), H5B2_NAT_NREC(right_native, hdr, (move_nrec - 1)), hdr->cls->nrec_size);
/* Slide records in right node down */
HDmemmove(H5B2_NAT_NREC(right_native, hdr, 0), H5B2_NAT_NREC(right_native, hdr, move_nrec), hdr->cls->nrec_size * new_right_nrec);
@@ -534,7 +535,7 @@ H5B2__redistribute2(H5B2_hdr_t *hdr, uint16_t depth, H5B2_internal_t *internal,
right_moved_nrec -= (hssize_t)moved_nrec;
/* Copy node pointers from right node to left */
- HDmemcpy(&(left_node_ptrs[*left_nrec + 1]), &(right_node_ptrs[0]), sizeof(H5B2_node_ptr_t) * move_nrec);
+ H5MM_memcpy(&(left_node_ptrs[*left_nrec + 1]), &(right_node_ptrs[0]), sizeof(H5B2_node_ptr_t) * move_nrec);
/* Slide node pointers in right node down */
HDmemmove(&(right_node_ptrs[0]), &(right_node_ptrs[move_nrec]), sizeof(H5B2_node_ptr_t) * (new_right_nrec + (unsigned)1));
@@ -569,14 +570,14 @@ H5B2__redistribute2(H5B2_hdr_t *hdr, uint16_t depth, H5B2_internal_t *internal,
hdr->cls->nrec_size * (*right_nrec));
/* Copy record from parent node down into right child */
- HDmemcpy(H5B2_NAT_NREC(right_native, hdr, (move_nrec - 1)), H5B2_INT_NREC(internal, hdr, idx), hdr->cls->nrec_size);
+ H5MM_memcpy(H5B2_NAT_NREC(right_native, hdr, (move_nrec - 1)), H5B2_INT_NREC(internal, hdr, idx), hdr->cls->nrec_size);
/* See if we need to move records from left node */
if(move_nrec > 1)
- HDmemcpy(H5B2_NAT_NREC(right_native, hdr, 0), H5B2_NAT_NREC(left_native, hdr, ((*left_nrec - move_nrec) + 1)), hdr->cls->nrec_size * (size_t)(move_nrec - 1));
+ H5MM_memcpy(H5B2_NAT_NREC(right_native, hdr, 0), H5B2_NAT_NREC(left_native, hdr, ((*left_nrec - move_nrec) + 1)), hdr->cls->nrec_size * (size_t)(move_nrec - 1));
/* Move record from left node into parent node */
- HDmemcpy(H5B2_INT_NREC(internal, hdr, idx), H5B2_NAT_NREC(left_native, hdr, (*left_nrec - move_nrec)), hdr->cls->nrec_size);
+ H5MM_memcpy(H5B2_INT_NREC(internal, hdr, idx), H5B2_NAT_NREC(left_native, hdr, (*left_nrec - move_nrec)), hdr->cls->nrec_size);
/* Handle node pointers, if we have an internal node */
if(depth > 1) {
@@ -587,7 +588,7 @@ H5B2__redistribute2(H5B2_hdr_t *hdr, uint16_t depth, H5B2_internal_t *internal,
HDmemmove(&(right_node_ptrs[move_nrec]), &(right_node_ptrs[0]), sizeof(H5B2_node_ptr_t) * (size_t)(*right_nrec + 1));
/* Copy node pointers from left node to right */
- HDmemcpy(&(right_node_ptrs[0]), &(left_node_ptrs[new_left_nrec + 1]), sizeof(H5B2_node_ptr_t) * move_nrec);
+ H5MM_memcpy(&(right_node_ptrs[0]), &(left_node_ptrs[new_left_nrec + 1]), sizeof(H5B2_node_ptr_t) * move_nrec);
/* Count the number of records being moved */
for(u = 0; u < move_nrec; u++)
@@ -775,16 +776,16 @@ H5B2__redistribute3(H5B2_hdr_t *hdr, uint16_t depth, H5B2_internal_t *internal,
uint16_t moved_middle_nrec = 0; /* Number of records moved into left node */
/* Move left parent record down to left node */
- HDmemcpy(H5B2_NAT_NREC(left_native, hdr, *left_nrec), H5B2_INT_NREC(internal, hdr, idx - 1), hdr->cls->nrec_size);
+ H5MM_memcpy(H5B2_NAT_NREC(left_native, hdr, *left_nrec), H5B2_INT_NREC(internal, hdr, idx - 1), hdr->cls->nrec_size);
/* Move records from middle node into left node */
if((new_left_nrec - 1) > *left_nrec) {
moved_middle_nrec = (uint16_t)(new_left_nrec - (*left_nrec + 1));
- HDmemcpy(H5B2_NAT_NREC(left_native, hdr, *left_nrec + 1), H5B2_NAT_NREC(middle_native, hdr, 0), hdr->cls->nrec_size * moved_middle_nrec);
+ H5MM_memcpy(H5B2_NAT_NREC(left_native, hdr, *left_nrec + 1), H5B2_NAT_NREC(middle_native, hdr, 0), hdr->cls->nrec_size * moved_middle_nrec);
} /* end if */
/* Move record from middle node up to parent node */
- HDmemcpy(H5B2_INT_NREC(internal, hdr, idx - 1), H5B2_NAT_NREC(middle_native, hdr, moved_middle_nrec), hdr->cls->nrec_size);
+ H5MM_memcpy(H5B2_INT_NREC(internal, hdr, idx - 1), H5B2_NAT_NREC(middle_native, hdr, moved_middle_nrec), hdr->cls->nrec_size);
moved_middle_nrec++;
/* Slide records in middle node down */
@@ -798,7 +799,7 @@ H5B2__redistribute3(H5B2_hdr_t *hdr, uint16_t depth, H5B2_internal_t *internal,
/* Move middle node pointers into left node */
move_nptrs = (unsigned)(new_left_nrec - *left_nrec);
- HDmemcpy(&(left_node_ptrs[*left_nrec + 1]), &(middle_node_ptrs[0]), sizeof(H5B2_node_ptr_t)*move_nptrs);
+ H5MM_memcpy(&(left_node_ptrs[*left_nrec + 1]), &(middle_node_ptrs[0]), sizeof(H5B2_node_ptr_t)*move_nptrs);
/* Count the number of records being moved into the left node */
for(u = 0, moved_nrec = 0; u < move_nptrs; u++)
@@ -832,14 +833,14 @@ H5B2__redistribute3(H5B2_hdr_t *hdr, uint16_t depth, H5B2_internal_t *internal,
HDmemmove(H5B2_NAT_NREC(right_native, hdr, right_nrec_move), H5B2_NAT_NREC(right_native, hdr, 0), hdr->cls->nrec_size * (*right_nrec));
/* Move right parent record down to right node */
- HDmemcpy(H5B2_NAT_NREC(right_native, hdr, right_nrec_move - 1), H5B2_INT_NREC(internal, hdr, idx), hdr->cls->nrec_size);
+ H5MM_memcpy(H5B2_NAT_NREC(right_native, hdr, right_nrec_move - 1), H5B2_INT_NREC(internal, hdr, idx), hdr->cls->nrec_size);
/* Move records from middle node into right node */
if(right_nrec_move > 1)
- HDmemcpy(H5B2_NAT_NREC(right_native, hdr, 0), H5B2_NAT_NREC(middle_native, hdr, ((curr_middle_nrec - right_nrec_move) + 1)), hdr->cls->nrec_size * (right_nrec_move - 1));
+ H5MM_memcpy(H5B2_NAT_NREC(right_native, hdr, 0), H5B2_NAT_NREC(middle_native, hdr, ((curr_middle_nrec - right_nrec_move) + 1)), hdr->cls->nrec_size * (right_nrec_move - 1));
/* Move record from middle node up to parent node */
- HDmemcpy(H5B2_INT_NREC(internal, hdr, idx), H5B2_NAT_NREC(middle_native, hdr, (curr_middle_nrec - right_nrec_move)), hdr->cls->nrec_size);
+ H5MM_memcpy(H5B2_INT_NREC(internal, hdr, idx), H5B2_NAT_NREC(middle_native, hdr, (curr_middle_nrec - right_nrec_move)), hdr->cls->nrec_size);
/* Move node pointers also if this is an internal node */
if(depth > 1) {
@@ -850,7 +851,7 @@ H5B2__redistribute3(H5B2_hdr_t *hdr, uint16_t depth, H5B2_internal_t *internal,
HDmemmove(&(right_node_ptrs[right_nrec_move]), &(right_node_ptrs[0]), sizeof(H5B2_node_ptr_t) * (size_t)(*right_nrec + 1));
/* Move middle node pointers into right node */
- HDmemcpy(&(right_node_ptrs[0]), &(middle_node_ptrs[(curr_middle_nrec - right_nrec_move) + 1]), sizeof(H5B2_node_ptr_t) * right_nrec_move);
+ H5MM_memcpy(&(right_node_ptrs[0]), &(middle_node_ptrs[(curr_middle_nrec - right_nrec_move) + 1]), sizeof(H5B2_node_ptr_t) * right_nrec_move);
/* Count the number of records being moved into the right node */
for(u = 0, moved_nrec = 0; u < right_nrec_move; u++)
@@ -881,14 +882,14 @@ H5B2__redistribute3(H5B2_hdr_t *hdr, uint16_t depth, H5B2_internal_t *internal,
HDmemmove(H5B2_NAT_NREC(middle_native, hdr, left_nrec_move), H5B2_NAT_NREC(middle_native, hdr, 0), hdr->cls->nrec_size * curr_middle_nrec);
/* Move left parent record down to middle node */
- HDmemcpy(H5B2_NAT_NREC(middle_native, hdr, left_nrec_move - 1), H5B2_INT_NREC(internal, hdr, idx - 1), hdr->cls->nrec_size);
+ H5MM_memcpy(H5B2_NAT_NREC(middle_native, hdr, left_nrec_move - 1), H5B2_INT_NREC(internal, hdr, idx - 1), hdr->cls->nrec_size);
/* Move left records to middle node */
if(left_nrec_move > 1)
HDmemmove(H5B2_NAT_NREC(middle_native, hdr, 0), H5B2_NAT_NREC(left_native, hdr, new_left_nrec + 1), hdr->cls->nrec_size * (left_nrec_move - 1));
/* Move left parent record up from left node */
- HDmemcpy(H5B2_INT_NREC(internal, hdr, idx - 1), H5B2_NAT_NREC(left_native, hdr, new_left_nrec), hdr->cls->nrec_size);
+ H5MM_memcpy(H5B2_INT_NREC(internal, hdr, idx - 1), H5B2_NAT_NREC(left_native, hdr, new_left_nrec), hdr->cls->nrec_size);
/* Move node pointers also if this is an internal node */
if(depth > 1) {
@@ -899,7 +900,7 @@ H5B2__redistribute3(H5B2_hdr_t *hdr, uint16_t depth, H5B2_internal_t *internal,
HDmemmove(&(middle_node_ptrs[left_nrec_move]), &(middle_node_ptrs[0]), sizeof(H5B2_node_ptr_t) * (size_t)(curr_middle_nrec + 1));
/* Move left node pointers into middle node */
- HDmemcpy(&(middle_node_ptrs[0]), &(left_node_ptrs[new_left_nrec + 1]), sizeof(H5B2_node_ptr_t) * left_nrec_move);
+ H5MM_memcpy(&(middle_node_ptrs[0]), &(left_node_ptrs[new_left_nrec + 1]), sizeof(H5B2_node_ptr_t) * left_nrec_move);
/* Count the number of records being moved into the left node */
for(u = 0, moved_nrec = 0; u < left_nrec_move; u++)
@@ -927,13 +928,13 @@ H5B2__redistribute3(H5B2_hdr_t *hdr, uint16_t depth, H5B2_internal_t *internal,
unsigned right_nrec_move = (unsigned)(*right_nrec - new_right_nrec); /* Number of records to move out of right node */
/* Move right parent record down to middle node */
- HDmemcpy(H5B2_NAT_NREC(middle_native, hdr, curr_middle_nrec), H5B2_INT_NREC(internal, hdr, idx), hdr->cls->nrec_size);
+ H5MM_memcpy(H5B2_NAT_NREC(middle_native, hdr, curr_middle_nrec), H5B2_INT_NREC(internal, hdr, idx), hdr->cls->nrec_size);
/* Move right records to middle node */
HDmemmove(H5B2_NAT_NREC(middle_native, hdr, (curr_middle_nrec + 1)), H5B2_NAT_NREC(right_native, hdr, 0), hdr->cls->nrec_size * (right_nrec_move - 1));
/* Move right parent record up from right node */
- HDmemcpy(H5B2_INT_NREC(internal, hdr, idx), H5B2_NAT_NREC(right_native, hdr, right_nrec_move - 1), hdr->cls->nrec_size);
+ H5MM_memcpy(H5B2_INT_NREC(internal, hdr, idx), H5B2_NAT_NREC(right_native, hdr, right_nrec_move - 1), hdr->cls->nrec_size);
/* Slide right records down */
HDmemmove(H5B2_NAT_NREC(right_native, hdr, 0), H5B2_NAT_NREC(right_native, hdr, right_nrec_move), hdr->cls->nrec_size * new_right_nrec);
@@ -944,7 +945,7 @@ H5B2__redistribute3(H5B2_hdr_t *hdr, uint16_t depth, H5B2_internal_t *internal,
unsigned u; /* Local index variable */
/* Move right node pointers into middle node */
- HDmemcpy(&(middle_node_ptrs[curr_middle_nrec + 1]), &(right_node_ptrs[0]), sizeof(H5B2_node_ptr_t) * right_nrec_move);
+ H5MM_memcpy(&(middle_node_ptrs[curr_middle_nrec + 1]), &(right_node_ptrs[0]), sizeof(H5B2_node_ptr_t) * right_nrec_move);
/* Count the number of records being moved into the right node */
for(u = 0, moved_nrec = 0; u < right_nrec_move; u++)
@@ -1113,14 +1114,14 @@ H5B2__merge2(H5B2_hdr_t *hdr, uint16_t depth, H5B2_node_ptr_t *curr_node_ptr,
/* Redistribute records into left node */
{
/* Copy record from parent node to proper location */
- HDmemcpy(H5B2_NAT_NREC(left_native, hdr, *left_nrec), H5B2_INT_NREC(internal, hdr, idx), hdr->cls->nrec_size);
+ H5MM_memcpy(H5B2_NAT_NREC(left_native, hdr, *left_nrec), H5B2_INT_NREC(internal, hdr, idx), hdr->cls->nrec_size);
/* Copy records from right node to left node */
- HDmemcpy(H5B2_NAT_NREC(left_native, hdr, *left_nrec + 1), H5B2_NAT_NREC(right_native, hdr, 0), hdr->cls->nrec_size * (*right_nrec));
+ H5MM_memcpy(H5B2_NAT_NREC(left_native, hdr, *left_nrec + 1), H5B2_NAT_NREC(right_native, hdr, 0), hdr->cls->nrec_size * (*right_nrec));
/* Copy node pointers from right node into left node */
if(depth > 1)
- HDmemcpy(&(left_node_ptrs[*left_nrec + 1]), &(right_node_ptrs[0]), sizeof(H5B2_node_ptr_t) * (size_t)(*right_nrec + 1));
+ H5MM_memcpy(&(left_node_ptrs[*left_nrec + 1]), &(right_node_ptrs[0]), sizeof(H5B2_node_ptr_t) * (size_t)(*right_nrec + 1));
/* Update flush dependencies for grandchildren, if using SWMR */
if(hdr->swmr_write && depth > 1)
@@ -1304,13 +1305,13 @@ H5B2__merge3(H5B2_hdr_t *hdr, uint16_t depth, H5B2_node_ptr_t *curr_node_ptr,
middle_moved_nrec = middle_nrec_move;
/* Copy record from parent node to proper location in left node */
- HDmemcpy(H5B2_NAT_NREC(left_native, hdr, *left_nrec), H5B2_INT_NREC(internal, hdr, idx - 1), hdr->cls->nrec_size);
+ H5MM_memcpy(H5B2_NAT_NREC(left_native, hdr, *left_nrec), H5B2_INT_NREC(internal, hdr, idx - 1), hdr->cls->nrec_size);
/* Copy records from middle node to left node */
- HDmemcpy(H5B2_NAT_NREC(left_native, hdr, *left_nrec + 1), H5B2_NAT_NREC(middle_native, hdr, 0), hdr->cls->nrec_size * (middle_nrec_move - 1));
+ H5MM_memcpy(H5B2_NAT_NREC(left_native, hdr, *left_nrec + 1), H5B2_NAT_NREC(middle_native, hdr, 0), hdr->cls->nrec_size * (middle_nrec_move - 1));
/* Copy record from middle node to proper location in parent node */
- HDmemcpy(H5B2_INT_NREC(internal, hdr, idx - 1), H5B2_NAT_NREC(middle_native, hdr, (middle_nrec_move - 1)), hdr->cls->nrec_size);
+ H5MM_memcpy(H5B2_INT_NREC(internal, hdr, idx - 1), H5B2_NAT_NREC(middle_native, hdr, (middle_nrec_move - 1)), hdr->cls->nrec_size);
/* Slide records in middle node down */
HDmemmove(H5B2_NAT_NREC(middle_native, hdr, 0), H5B2_NAT_NREC(middle_native, hdr, middle_nrec_move), hdr->cls->nrec_size * (*middle_nrec - middle_nrec_move));
@@ -1320,7 +1321,7 @@ H5B2__merge3(H5B2_hdr_t *hdr, uint16_t depth, H5B2_node_ptr_t *curr_node_ptr,
unsigned u; /* Local index variable */
/* Copy node pointers from middle node into left node */
- HDmemcpy(&(left_node_ptrs[*left_nrec + 1]), &(middle_node_ptrs[0]), sizeof(H5B2_node_ptr_t) * middle_nrec_move);
+ H5MM_memcpy(&(left_node_ptrs[*left_nrec + 1]), &(middle_node_ptrs[0]), sizeof(H5B2_node_ptr_t) * middle_nrec_move);
/* Count the number of records being moved into the left node */
for(u = 0; u < middle_nrec_move; u++)
@@ -1348,15 +1349,15 @@ H5B2__merge3(H5B2_hdr_t *hdr, uint16_t depth, H5B2_node_ptr_t *curr_node_ptr,
/* Redistribute records into middle node */
{
/* Copy record from parent node to proper location in middle node */
- HDmemcpy(H5B2_NAT_NREC(middle_native, hdr, *middle_nrec), H5B2_INT_NREC(internal, hdr, idx), hdr->cls->nrec_size);
+ H5MM_memcpy(H5B2_NAT_NREC(middle_native, hdr, *middle_nrec), H5B2_INT_NREC(internal, hdr, idx), hdr->cls->nrec_size);
/* Copy records from right node to middle node */
- HDmemcpy(H5B2_NAT_NREC(middle_native, hdr, *middle_nrec + 1), H5B2_NAT_NREC(right_native, hdr, 0), hdr->cls->nrec_size * (*right_nrec));
+ H5MM_memcpy(H5B2_NAT_NREC(middle_native, hdr, *middle_nrec + 1), H5B2_NAT_NREC(right_native, hdr, 0), hdr->cls->nrec_size * (*right_nrec));
/* Move node pointers also if this is an internal node */
if(depth > 1)
/* Copy node pointers from right node into middle node */
- HDmemcpy(&(middle_node_ptrs[*middle_nrec + 1]), &(right_node_ptrs[0]), sizeof(H5B2_node_ptr_t) * (size_t)(*right_nrec + 1));
+ H5MM_memcpy(&(middle_node_ptrs[*middle_nrec + 1]), &(right_node_ptrs[0]), sizeof(H5B2_node_ptr_t) * (size_t)(*right_nrec + 1));
/* Update flush dependencies for grandchildren, if using SWMR */
if(hdr->swmr_write && depth > 1)
@@ -1539,7 +1540,7 @@ H5B2__iterate_node(H5B2_hdr_t *hdr, uint16_t depth, const H5B2_node_ptr_t *curr_
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for B-tree internal node pointers")
/* Copy the node pointers */
- HDmemcpy(node_ptrs, internal->node_ptrs, (sizeof(H5B2_node_ptr_t) * (size_t)(curr_node->node_nrec + 1)));
+ H5MM_memcpy(node_ptrs, internal->node_ptrs, (sizeof(H5B2_node_ptr_t) * (size_t)(curr_node->node_nrec + 1)));
} /* end if */
else {
H5B2_leaf_t *leaf; /* Pointer to leaf node */
@@ -1559,7 +1560,7 @@ H5B2__iterate_node(H5B2_hdr_t *hdr, uint16_t depth, const H5B2_node_ptr_t *curr_
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for B-tree internal native keys")
/* Copy the native keys */
- HDmemcpy(native, node_native, (hdr->cls->nrec_size * curr_node->node_nrec));
+ H5MM_memcpy(native, node_native, (hdr->cls->nrec_size * curr_node->node_nrec));
/* Unlock the node */
if(H5AC_unprotect(hdr->f, curr_node_class, curr_node->addr, node, (unsigned)(hdr->swmr_write ? H5AC__PIN_ENTRY_FLAG : H5AC__NO_FLAGS_SET)) < 0)
@@ -1572,23 +1573,20 @@ H5B2__iterate_node(H5B2_hdr_t *hdr, uint16_t depth, const H5B2_node_ptr_t *curr_
/* Iterate through records, in order */
for(u = 0; u < curr_node->node_nrec && !ret_value; u++) {
/* Descend into child node, if current node is an internal node */
- if(depth > 0) {
+ if(depth > 0)
if((ret_value = H5B2__iterate_node(hdr, (uint16_t)(depth - 1), &(node_ptrs[u]), node, op, op_data)) < 0)
HERROR(H5E_BTREE, H5E_CANTLIST, "node iteration failed");
- } /* end if */
/* Make callback for current record */
- if(!ret_value) {
+ if(!ret_value)
if((ret_value = (op)(H5B2_NAT_NREC(native, hdr, u), op_data)) < 0)
HERROR(H5E_BTREE, H5E_CANTLIST, "iterator function failed");
- } /* end if */
} /* end for */
/* Descend into last child node, if current node is an internal node */
- if(!ret_value && depth > 0) {
+ if(!ret_value && depth > 0)
if((ret_value = H5B2__iterate_node(hdr, (uint16_t)(depth - 1), &(node_ptrs[u]), node, op, op_data)) < 0)
HERROR(H5E_BTREE, H5E_CANTLIST, "node iteration failed");
- } /* end if */
done:
/* Unpin the node if it was pinned */
diff --git a/src/H5B2leaf.c b/src/H5B2leaf.c
index 54d40ea..beca40c 100644
--- a/src/H5B2leaf.c
+++ b/src/H5B2leaf.c
@@ -412,7 +412,7 @@ H5B2__insert_leaf(H5B2_hdr_t *hdr, H5B2_node_ptr_t *curr_node_ptr,
if(hdr->min_native_rec == NULL)
if(NULL == (hdr->min_native_rec = H5MM_malloc(hdr->cls->nrec_size)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, FAIL, "memory allocation failed for v2 B-tree min record info")
- HDmemcpy(hdr->min_native_rec, H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size);
+ H5MM_memcpy(hdr->min_native_rec, H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size);
} /* end if */
} /* end if */
if(idx == (unsigned)(leaf->nrec - 1)) {
@@ -420,7 +420,7 @@ H5B2__insert_leaf(H5B2_hdr_t *hdr, H5B2_node_ptr_t *curr_node_ptr,
if(hdr->max_native_rec == NULL)
if(NULL == (hdr->max_native_rec = H5MM_malloc(hdr->cls->nrec_size)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, FAIL, "memory allocation failed for v2 B-tree max record info")
- HDmemcpy(hdr->max_native_rec, H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size);
+ H5MM_memcpy(hdr->max_native_rec, H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size);
} /* end if */
} /* end if */
} /* end if */
@@ -561,7 +561,7 @@ H5B2__update_leaf(H5B2_hdr_t *hdr, H5B2_node_ptr_t *curr_node_ptr,
if(hdr->min_native_rec == NULL)
if(NULL == (hdr->min_native_rec = H5MM_malloc(hdr->cls->nrec_size)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, FAIL, "memory allocation failed for v2 B-tree min record info")
- HDmemcpy(hdr->min_native_rec, H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size);
+ H5MM_memcpy(hdr->min_native_rec, H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size);
} /* end if */
} /* end if */
if(idx == (unsigned)(leaf->nrec - 1)) {
@@ -569,7 +569,7 @@ H5B2__update_leaf(H5B2_hdr_t *hdr, H5B2_node_ptr_t *curr_node_ptr,
if(hdr->max_native_rec == NULL)
if(NULL == (hdr->max_native_rec = H5MM_malloc(hdr->cls->nrec_size)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, FAIL, "memory allocation failed for v2 B-tree max record info")
- HDmemcpy(hdr->max_native_rec, H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size);
+ H5MM_memcpy(hdr->max_native_rec, H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size);
} /* end if */
} /* end if */
} /* end if */
@@ -664,9 +664,9 @@ H5B2__swap_leaf(H5B2_hdr_t *hdr, uint16_t depth, H5B2_internal_t *internal,
} /* end else */
/* Swap records (use disk page as temporary buffer) */
- HDmemcpy(hdr->page, H5B2_NAT_NREC(child_native, hdr, 0), hdr->cls->nrec_size);
- HDmemcpy(H5B2_NAT_NREC(child_native, hdr, 0), swap_loc, hdr->cls->nrec_size);
- HDmemcpy(swap_loc, hdr->page, hdr->cls->nrec_size);
+ H5MM_memcpy(hdr->page, H5B2_NAT_NREC(child_native, hdr, 0), hdr->cls->nrec_size);
+ H5MM_memcpy(H5B2_NAT_NREC(child_native, hdr, 0), swap_loc, hdr->cls->nrec_size);
+ H5MM_memcpy(swap_loc, hdr->page, hdr->cls->nrec_size);
/* Mark parent as dirty */
*internal_flags_ptr |= H5AC__DIRTIED_FLAG;
diff --git a/src/H5B2private.h b/src/H5B2private.h
index 83a5272..0b64381 100644
--- a/src/H5B2private.h
+++ b/src/H5B2private.h
@@ -25,9 +25,6 @@
#ifndef _H5B2private_H
#define _H5B2private_H
-/* Include package's public header */
-#include "H5B2public.h"
-
/* Private headers needed by this file */
#include "H5ACprivate.h" /* Metadata cache */
#include "H5Fprivate.h" /* File access */
diff --git a/src/H5Bcache.c b/src/H5Bcache.c
index e3febe1..24a6716 100644
--- a/src/H5Bcache.c
+++ b/src/H5Bcache.c
@@ -35,6 +35,7 @@
#include "H5private.h" /* Generic Functions */
#include "H5Bpkg.h" /* B-link trees */
#include "H5Eprivate.h" /* Error handling */
+#include "H5MMprivate.h" /* Memory management */
/****************/
@@ -305,7 +306,7 @@ H5B__cache_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_UNUSED len,
HDassert(shared->type->encode);
/* magic number */
- HDmemcpy(image, H5B_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ H5MM_memcpy(image, H5B_MAGIC, (size_t)H5_SIZEOF_MAGIC);
image += 4;
/* node type and level */
diff --git a/src/H5Bdbg.c b/src/H5Bdbg.c
index c491783..665e826 100644
--- a/src/H5Bdbg.c
+++ b/src/H5Bdbg.c
@@ -193,13 +193,13 @@ H5B__assert(H5F_t *f, haddr_t addr, const H5B_class_t *type, void *udata)
FUNC_ENTER_PACKAGE
if(0 == ncalls++) {
- if(H5DEBUG(B))
- fprintf(H5DEBUG(B), "H5B: debugging B-trees (expensive)\n");
+ if(H5DEBUG(B))
+ HDfprintf(H5DEBUG(B), "H5B: debugging B-trees (expensive)\n");
} /* end if */
/* Get shared info for B-tree */
if(NULL == (rc_shared = (type->get_shared)(f, udata)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTGET, FAIL, "can't retrieve B-tree's shared ref. count object")
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTGET, FAIL, "can't retrieve B-tree's shared ref. count object")
shared = (H5B_shared_t *)H5UC_GET_OBJ(rc_shared);
HDassert(shared);
diff --git a/src/H5Bprivate.h b/src/H5Bprivate.h
index e203b87..5aa3628 100644
--- a/src/H5Bprivate.h
+++ b/src/H5Bprivate.h
@@ -27,7 +27,6 @@
#ifndef _H5Bprivate_H
#define _H5Bprivate_H
-#include "H5Bpublic.h" /*API prototypes */
/* Private headers needed by this file */
#include "H5private.h" /* Generic Functions */
diff --git a/src/H5Bpublic.h b/src/H5Bpublic.h
deleted file mode 100644
index 1764f61..0000000
--- a/src/H5Bpublic.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * 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 COPYING file, which can be found at the root of the source code *
- * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
- * If you do not have access to either file, you may request a copy from *
- * help@hdfgroup.org. *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-/*-------------------------------------------------------------------------
- *
- * Created: H5Bproto.h
- * Jul 10 1997
- * Robb Matzke <matzke@llnl.gov>
- *
- * Purpose: Public declarations for the H5B package.
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-#ifndef _H5Bpublic_H
-#define _H5Bpublic_H
-
-/* Public headers needed by this file */
-#include "H5public.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-#endif
diff --git a/src/H5C.c b/src/H5C.c
index d4bae68..54de160 100644
--- a/src/H5C.c
+++ b/src/H5C.c
@@ -80,6 +80,7 @@
/* Headers */
/***********/
#include "H5private.h" /* Generic Functions */
+#include "H5retry_private.h" /* Retry loops. */
#include "H5Cpkg.h" /* Cache */
#include "H5CXprivate.h" /* API Contexts */
#include "H5Eprivate.h" /* Error handling */
@@ -106,6 +107,9 @@
/* Local Typedefs */
/******************/
+/* Alias for pointer to cache entry, for use when allocating sequences of them */
+typedef H5C_cache_entry_t *H5C_cache_entry_ptr_t;
+
/********************/
/* Local Prototypes */
@@ -207,8 +211,8 @@ H5FL_DEFINE(H5C_tag_info_t);
/* Declare a free list to manage the H5C_t struct */
H5FL_DEFINE_STATIC(H5C_t);
-/* Declare a free list to manage flush dependency arrays */
-H5FL_BLK_DEFINE_STATIC(parent);
+/* Declare a free list to manage arrays of cache entries */
+H5FL_SEQ_DEFINE_STATIC(H5C_cache_entry_ptr_t);
@@ -282,13 +286,8 @@ H5C_create(size_t max_cache_size,
cache_ptr->flush_in_progress = FALSE;
- cache_ptr->logging_enabled = FALSE;
-
- cache_ptr->currently_logging = FALSE;
-
- cache_ptr->log_file_ptr = NULL;
-
- cache_ptr->trace_file_ptr = NULL;
+ if(NULL == (cache_ptr->log_info = (H5C_log_info_t *)H5MM_calloc(sizeof(H5C_log_info_t))))
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, NULL, "memory allocation failed")
cache_ptr->aux_ptr = aux_ptr;
@@ -340,6 +339,7 @@ H5C_create(size_t max_cache_size,
/* Tagging Field Initializations */
cache_ptr->ignore_tags = FALSE;
+ cache_ptr->num_objs_corked = 0;
cache_ptr->slist_changed = FALSE;
cache_ptr->slist_len = 0;
@@ -501,6 +501,9 @@ done:
if(cache_ptr->tag_list != NULL)
H5SL_close(cache_ptr->tag_list);
+ if(cache_ptr->log_info != NULL)
+ H5MM_xfree(cache_ptr->log_info);
+
cache_ptr->magic = 0;
cache_ptr = H5FL_FREE(H5C_t, cache_ptr);
} /* end if */
@@ -874,6 +877,9 @@ H5C_dest(H5F_t * f)
cache_ptr->tag_list = NULL;
} /* end if */
+ if(cache_ptr->log_info != NULL)
+ H5MM_xfree(cache_ptr->log_info);
+
#ifndef NDEBUG
#if H5C_DO_SANITY_CHECKS
if(cache_ptr->get_entry_ptr_from_addr_counter > 0)
@@ -2762,13 +2768,8 @@ H5C_protect(H5F_t * f,
ring = H5CX_get_ring();
#ifdef H5_HAVE_PARALLEL
- if(H5F_HAS_FEATURE(f, H5FD_FEAT_HAS_MPI)) {
- coll_access = (H5P_USER_TRUE == f->coll_md_read ? TRUE : FALSE);
-
- /* If not explicitly disabled, get the cmdr setting from the API context */
- if(!coll_access && H5P_FORCE_FALSE != f->coll_md_read)
- coll_access = H5CX_get_coll_metadata_read();
- } /* end if */
+ if(H5F_HAS_FEATURE(f, H5FD_FEAT_HAS_MPI))
+ coll_access = H5CX_get_coll_metadata_read();
#endif /* H5_HAVE_PARALLEL */
/* first check to see if the target is in cache */
@@ -2805,7 +2806,7 @@ H5C_protect(H5F_t * f,
the entry in their cache still have to participate in the
bcast. */
#ifdef H5_HAVE_PARALLEL
- if(H5F_HAS_FEATURE(f, H5FD_FEAT_HAS_MPI) && coll_access) {
+ if(coll_access) {
if(!(entry_ptr->is_dirty) && !(entry_ptr->coll_access)) {
MPI_Comm comm; /* File MPI Communicator */
int mpi_code; /* MPI error code */
@@ -2823,7 +2824,7 @@ H5C_protect(H5F_t * f,
if(NULL == (entry_ptr->image_ptr = H5MM_malloc(entry_ptr->size + H5C_IMAGE_EXTRA_SPACE)))
HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, NULL, "memory allocation failed for on disk image buffer")
#if H5C_DO_MEMORY_SANITY_CHECKS
- HDmemcpy(((uint8_t *)entry_ptr->image_ptr) + entry_ptr->size, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
+ H5MM_memcpy(((uint8_t *)entry_ptr->image_ptr) + entry_ptr->size, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
#endif /* H5C_DO_MEMORY_SANITY_CHECKS */
if(0 == mpi_rank)
if(H5C__generate_image(f, cache_ptr, entry_ptr) < 0)
@@ -3120,21 +3121,11 @@ H5C_protect(H5F_t * f,
} /* end if */
#ifdef H5_HAVE_PARALLEL
- if(H5F_HAS_FEATURE(f, H5FD_FEAT_HAS_MPI)) {
- /* Make sure the size of the collective entries in the cache remain in check */
- if(coll_access) {
- if(H5P_USER_TRUE == f->coll_md_read) {
- if(cache_ptr->max_cache_size * 80 < cache_ptr->coll_list_size * 100)
- if(H5C_clear_coll_entries(cache_ptr, TRUE) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, NULL, "can't clear collective metadata entries")
- } /* end if */
- else {
- if(cache_ptr->max_cache_size * 40 < cache_ptr->coll_list_size * 100)
- if(H5C_clear_coll_entries(cache_ptr, TRUE) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, NULL, "can't clear collective metadata entries")
- } /* end else */
- } /* end if */
- } /* end if */
+ /* Make sure the size of the collective entries in the cache remain in check */
+ if(coll_access)
+ if(cache_ptr->max_cache_size * 80 < cache_ptr->coll_list_size * 100)
+ if(H5C_clear_coll_entries(cache_ptr, TRUE) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, NULL, "can't clear collective metadata entries")
#endif /* H5_HAVE_PARALLEL */
done:
@@ -4185,7 +4176,7 @@ H5C_create_flush_dependency(void * parent_thing, void * child_thing)
/* Array does not exist yet, allocate it */
HDassert(!child_entry->flush_dep_parent);
- if(NULL == (child_entry->flush_dep_parent = (H5C_cache_entry_t **)H5FL_BLK_MALLOC(parent, H5C_FLUSH_DEP_PARENT_INIT * sizeof(H5C_cache_entry_t *))))
+ if(NULL == (child_entry->flush_dep_parent = H5FL_SEQ_MALLOC(H5C_cache_entry_ptr_t, H5C_FLUSH_DEP_PARENT_INIT)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for flush dependency parent list")
child_entry->flush_dep_parent_nalloc = H5C_FLUSH_DEP_PARENT_INIT;
} /* end if */
@@ -4193,7 +4184,7 @@ H5C_create_flush_dependency(void * parent_thing, void * child_thing)
/* Resize existing array */
HDassert(child_entry->flush_dep_parent);
- if(NULL == (child_entry->flush_dep_parent = (H5C_cache_entry_t **)H5FL_BLK_REALLOC(parent, child_entry->flush_dep_parent, 2 * child_entry->flush_dep_parent_nalloc * sizeof(H5C_cache_entry_t *))))
+ if(NULL == (child_entry->flush_dep_parent = H5FL_SEQ_REALLOC(H5C_cache_entry_ptr_t, child_entry->flush_dep_parent, 2 * child_entry->flush_dep_parent_nalloc)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for flush dependency parent list")
child_entry->flush_dep_parent_nalloc *= 2;
} /* end else */
@@ -4351,12 +4342,12 @@ H5C_destroy_flush_dependency(void *parent_thing, void * child_thing)
/* Shrink or free the parent array if apporpriate */
if(child_entry->flush_dep_nparents == 0) {
- child_entry->flush_dep_parent = (H5C_cache_entry_t **)H5FL_BLK_FREE(parent, child_entry->flush_dep_parent);
+ child_entry->flush_dep_parent = H5FL_SEQ_FREE(H5C_cache_entry_ptr_t, child_entry->flush_dep_parent);
child_entry->flush_dep_parent_nalloc = 0;
} /* end if */
else if(child_entry->flush_dep_parent_nalloc > H5C_FLUSH_DEP_PARENT_INIT
&& child_entry->flush_dep_nparents <= (child_entry->flush_dep_parent_nalloc / 4)) {
- if(NULL == (child_entry->flush_dep_parent = (H5C_cache_entry_t **)H5FL_BLK_REALLOC(parent, child_entry->flush_dep_parent, (child_entry->flush_dep_parent_nalloc / 4) * sizeof(H5C_cache_entry_t *))))
+ if(NULL == (child_entry->flush_dep_parent = H5FL_SEQ_REALLOC(H5C_cache_entry_ptr_t, child_entry->flush_dep_parent, child_entry->flush_dep_parent_nalloc / 4)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for flush dependency parent list")
child_entry->flush_dep_parent_nalloc /= 4;
} /* end if */
@@ -6627,7 +6618,7 @@ H5C__flush_single_entry(H5F_t *f, H5C_cache_entry_t *entry_ptr, unsigned flags)
if(NULL == (entry_ptr->image_ptr = H5MM_malloc(entry_ptr->size + H5C_IMAGE_EXTRA_SPACE)))
HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed for on disk image buffer")
#if H5C_DO_MEMORY_SANITY_CHECKS
- HDmemcpy(((uint8_t *)entry_ptr->image_ptr) + entry_ptr->size, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
+ H5MM_memcpy(((uint8_t *)entry_ptr->image_ptr) + entry_ptr->size, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
#endif /* H5C_DO_MEMORY_SANITY_CHECKS */
} /* end if */
@@ -7169,7 +7160,7 @@ H5C_load_entry(H5F_t * f,
"memory allocation failed for on disk image buffer")
#if H5C_DO_MEMORY_SANITY_CHECKS
- HDmemcpy(image + len, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
+ H5MM_memcpy(image + len, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
#endif /* H5C_DO_MEMORY_SANITY_CHECKS */
#ifdef H5_HAVE_PARALLEL
@@ -7221,7 +7212,7 @@ H5C_load_entry(H5F_t * f,
image = (uint8_t *)new_image;
#if H5C_DO_MEMORY_SANITY_CHECKS
- HDmemcpy(image + len, H5C_IMAGE_SANITY_VALUE,
+ H5MM_memcpy(image + len, H5C_IMAGE_SANITY_VALUE,
H5C_IMAGE_EXTRA_SPACE);
#endif /* H5C_DO_MEMORY_SANITY_CHECKS */
} /* end if */
@@ -7290,7 +7281,7 @@ H5C_load_entry(H5F_t * f,
image = (uint8_t *)new_image;
#if H5C_DO_MEMORY_SANITY_CHECKS
- HDmemcpy(image + actual_len, H5C_IMAGE_SANITY_VALUE,
+ H5MM_memcpy(image + actual_len, H5C_IMAGE_SANITY_VALUE,
H5C_IMAGE_EXTRA_SPACE);
#endif /* H5C_DO_MEMORY_SANITY_CHECKS */
@@ -8414,6 +8405,8 @@ H5C_cork(H5C_t *cache_ptr, haddr_t obj_addr, unsigned action, hbool_t *corked)
/* Set the corked status for the entire object */
tag_info->corked = TRUE;
+ cache_ptr->num_objs_corked++;
+
} /* end if */
else {
/* Sanity check */
@@ -8425,6 +8418,7 @@ H5C_cork(H5C_t *cache_ptr, haddr_t obj_addr, unsigned action, hbool_t *corked)
/* Set the corked status for the entire object */
tag_info->corked = FALSE;
+ cache_ptr->num_objs_corked--;
/* Remove the tag info from the tag list, if there's no more entries with this tag */
if(0 == tag_info->entry_cnt) {
@@ -9166,7 +9160,7 @@ H5C__serialize_single_entry(H5F_t *f, H5C_t *cache_ptr, H5C_cache_entry_t *entry
if(NULL == (entry_ptr->image_ptr = H5MM_malloc(entry_ptr->size + H5C_IMAGE_EXTRA_SPACE)) )
HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed for on disk image buffer")
#if H5C_DO_MEMORY_SANITY_CHECKS
- HDmemcpy(((uint8_t *)entry_ptr->image_ptr) + image_size, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
+ H5MM_memcpy(((uint8_t *)entry_ptr->image_ptr) + image_size, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
#endif /* H5C_DO_MEMORY_SANITY_CHECKS */
} /* end if */
@@ -9310,7 +9304,7 @@ H5C__generate_image(H5F_t *f, H5C_t *cache_ptr, H5C_cache_entry_t *entry_ptr)
"memory allocation failed for on disk image buffer")
#if H5C_DO_MEMORY_SANITY_CHECKS
- HDmemcpy(((uint8_t *)entry_ptr->image_ptr) + new_len, \
+ H5MM_memcpy(((uint8_t *)entry_ptr->image_ptr) + new_len,
H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
#endif /* H5C_DO_MEMORY_SANITY_CHECKS */
diff --git a/src/H5CX.c b/src/H5CX.c
index faf0b24..96c1d72 100644
--- a/src/H5CX.c
+++ b/src/H5CX.c
@@ -53,7 +53,7 @@
* each thread individually. The association of contexts to threads will
* be handled by the pthread library.
*
- * In order for this macro to work, H5E__get_my_stack() must be preceeded
+ * In order for this macro to work, H5CX_get_my_context() must be preceeded
* by "H5CX_node_t *ctx =".
*/
#define H5CX_get_my_context() H5CX__get_context()
@@ -64,17 +64,22 @@
#define H5CX_get_my_context() (&H5CX_head_g)
#endif /* H5_HAVE_THREADSAFE */
+/* Common macro for the retrieving the pointer to a property list */
+#define H5CX_RETRIEVE_PLIST(PL, FAILVAL) \
+ /* Check if the property list is already available */ \
+ if(NULL == (*head)->ctx.PL) \
+ /* Get the property list pointer */ \
+ if(NULL == ((*head)->ctx.PL = (H5P_genplist_t *)H5I_object((*head)->ctx.H5_GLUE(PL,_id)))) \
+ HGOTO_ERROR(H5E_CONTEXT, H5E_BADTYPE, (FAILVAL), "can't get property list")
+
/* Common macro for the duplicated code to retrieve properties from a property list */
#define H5CX_RETRIEVE_PROP_COMMON(PL, DEF_PL, PROP_NAME, PROP_FIELD) \
/* Check for default property list */ \
if((*head)->ctx.H5_GLUE(PL,_id) == (DEF_PL)) \
- HDmemcpy(&(*head)->ctx.PROP_FIELD, &H5_GLUE3(H5CX_def_,PL,_cache).PROP_FIELD, sizeof(H5_GLUE3(H5CX_def_,PL,_cache).PROP_FIELD)); \
+ H5MM_memcpy(&(*head)->ctx.PROP_FIELD, &H5_GLUE3(H5CX_def_,PL,_cache).PROP_FIELD, sizeof(H5_GLUE3(H5CX_def_,PL,_cache).PROP_FIELD)); \
else { \
- /* Check if the property list is already available */ \
- if(NULL == (*head)->ctx.PL) \
- /* Get the dataset transfer property list pointer */ \
- if(NULL == ((*head)->ctx.PL = (H5P_genplist_t *)H5I_object((*head)->ctx.H5_GLUE(PL,_id)))) \
- HGOTO_ERROR(H5E_CONTEXT, H5E_BADTYPE, FAIL, "can't get default dataset transfer property list") \
+ /* Retrieve the property list */ \
+ H5CX_RETRIEVE_PLIST(PL, FAIL) \
\
/* Get the property */ \
if(H5P_get((*head)->ctx.PL, (PROP_NAME), &(*head)->ctx.PROP_FIELD) < 0) \
@@ -108,11 +113,8 @@
\
/* Check if property exists in DXPL */ \
if(!(*head)->ctx.H5_GLUE(PROP_FIELD,_set)) { \
- /* Check if the property list is already available */ \
- if(NULL == (*head)->ctx.dxpl) \
- /* Get the dataset transfer property list pointer */ \
- if(NULL == ((*head)->ctx.dxpl = (H5P_genplist_t *)H5I_object((*head)->ctx.dxpl_id))) \
- HGOTO_ERROR(H5E_CONTEXT, H5E_BADTYPE, FAIL, "can't get default dataset transfer property list") \
+ /* Retrieve the dataset transfer property list */ \
+ H5CX_RETRIEVE_PLIST(dxpl, FAIL) \
\
if((check_prop = H5P_exist_plist((*head)->ctx.dxpl, PROP_NAME)) < 0) \
HGOTO_ERROR(H5E_CONTEXT, H5E_CANTGET, FAIL, "error checking for property") \
@@ -125,21 +127,18 @@
(*head)->ctx.H5_GLUE(PROP_FIELD,_set) = TRUE; \
} /* end if */ \
}
-#endif /* H5_HAVE_PARALLEL */
/* Macro for the duplicated code to test and set properties for a property list */
#define H5CX_SET_PROP(PROP_NAME, PROP_FIELD) \
if((*head)->ctx.H5_GLUE(PROP_FIELD,_set)) { \
- /* Check if the property list is already available */ \
- if(NULL == (*head)->ctx.dxpl) \
- /* Get the dataset transfer property list pointer */ \
- if(NULL == ((*head)->ctx.dxpl = (H5P_genplist_t *)H5I_object((*head)->ctx.dxpl_id))) \
- HGOTO_ERROR(H5E_CONTEXT, H5E_BADTYPE, NULL, "can't get default dataset transfer property list") \
+ /* Retrieve the dataset transfer property list */ \
+ H5CX_RETRIEVE_PLIST(dxpl, NULL) \
\
- /* Set the chunk filter mask property */ \
+ /* Set the property */ \
if(H5P_set((*head)->ctx.dxpl, PROP_NAME, &(*head)->ctx.PROP_FIELD) < 0) \
- HGOTO_ERROR(H5E_CONTEXT, H5E_CANTSET, NULL, "error setting filter mask xfer property") \
+ HGOTO_ERROR(H5E_CONTEXT, H5E_CANTSET, NULL, "error setting data xfer property") \
} /* end if */
+#endif /* H5_HAVE_PARALLEL */
/******************/
@@ -175,7 +174,7 @@
* corresponding property in the property list to be set when the API
* context is popped, when returning from the API routine. Note that the
* naming of these fields, <foo> and <foo>_set, is important for the
-* H5CX_TEST_SET_PROP and H5CX_SET_PROP macros to work properly.
+ * H5CX_TEST_SET_PROP and H5CX_SET_PROP macros to work properly.
*/
typedef struct H5CX_t {
/* DXPL */
@@ -186,6 +185,18 @@ typedef struct H5CX_t {
hid_t lapl_id; /* LAPL ID for API operation */
H5P_genplist_t *lapl; /* Link Access Property List */
+ /* DCPL */
+ hid_t dcpl_id; /* DCPL ID for API operation */
+ H5P_genplist_t *dcpl; /* Dataset Creation Property List */
+
+ /* DAPL */
+ hid_t dapl_id; /* DAPL ID for API operation */
+ H5P_genplist_t *dapl; /* Dataset Access Property List */
+
+ /* FAPL */
+ hid_t fapl_id; /* FAPL ID for API operation */
+ H5P_genplist_t *fapl; /* File Access Property List */
+
/* Internal: Object tagging info */
haddr_t tag; /* Current object's tag (ohdr chunk #0 address) */
@@ -198,6 +209,7 @@ typedef struct H5CX_t {
MPI_Datatype btype; /* MPI datatype for buffer, when using collective I/O */
MPI_Datatype ftype; /* MPI datatype for file, when using collective I/O */
hbool_t mpi_file_flushing; /* Whether an MPI-opened file is being flushed */
+ hbool_t rank0_bcast; /* Whether a dataset meets read-with-rank0-and-bcast requirements */
#endif /* H5_HAVE_PARALLEL */
/* Cached DXPL properties */
@@ -261,12 +273,36 @@ typedef struct H5CX_t {
hbool_t mpio_coll_chunk_multi_ratio_coll_set; /* Whether instrumented "collective chunk multi ratio coll" value is set */
int mpio_coll_chunk_multi_ratio_ind; /* Instrumented "collective chunk multi ratio ind" value (H5D_XFER_COLL_CHUNK_MULTI_RATIO_IND_NAME) */
hbool_t mpio_coll_chunk_multi_ratio_ind_set; /* Whether instrumented "collective chunk multi ratio ind" value is set */
+ hbool_t mpio_coll_rank0_bcast; /* Instrumented "collective chunk multi ratio ind" value (H5D_XFER_COLL_CHUNK_MULTI_RATIO_IND_NAME) */
+ hbool_t mpio_coll_rank0_bcast_set; /* Whether instrumented "collective chunk multi ratio ind" value is set */
#endif /* H5_HAVE_INSTRUMENTED_LIBRARY */
#endif /* H5_HAVE_PARALLEL */
/* Cached LAPL properties */
size_t nlinks; /* Number of soft / UD links to traverse (H5L_ACS_NLINKS_NAME) */
hbool_t nlinks_valid; /* Whether number of soft / UD links to traverse is valid */
+
+ /* Cached DCPL properties */
+ hbool_t do_min_dset_ohdr; /* Whether to minimize dataset object header */
+ hbool_t do_min_dset_ohdr_valid; /* Whether minimize dataset object header flag is valid */
+
+ /* Cached DAPL properties */
+ const char *extfile_prefix; /* Prefix for external file */
+ hbool_t extfile_prefix_valid; /* Whether the prefix for external file is valid */
+ const char *vds_prefix; /* Prefix for VDS */
+ hbool_t vds_prefix_valid; /* Whether the prefix for VDS is valid */
+
+ /* Cached FAPL properties */
+ H5F_libver_t low_bound; /* low_bound property for H5Pset_libver_bounds() */
+ hbool_t low_bound_valid; /* Whether low_bound property is valid */
+ H5F_libver_t high_bound; /* high_bound property for H5Pset_libver_bounds */
+ hbool_t high_bound_valid; /* Whether high_bound property is valid */
+
+ /* Cached VOL settings */
+ H5VL_connector_prop_t vol_connector_prop; /* Property for VOL connector ID & info */
+ hbool_t vol_connector_prop_valid; /* Whether property for VOL connector ID & info is valid */
+ void *vol_wrap_ctx; /* VOL connector's "wrap context" for creating IDs */
+ hbool_t vol_wrap_ctx_valid; /* Whether VOL connector's "wrap context" for creating IDs is valid */
} H5CX_t;
/* Typedef for nodes on the API context stack */
@@ -316,6 +352,25 @@ typedef struct H5CX_lapl_cache_t {
size_t nlinks; /* Number of soft / UD links to traverse (H5L_ACS_NLINKS_NAME) */
} H5CX_lapl_cache_t;
+/* Typedef for cached default dataset creation property list information */
+/* (Same as the cached DXPL struct, above, except for the default DCPL) */
+typedef struct H5CX_dcpl_cache_t {
+ hbool_t do_min_dset_ohdr; /* Whether to minimize dataset object header */
+} H5CX_dcpl_cache_t;
+
+/* Typedef for cached default dataset access property list information */
+/* (Same as the cached DXPL struct, above, except for the default DXPL) */
+typedef struct H5CX_dapl_cache_t {
+ const char *extfile_prefix; /* Prefix for external file */
+ const char *vds_prefix; /* Prefix for VDS */
+} H5CX_dapl_cache_t;
+
+/* Typedef for cached default file access property list information */
+/* (Same as the cached DXPL struct, above, except for the default DCPL) */
+typedef struct H5CX_fapl_cache_t {
+ H5F_libver_t low_bound; /* low_bound property for H5Pset_libver_bounds() */
+ H5F_libver_t high_bound; /* high_bound property for H5Pset_libver_bounds */
+} H5CX_fapl_cache_t;
/********************/
/* Local Prototypes */
@@ -349,9 +404,21 @@ static H5CX_dxpl_cache_t H5CX_def_dxpl_cache;
/* Define a "default" link access property list cache structure to use for default LAPLs */
static H5CX_lapl_cache_t H5CX_def_lapl_cache;
+/* Define a "default" dataset creation property list cache structure to use for default DCPLs */
+static H5CX_dcpl_cache_t H5CX_def_dcpl_cache;
+
+/* Define a "default" dataset access property list cache structure to use for default DAPLs */
+static H5CX_dapl_cache_t H5CX_def_dapl_cache;
+
+/* Define a "default" file access property list cache structure to use for default FAPLs */
+static H5CX_fapl_cache_t H5CX_def_fapl_cache;
+
/* Declare a static free list to manage H5CX_node_t structs */
H5FL_DEFINE_STATIC(H5CX_node_t);
+/* Declare a static free list to manage H5CX_state_t structs */
+H5FL_DEFINE_STATIC(H5CX_state_t);
+
/*--------------------------------------------------------------------------
@@ -369,6 +436,9 @@ H5CX__init_package(void)
{
H5P_genplist_t *dx_plist; /* Data transfer property list */
H5P_genplist_t *la_plist; /* Link access property list */
+ H5P_genplist_t *dc_plist; /* Dataset creation property list */
+ H5P_genplist_t *da_plist; /* Dataset access property list */
+ H5P_genplist_t *fa_plist; /* File access property list */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC
@@ -468,6 +538,53 @@ H5CX__init_package(void)
if(H5P_get(la_plist, H5L_ACS_NLINKS_NAME, &H5CX_def_lapl_cache.nlinks) < 0)
HGOTO_ERROR(H5E_CONTEXT, H5E_CANTGET, FAIL, "Can't retrieve number of soft / UD links to traverse")
+
+ /* Reset the "default DCPL cache" information */
+ HDmemset(&H5CX_def_dcpl_cache, 0, sizeof(H5CX_dcpl_cache_t));
+
+ /* Get the default DCPL cache information */
+
+ /* Get the default dataset creation property list */
+ if(NULL == (dc_plist = (H5P_genplist_t *)H5I_object(H5P_DATASET_CREATE_DEFAULT)))
+ HGOTO_ERROR(H5E_CONTEXT, H5E_BADTYPE, FAIL, "not a dataset create property list")
+
+ /* Get flag to indicate whether to minimize dataset object header */
+ if(H5P_get(dc_plist, H5D_CRT_MIN_DSET_HDR_SIZE_NAME, &H5CX_def_dcpl_cache.do_min_dset_ohdr) < 0)
+ HGOTO_ERROR(H5E_CONTEXT, H5E_CANTGET, FAIL, "Can't retrieve dataset minimize flag")
+
+ /* Reset the "default DAPL cache" information */
+ HDmemset(&H5CX_def_dapl_cache, 0, sizeof(H5CX_dapl_cache_t));
+
+ /* Get the default DAPL cache information */
+
+ /* Get the default dataset access property list */
+ if(NULL == (da_plist = (H5P_genplist_t *)H5I_object(H5P_DATASET_ACCESS_DEFAULT)))
+ HGOTO_ERROR(H5E_CONTEXT, H5E_BADTYPE, FAIL, "not a dataset create property list")
+
+ /* Get the prefix for the external file */
+ if(H5P_peek(da_plist, H5D_ACS_EFILE_PREFIX_NAME, &H5CX_def_dapl_cache.extfile_prefix) < 0)
+ HGOTO_ERROR(H5E_CONTEXT, H5E_CANTGET, FAIL, "Can't retrieve prefix for external file")
+
+ /* Get the prefix for the VDS file */
+ if(H5P_peek(da_plist, H5D_ACS_VDS_PREFIX_NAME, &H5CX_def_dapl_cache.vds_prefix) < 0)
+ HGOTO_ERROR(H5E_CONTEXT, H5E_CANTGET, FAIL, "Can't retrieve prefix for VDS")
+
+ /* Reset the "default FAPL cache" information */
+ HDmemset(&H5CX_def_fapl_cache, 0, sizeof(H5CX_fapl_cache_t));
+
+ /* Get the default FAPL cache information */
+
+ /* Get the default file access property list */
+ if(NULL == (fa_plist = (H5P_genplist_t *)H5I_object(H5P_FILE_ACCESS_DEFAULT)))
+ HGOTO_ERROR(H5E_CONTEXT, H5E_BADTYPE, FAIL, "not a dataset create property list")
+
+ /* Get low_bound */
+ if(H5P_get(fa_plist, H5F_ACS_LIBVER_LOW_BOUND_NAME, &H5CX_def_fapl_cache.low_bound) < 0)
+ HGOTO_ERROR(H5E_CONTEXT, H5E_CANTGET, FAIL, "Can't retrieve dataset minimize flag")
+
+ if(H5P_get(fa_plist, H5F_ACS_LIBVER_HIGH_BOUND_NAME, &H5CX_def_fapl_cache.high_bound) < 0)
+ HGOTO_ERROR(H5E_CONTEXT, H5E_CANTGET, FAIL, "Can't retrieve dataset minimize flag")
+
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5CX__init_package() */
@@ -591,7 +708,10 @@ H5CX__push_common(H5CX_node_t *cnode)
/* Set non-zero context info */
cnode->ctx.dxpl_id = H5P_DATASET_XFER_DEFAULT;
+ cnode->ctx.dcpl_id = H5P_DATASET_CREATE_DEFAULT;
+ cnode->ctx.dapl_id = H5P_DATASET_ACCESS_DEFAULT;
cnode->ctx.lapl_id = H5P_LINK_ACCESS_DEFAULT;
+ cnode->ctx.fapl_id = H5P_FILE_ACCESS_DEFAULT;
cnode->ctx.tag = H5AC__INVALID_TAG;
cnode->ctx.ring = H5AC_RING_USER;
@@ -668,6 +788,217 @@ H5CX_push_special(void)
/*-------------------------------------------------------------------------
+ * Function: H5CX_retrieve_state
+ *
+ * Purpose: Retrieve the state of an API context, for later resumption.
+ *
+ * Note: This routine _only_ tracks the state of API context information
+ * set before the VOL callback is invoked, not values that are
+ * set internal to the library. It's main purpose is to provide
+ * API context state to VOL connectors.
+ *
+ * Return: Non-negative on success / Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * January 8, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5CX_retrieve_state(H5CX_state_t **api_state)
+{
+ H5CX_node_t **head = H5CX_get_my_context(); /* Get the pointer to the head of the API context, for this thread */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check */
+ HDassert(head && *head);
+ HDassert(api_state);
+
+ /* Allocate & clear API context state */
+ if(NULL == (*api_state = H5FL_CALLOC(H5CX_state_t)))
+ HGOTO_ERROR(H5E_CONTEXT, H5E_CANTALLOC, FAIL, "unable to allocate new API context state")
+
+ /* Check for non-default DXPL */
+ if(H5P_DATASET_XFER_DEFAULT != (*head)->ctx.dxpl_id) {
+ /* Retrieve the DXPL property list */
+ H5CX_RETRIEVE_PLIST(dxpl, FAIL)
+
+ /* Copy the DXPL ID */
+ if(((*api_state)->dxpl_id = H5P_copy_plist((H5P_genplist_t *)(*head)->ctx.dxpl, FALSE)) < 0)
+ HGOTO_ERROR(H5E_CONTEXT, H5E_CANTCOPY, FAIL, "can't copy property list")
+ } /* end if */
+ else
+ (*api_state)->dxpl_id = H5P_DATASET_XFER_DEFAULT;
+
+ /* Check for non-default LAPL */
+ if(H5P_LINK_ACCESS_DEFAULT != (*head)->ctx.lapl_id) {
+ /* Retrieve the LAPL property list */
+ H5CX_RETRIEVE_PLIST(lapl, FAIL)
+
+ /* Copy the LAPL ID */
+ if(((*api_state)->lapl_id = H5P_copy_plist((H5P_genplist_t *)(*head)->ctx.lapl, FALSE)) < 0)
+ HGOTO_ERROR(H5E_CONTEXT, H5E_CANTCOPY, FAIL, "can't copy property list")
+ } /* end if */
+ else
+ (*api_state)->lapl_id = H5P_LINK_ACCESS_DEFAULT;
+
+ /* Keep a reference to the current VOL wrapping context */
+ (*api_state)->vol_wrap_ctx = (*head)->ctx.vol_wrap_ctx;
+ if(NULL != (*api_state)->vol_wrap_ctx)
+ if(H5VL_inc_vol_wrapper((*api_state)->vol_wrap_ctx) < 0)
+ HGOTO_ERROR(H5E_CONTEXT, H5E_CANTINC, FAIL, "can't increment refcount on VOL wrapping context")
+
+ /* Keep a copy of the VOL connector property, if there is one */
+ if((*head)->ctx.vol_connector_prop_valid && (*head)->ctx.vol_connector_prop.connector_id > 0) {
+ /* Get the connector property */
+ H5MM_memcpy(&(*api_state)->vol_connector_prop, &(*head)->ctx.vol_connector_prop, sizeof(H5VL_connector_prop_t));
+
+ /* Check for actual VOL connector property */
+ if((*api_state)->vol_connector_prop.connector_id) {
+ /* Copy connector info, if it exists */
+ if((*api_state)->vol_connector_prop.connector_info) {
+ H5VL_class_t *connector; /* Pointer to connector */
+ void *new_connector_info = NULL; /* Copy of connector info */
+
+ /* Retrieve the connector for the ID */
+ if(NULL == (connector = (H5VL_class_t *)H5I_object((*api_state)->vol_connector_prop.connector_id)))
+ HGOTO_ERROR(H5E_CONTEXT, H5E_BADTYPE, FAIL, "not a VOL connector ID")
+
+ /* Allocate and copy connector info */
+ if(H5VL_copy_connector_info(connector, &new_connector_info, (*api_state)->vol_connector_prop.connector_info) < 0)
+ HGOTO_ERROR(H5E_CONTEXT, H5E_CANTCOPY, FAIL, "connector info copy failed")
+ (*api_state)->vol_connector_prop.connector_info = new_connector_info;
+ } /* end if */
+
+ /* Increment the refcount on the connector ID */
+ if(H5I_inc_ref((*api_state)->vol_connector_prop.connector_id, FALSE) < 0)
+ HGOTO_ERROR(H5E_CONTEXT, H5E_CANTINC, FAIL, "incrementing VOL connector ID failed")
+ } /* end if */
+ } /* end if */
+
+#ifdef H5_HAVE_PARALLEL
+ /* Save parallel I/O settings */
+ (*api_state)->coll_metadata_read = (*head)->ctx.coll_metadata_read;
+#endif /* H5_HAVE_PARALLEL */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5CX_retrieve_state() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5CX_restore_state
+ *
+ * Purpose: Restore an API context, from a previously retrieved state.
+ *
+ * Note: This routine _only_ resets the state of API context information
+ * set before the VOL callback is invoked, not values that are
+ * set internal to the library. It's main purpose is to restore
+ * API context state from VOL connectors.
+ *
+ * Return: Non-negative on success / Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * January 9, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5CX_restore_state(const H5CX_state_t *api_state)
+{
+ H5CX_node_t **head = H5CX_get_my_context(); /* Get the pointer to the head of the API context, for this thread */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ /* Sanity check */
+ HDassert(head && *head);
+ HDassert(api_state);
+
+ /* Restore the DXPL info */
+ (*head)->ctx.dxpl_id = api_state->dxpl_id;
+ (*head)->ctx.dxpl = NULL;
+
+ /* Restore the LAPL info */
+ (*head)->ctx.lapl_id = api_state->lapl_id;
+ (*head)->ctx.lapl = NULL;
+
+ /* Restore the VOL wrapper context */
+ (*head)->ctx.vol_wrap_ctx = api_state->vol_wrap_ctx;
+
+ /* Restore the VOL connector info */
+ if(api_state->vol_connector_prop.connector_id) {
+ H5MM_memcpy(&(*head)->ctx.vol_connector_prop, &api_state->vol_connector_prop, sizeof(H5VL_connector_prop_t));
+ (*head)->ctx.vol_connector_prop_valid = TRUE;
+ } /* end if */
+
+#ifdef H5_HAVE_PARALLEL
+ /* Restore parallel I/O settings */
+ (*head)->ctx.coll_metadata_read = api_state->coll_metadata_read;
+#endif /* H5_HAVE_PARALLEL */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5CX_restore_state() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5CX_free_state
+ *
+ * Purpose: Free a previously retrievedAPI context state
+ *
+ * Return: Non-negative on success / Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * January 9, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5CX_free_state(H5CX_state_t *api_state)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check */
+ HDassert(api_state);
+
+ /* Release the DXPL */
+ if(api_state->dxpl_id != H5P_DATASET_XFER_DEFAULT)
+ if(H5I_dec_ref(api_state->dxpl_id) < 0)
+ HGOTO_ERROR(H5E_CONTEXT, H5E_CANTDEC, FAIL, "can't decrement refcount on DXPL")
+
+ /* Release the LAPL */
+ if(api_state->lapl_id != H5P_LINK_ACCESS_DEFAULT)
+ if(H5I_dec_ref(api_state->lapl_id) < 0)
+ HGOTO_ERROR(H5E_CONTEXT, H5E_CANTDEC, FAIL, "can't decrement refcount on LAPL")
+
+ /* Release the VOL wrapper context */
+ if(api_state->vol_wrap_ctx)
+ if(H5VL_dec_vol_wrapper(api_state->vol_wrap_ctx) < 0)
+ HGOTO_ERROR(H5E_CONTEXT, H5E_CANTDEC, FAIL, "can't decrement refcount on VOL wrapping context")
+
+ /* Release the VOL connector property, if it was set */
+ if(api_state->vol_connector_prop.connector_id) {
+ /* Clean up any VOL connector info */
+ if(api_state->vol_connector_prop.connector_info)
+ if(H5VL_free_connector_info(api_state->vol_connector_prop.connector_id, api_state->vol_connector_prop.connector_info) < 0)
+ HGOTO_ERROR(H5E_CONTEXT, H5E_CANTRELEASE, FAIL, "unable to release VOL connector info object")
+ /* Decrement connector ID */
+ if(H5I_dec_ref(api_state->vol_connector_prop.connector_id) < 0)
+ HDONE_ERROR(H5E_CONTEXT, H5E_CANTDEC, FAIL, "can't close VOL connector ID")
+ } /* end if */
+
+ /* Free the state */
+ api_state = H5FL_FREE(H5CX_state_t, api_state);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5CX_free_state() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5CX_is_def_dxpl
*
* Purpose: Checks if the API context is using the library's default DXPL
@@ -723,6 +1054,71 @@ H5CX_set_dxpl(hid_t dxpl_id)
/*-------------------------------------------------------------------------
+ * Function: H5CX_set_dcpl
+ *
+ * Purpose: Sets the DCPL for the current API call context.
+ *
+ * Return: <none>
+ *
+ * Programmer: Quincey Koziol
+ * March 6, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+H5CX_set_dcpl(hid_t dcpl_id)
+{
+ H5CX_node_t **head = H5CX_get_my_context(); /* Get the pointer to the head of the API context, for this thread */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ /* Sanity check */
+ HDassert(*head);
+
+ /* Set the API context's DCPL to a new value */
+ (*head)->ctx.dcpl_id = dcpl_id;
+
+ FUNC_LEAVE_NOAPI_VOID
+} /* end H5CX_set_dcpl() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5CX_set_libver_bounds
+ *
+ * Purpose: Sets the low/high bounds according to "f" for the current API call context.
+ * When "f" is NULL, the low/high bounds are set to latest format.
+ *
+ * Return: Non-negative on success / Negative on failure
+ *
+ * Programmer: Vailin Choi
+ * March 27, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5CX_set_libver_bounds(H5F_t *f)
+{
+ H5CX_node_t **head = H5CX_get_my_context(); /* Get the pointer to the head of the API context, for this thread */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check */
+ HDassert(head && *head);
+
+ /* Set the API context value */
+ (*head)->ctx.low_bound = (f == NULL) ? H5F_LIBVER_LATEST : H5F_LOW_BOUND(f);
+ (*head)->ctx.high_bound = (f == NULL) ? H5F_LIBVER_LATEST : H5F_HIGH_BOUND(f);
+
+ /* Mark the values as valid */
+ (*head)->ctx.low_bound_valid = TRUE;
+ (*head)->ctx.high_bound_valid = TRUE;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5CX_set_libver_bounds() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5CX_set_lapl
*
* Purpose: Sets the LAPL for the current API call context.
@@ -791,6 +1187,8 @@ H5CX_set_apl(hid_t *acspl_id, const H5P_libclass_t *libclass,
*acspl_id = *libclass->def_plist_id;
else {
htri_t is_lapl; /* Whether the access property list is (or is derived from) a link access property list */
+ htri_t is_dapl; /* Whether the access property list is (or is derived from) a dataset access property list */
+ htri_t is_fapl; /* Whether the access property list is (or is derived from) a file access property list */
#ifdef H5CX_DEBUG
/* Sanity check the access property list class */
@@ -804,10 +1202,22 @@ H5CX_set_apl(hid_t *acspl_id, const H5P_libclass_t *libclass,
else if(is_lapl)
(*head)->ctx.lapl_id = *acspl_id;
+ /* Check for dataset access property and set API context if so */
+ if((is_dapl = H5P_class_isa(*libclass->pclass, *H5P_CLS_DACC->pclass)) < 0)
+ HGOTO_ERROR(H5E_CONTEXT, H5E_CANTGET, FAIL, "can't check for dataset access class")
+ else if(is_dapl)
+ (*head)->ctx.dapl_id = *acspl_id;
+
+ /* Check for file access property and set API context if so */
+ if((is_fapl = H5P_class_isa(*libclass->pclass, *H5P_CLS_FACC->pclass)) < 0)
+ HGOTO_ERROR(H5E_CONTEXT, H5E_CANTGET, FAIL, "can't check for file access class")
+ else if(is_fapl)
+ (*head)->ctx.fapl_id = *acspl_id;
+
#ifdef H5_HAVE_PARALLEL
/* If this routine is not guaranteed to be collective (i.e. it doesn't
- * modify the structural metadata in a file), check if we should use
- * a collective metadata read.
+ * modify the structural metadata in a file), check if the application
+ * specified a collective metadata read for just this operation.
*/
if(!is_collective) {
H5P_genplist_t *plist; /* Property list pointer */
@@ -881,6 +1291,7 @@ H5CX_set_loc(hid_t
#endif /* H5_HAVE_PARALLEL */
loc_id)
{
+#ifdef H5_HAVE_PARALLEL
H5CX_node_t **head = H5CX_get_my_context(); /* Get the pointer to the head of the API context, for this thread */
herr_t ret_value = SUCCEED; /* Return value */
@@ -889,7 +1300,6 @@ H5CX_set_loc(hid_t
/* Sanity check */
HDassert(head && *head);
-#ifdef H5_HAVE_PARALLEL
/* Set collective metadata read flag */
(*head)->ctx.coll_metadata_read = TRUE;
@@ -910,14 +1320,86 @@ H5CX_set_loc(hid_t
if(mpi_comm != MPI_COMM_NULL)
MPI_Barrier(mpi_comm);
} /* end if */
-#endif /* H5_HAVE_PARALLEL */
done:
FUNC_LEAVE_NOAPI(ret_value)
+#else /* H5_HAVE_PARALLEL */
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+#endif /* H5_HAVE_PARALLEL */
} /* end H5CX_set_loc() */
/*-------------------------------------------------------------------------
+ * Function: H5CX_set_vol_wrap_ctx
+ *
+ * Purpose: Sets the VOL object wrapping context for an operation.
+ *
+ * Return: Non-negative on success / Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * October 14, 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5CX_set_vol_wrap_ctx(void *vol_wrap_ctx)
+{
+ H5CX_node_t **head = H5CX_get_my_context(); /* Get the pointer to the head of the API context, for this thread */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check */
+ HDassert(head && *head);
+
+ /* Set the API context value */
+ (*head)->ctx.vol_wrap_ctx = vol_wrap_ctx;
+
+ /* Mark the value as valid */
+ (*head)->ctx.vol_wrap_ctx_valid = TRUE;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5CX_set_vol_wrap_ctx() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5CX_set_vol_connector_prop
+ *
+ * Purpose: Sets the VOL connector ID & info for an operation.
+ *
+ * Return: Non-negative on success / Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * January 3, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5CX_set_vol_connector_prop(const H5VL_connector_prop_t *vol_connector_prop)
+{
+ H5CX_node_t **head = H5CX_get_my_context(); /* Get the pointer to the head of the API context, for this thread */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check */
+ HDassert(head && *head);
+
+ /* Set the API context value */
+ H5MM_memcpy(&(*head)->ctx.vol_connector_prop, vol_connector_prop, sizeof(H5VL_connector_prop_t));
+
+ /* Mark the value as valid */
+ (*head)->ctx.vol_connector_prop_valid = TRUE;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5CX_set_vol_connector_prop() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5CX_get_dxpl
*
* Purpose: Retrieves the DXPL ID for the current API call context.
@@ -970,6 +1452,78 @@ H5CX_get_lapl(void)
/*-------------------------------------------------------------------------
+ * Function: H5CX_get_vol_wrap_ctx
+ *
+ * Purpose: Retrieves the VOL object wrapping context for an operation.
+ *
+ * Return: Non-negative on success / Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * October 14, 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5CX_get_vol_wrap_ctx(void **vol_wrap_ctx)
+{
+ H5CX_node_t **head = H5CX_get_my_context(); /* Get the pointer to the head of the API context, for this thread */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check */
+ HDassert(vol_wrap_ctx);
+ HDassert(head && *head);
+
+ /* Check for value that was set */
+ if((*head)->ctx.vol_wrap_ctx_valid)
+ /* Get the value */
+ *vol_wrap_ctx = (*head)->ctx.vol_wrap_ctx;
+ else
+ *vol_wrap_ctx = NULL;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5CX_get_vol_wrap_ctx() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5CX_get_vol_connector_prop
+ *
+ * Purpose: Retrieves the VOL connector ID & info for an operation.
+ *
+ * Return: Non-negative on success / Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * January 3, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5CX_get_vol_connector_prop(H5VL_connector_prop_t *vol_connector_prop)
+{
+ H5CX_node_t **head = H5CX_get_my_context(); /* Get the pointer to the head of the API context, for this thread */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check */
+ HDassert(vol_connector_prop);
+ HDassert(head && *head);
+
+ /* Check for value that was set */
+ if((*head)->ctx.vol_connector_prop_valid)
+ /* Get the value */
+ H5MM_memcpy(vol_connector_prop, &(*head)->ctx.vol_connector_prop, sizeof(H5VL_connector_prop_t));
+ else
+ HDmemset(vol_connector_prop, 0, sizeof(H5VL_connector_prop_t));
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5CX_get_vol_connector_prop() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5CX_get_tag
*
* Purpose: Retrieves the object tag for the current API call context.
@@ -1108,6 +1662,32 @@ H5CX_get_mpi_file_flushing(void)
FUNC_LEAVE_NOAPI((*head)->ctx.mpi_file_flushing)
} /* end H5CX_get_mpi_file_flushing() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5CX_get_mpio_rank0_bcast
+ *
+ * Purpose: Retrieves if the dataset meets read-with-rank0-and-bcast requirements for the current API call context.
+ *
+ * Return: Non-negative on success / Negative on failure
+ *
+ * Programmer: M. Breitenfeld
+ * December 31, 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+hbool_t
+H5CX_get_mpio_rank0_bcast(void)
+{
+ H5CX_node_t **head = H5CX_get_my_context(); /* Get the pointer to the head of the API context, for this thread */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ /* Sanity check */
+ HDassert(head && *head);
+
+ FUNC_LEAVE_NOAPI((*head)->ctx.rank0_bcast)
+} /* end H5CX_get_mpio_rank0_bcast() */
#endif /* H5_HAVE_PARALLEL */
@@ -1139,7 +1719,7 @@ H5CX_get_btree_split_ratios(double split_ratio[3])
H5CX_RETRIEVE_PROP_VALID(dxpl, H5P_DATASET_XFER_DEFAULT, H5D_XFER_BTREE_SPLIT_RATIO_NAME, btree_split_ratio)
/* Get the B-tree split ratio values */
- HDmemcpy(split_ratio, &(*head)->ctx.btree_split_ratio, sizeof((*head)->ctx.btree_split_ratio));
+ H5MM_memcpy(split_ratio, &(*head)->ctx.btree_split_ratio, sizeof((*head)->ctx.btree_split_ratio));
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -1824,6 +2404,193 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5CX_get_nlinks() */
+/*-------------------------------------------------------------------------
+ * Function: H5CX_get_libver_bounds
+ *
+ * Purpose: Retrieves the low/high bounds for the current API call context.
+ *
+ * Return: Non-negative on success / Negative on failure
+ *
+ * Programmer: Vailin Choi
+ * March 27, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5CX_get_libver_bounds(H5F_libver_t *low_bound, H5F_libver_t *high_bound)
+{
+ H5CX_node_t **head = H5CX_get_my_context(); /* Get the pointer to the head of the API context, for this thread */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check */
+ HDassert(low_bound);
+ HDassert(high_bound);
+ HDassert(head && *head);
+ HDassert(H5P_DEFAULT != (*head)->ctx.fapl_id);
+
+ H5CX_RETRIEVE_PROP_VALID(fapl, H5P_FILE_ACCESS_DEFAULT, H5F_ACS_LIBVER_LOW_BOUND_NAME, low_bound)
+ H5CX_RETRIEVE_PROP_VALID(fapl, H5P_FILE_ACCESS_DEFAULT, H5F_ACS_LIBVER_HIGH_BOUND_NAME, high_bound)
+
+ /* Get the values */
+ *low_bound = (*head)->ctx.low_bound;
+ *high_bound = (*head)->ctx.high_bound;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5CX_get_libver_bounds() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5CX_get_dset_min_ohdr_flag
+ *
+ * Purpose: Retrieves the flag that indicates whether the dataset object
+ * header should be minimized
+ *
+ * Return: Non-negative on success / Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * March 6, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5CX_get_dset_min_ohdr_flag(hbool_t *dset_min_ohdr_flag)
+{
+ H5CX_node_t **head = H5CX_get_my_context(); /* Get the pointer to the head of the API context, for this thread */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check */
+ HDassert(dset_min_ohdr_flag);
+ HDassert(head && *head);
+ HDassert(H5P_DEFAULT != (*head)->ctx.dcpl_id);
+
+ H5CX_RETRIEVE_PROP_VALID(dcpl, H5P_DATASET_CREATE_DEFAULT, H5D_CRT_MIN_DSET_HDR_SIZE_NAME, do_min_dset_ohdr)
+
+ /* Get the value */
+ *dset_min_ohdr_flag = (*head)->ctx.do_min_dset_ohdr;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5CX_get_dset_min_ohdr_flag() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5CX_get_ext_file_prefix
+ *
+ * Purpose: Retrieves the prefix for external file
+ *
+ * Return: Non-negative on success / Negative on failure
+ *
+ * Programmer: Raymond Lu
+ * March 6, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5CX_get_ext_file_prefix(const char **extfile_prefix)
+{
+ H5CX_node_t **head = H5CX_get_my_context(); /* Get the pointer to the head of the API context, for this thread */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check */
+ HDassert(extfile_prefix);
+ HDassert(head && *head);
+ HDassert(H5P_DEFAULT != (*head)->ctx.dapl_id);
+
+ /* Check if the value has been retrieved already */
+ if(!(*head)->ctx.extfile_prefix_valid) {
+ /* Check for default DAPL */
+ if((*head)->ctx.dapl_id == H5P_DATASET_ACCESS_DEFAULT)
+ (*head)->ctx.extfile_prefix = H5CX_def_dapl_cache.extfile_prefix;
+ else {
+ /* Check if the property list is already available */
+ if(NULL == (*head)->ctx.dapl)
+ /* Get the dataset access property list pointer */
+ if(NULL == ((*head)->ctx.dapl = (H5P_genplist_t *)H5I_object((*head)->ctx.dapl_id)))
+ HGOTO_ERROR(H5E_CONTEXT, H5E_BADTYPE, FAIL, "can't get default dataset access property list")
+
+ /* Get the prefix for the external file */
+ /* (Note: 'peek', not 'get' - if this turns out to be a problem, we may need
+ * to copy it and free this in the H5CX pop routine. -QAK)
+ */
+ if(H5P_peek((*head)->ctx.dapl, H5D_ACS_EFILE_PREFIX_NAME, &(*head)->ctx.extfile_prefix) < 0)
+ HGOTO_ERROR(H5E_CONTEXT, H5E_CANTGET, FAIL, "Can't retrieve external file prefix")
+ } /* end else */
+
+ /* Mark the value as valid */
+ (*head)->ctx.extfile_prefix_valid = TRUE;
+ } /* end if */
+
+ /* Get the value */
+ *extfile_prefix = (*head)->ctx.extfile_prefix;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5CX_get_ext_file_prefix() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5CX_get_vds_prefix
+ *
+ * Purpose: Retrieves the prefix for VDS
+ *
+ * Return: Non-negative on success / Negative on failure
+ *
+ * Programmer: Raymond Lu
+ * March 6, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5CX_get_vds_prefix(const char **vds_prefix)
+{
+ H5CX_node_t **head = H5CX_get_my_context(); /* Get the pointer to the head of the API context, for this thread */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check */
+ HDassert(vds_prefix);
+ HDassert(head && *head);
+ HDassert(H5P_DEFAULT != (*head)->ctx.dapl_id);
+
+ /* Check if the value has been retrieved already */
+ if(!(*head)->ctx.vds_prefix_valid) {
+ /* Check for default DAPL */
+ if((*head)->ctx.dapl_id == H5P_DATASET_ACCESS_DEFAULT)
+ (*head)->ctx.vds_prefix = H5CX_def_dapl_cache.vds_prefix;
+ else {
+ /* Check if the property list is already available */
+ if(NULL == (*head)->ctx.dapl)
+ /* Get the dataset access property list pointer */
+ if(NULL == ((*head)->ctx.dapl = (H5P_genplist_t *)H5I_object((*head)->ctx.dapl_id)))
+ HGOTO_ERROR(H5E_CONTEXT, H5E_BADTYPE, FAIL, "can't get default dataset access property list")
+
+ /* Get the prefix for the VDS */
+ /* (Note: 'peek', not 'get' - if this turns out to be a problem, we may need
+ * to copy it and free this in the H5CX pop routine. -QAK)
+ */
+ if(H5P_peek((*head)->ctx.dapl, H5D_ACS_VDS_PREFIX_NAME, &(*head)->ctx.vds_prefix) < 0)
+ HGOTO_ERROR(H5E_CONTEXT, H5E_CANTGET, FAIL, "Can't retrieve VDS prefix")
+ } /* end else */
+
+ /* Mark the value as valid */
+ (*head)->ctx.vds_prefix_valid = TRUE;
+ } /* end if */
+
+ /* Get the value */
+ *vds_prefix = (*head)->ctx.vds_prefix;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5CX_get_vds_prefix() */
+
/*-------------------------------------------------------------------------
* Function: H5CX_set_tag
@@ -2039,6 +2806,34 @@ H5CX_set_mpi_file_flushing(hbool_t flushing)
FUNC_LEAVE_NOAPI_VOID
} /* end H5CX_set_mpi_file_flushing() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5CX_set_mpio_rank0_bcast
+ *
+ * Purpose: Sets the "dataset meets read-with-rank0-and-bcast requirements" flag for the current API call context.
+ *
+ * Return: <none>
+ *
+ * Programmer: M. Breitenfeld
+ * December 31, 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+H5CX_set_mpio_rank0_bcast(hbool_t rank0_bcast)
+{
+ H5CX_node_t **head = H5CX_get_my_context(); /* Get the pointer to the head of the API context, for this thread */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ /* Sanity checks */
+ HDassert(head && *head);
+
+ (*head)->ctx.rank0_bcast = rank0_bcast;
+
+ FUNC_LEAVE_NOAPI_VOID
+} /* end H5CX_set_mpio_rank0_bcast() */
#endif /* H5_HAVE_PARALLEL */
@@ -2450,6 +3245,40 @@ H5CX_test_set_mpio_coll_chunk_multi_ratio_ind(int mpio_coll_chunk_multi_ratio_in
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5CX_test_set_mpio_coll_chunk_multi_ratio_ind() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5CX_test_set_mpio_coll_rank0_bcast
+ *
+ * Purpose: Sets the instrumented "read-with-rank0-bcast" flag for the current API call context.
+ *
+ * Note: Only sets value if property set in DXPL
+ *
+ * Return: Non-negative on success / Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * January 2, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5CX_test_set_mpio_coll_rank0_bcast(hbool_t mpio_coll_rank0_bcast)
+{
+ H5CX_node_t **head = H5CX_get_my_context(); /* Get the pointer to the head of the API context, for this thread */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* Sanity checks */
+ HDassert(head && *head);
+ HDassert(!((*head)->ctx.dxpl_id == H5P_DEFAULT ||
+ (*head)->ctx.dxpl_id == H5P_DATASET_XFER_DEFAULT));
+
+ H5CX_TEST_SET_PROP(H5D_XFER_COLL_RANK0_BCAST_NAME, mpio_coll_rank0_bcast)
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5CX_test_set_mpio_coll_rank0_bcast() */
#endif /* H5_HAVE_INSTRUMENTED_LIBRARY */
#endif /* H5_HAVE_PARALLEL */
@@ -2472,7 +3301,11 @@ H5CX__pop_common(void)
H5CX_node_t **head = H5CX_get_my_context(); /* Get the pointer to the head of the API context, for this thread */
H5CX_node_t *ret_value = NULL; /* Return value */
+#ifdef H5_HAVE_PARALLEL
FUNC_ENTER_STATIC
+#else
+ FUNC_ENTER_STATIC_NOERR
+#endif
/* Sanity check */
HDassert(head && *head);
@@ -2490,6 +3323,7 @@ H5CX__pop_common(void)
H5CX_SET_PROP(H5D_XFER_COLL_CHUNK_LINK_NUM_FALSE_NAME, mpio_coll_chunk_link_num_false)
H5CX_SET_PROP(H5D_XFER_COLL_CHUNK_MULTI_RATIO_COLL_NAME, mpio_coll_chunk_multi_ratio_coll)
H5CX_SET_PROP(H5D_XFER_COLL_CHUNK_MULTI_RATIO_IND_NAME, mpio_coll_chunk_multi_ratio_ind)
+ H5CX_SET_PROP(H5D_XFER_COLL_RANK0_BCAST_NAME, mpio_coll_rank0_bcast)
#endif /* H5_HAVE_INSTRUMENTED_LIBRARY */
#endif /* H5_HAVE_PARALLEL */
@@ -2497,7 +3331,9 @@ H5CX__pop_common(void)
ret_value = (*head);
(*head) = (*head)->next;
+#ifdef H5_HAVE_PARALLEL
done:
+#endif /* H5_HAVE_PARALLEL */
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5CX__pop_common() */
diff --git a/src/H5CXprivate.h b/src/H5CXprivate.h
index 44a4067..2f86adf 100644
--- a/src/H5CXprivate.h
+++ b/src/H5CXprivate.h
@@ -39,6 +39,19 @@
/* Library Private Typedefs */
/****************************/
+/* API context state */
+typedef struct H5CX_state_t {
+ hid_t dxpl_id; /* DXPL for operation */
+ hid_t lapl_id; /* LAPL for operation */
+ void *vol_wrap_ctx; /* VOL connector's "wrap context" for creating IDs */
+ H5VL_connector_prop_t vol_connector_prop; /* VOL connector property */
+
+#ifdef H5_HAVE_PARALLEL
+ /* Internal: Parallel I/O settings */
+ hbool_t coll_metadata_read; /* Whether to use collective I/O for metadata read */
+#endif /* H5_HAVE_PARALLEL */
+} H5CX_state_t;
+
/*****************************/
/* Library-private Variables */
@@ -57,22 +70,34 @@ H5_DLL herr_t H5CX_pop(void);
H5_DLL void H5CX_push_special(void);
H5_DLL hbool_t H5CX_is_def_dxpl(void);
+/* API context state routines */
+H5_DLL herr_t H5CX_retrieve_state(H5CX_state_t **api_state);
+H5_DLL herr_t H5CX_restore_state(const H5CX_state_t *api_state);
+H5_DLL herr_t H5CX_free_state(H5CX_state_t *api_state);
+
/* "Setter" routines for API context info */
H5_DLL void H5CX_set_dxpl(hid_t dxpl_id);
H5_DLL void H5CX_set_lapl(hid_t lapl_id);
+H5_DLL void H5CX_set_dcpl(hid_t dcpl_id);
+H5_DLL herr_t H5CX_set_libver_bounds(H5F_t *f);
H5_DLL herr_t H5CX_set_apl(hid_t *acspl_id, const H5P_libclass_t *libclass,
hid_t loc_id, hbool_t is_collective);
H5_DLL herr_t H5CX_set_loc(hid_t loc_id);
+H5_DLL herr_t H5CX_set_vol_wrap_ctx(void *wrap_ctx);
+H5_DLL herr_t H5CX_set_vol_connector_prop(const H5VL_connector_prop_t *vol_connector_prop);
/* "Getter" routines for API context info */
H5_DLL hid_t H5CX_get_dxpl(void);
H5_DLL hid_t H5CX_get_lapl(void);
+H5_DLL herr_t H5CX_get_vol_wrap_ctx(void **wrap_ctx);
+H5_DLL herr_t H5CX_get_vol_connector_prop(H5VL_connector_prop_t *vol_connector_prop);
H5_DLL haddr_t H5CX_get_tag(void);
H5_DLL H5AC_ring_t H5CX_get_ring(void);
#ifdef H5_HAVE_PARALLEL
H5_DLL hbool_t H5CX_get_coll_metadata_read(void);
H5_DLL herr_t H5CX_get_mpi_coll_datatypes(MPI_Datatype *btype, MPI_Datatype *ftype);
H5_DLL hbool_t H5CX_get_mpi_file_flushing(void);
+H5_DLL hbool_t H5CX_get_mpio_rank0_bcast(void);
#endif /* H5_HAVE_PARALLEL */
/* "Getter" routines for DXPL properties cached in API context */
@@ -100,6 +125,16 @@ H5_DLL herr_t H5CX_get_dt_conv_cb(H5T_conv_cb_t *cb_struct);
/* "Getter" routines for LAPL properties cached in API context */
H5_DLL herr_t H5CX_get_nlinks(size_t *nlinks);
+/* "Getter" routines for DCPL properties cached in API context */
+H5_DLL herr_t H5CX_get_dset_min_ohdr_flag(hbool_t *dset_min_ohdr_flag);
+
+/* "Getter" routines for DAPL properties cached in API context */
+H5_DLL herr_t H5CX_get_ext_file_prefix(const char **prefix_extfile);
+H5_DLL herr_t H5CX_get_vds_prefix(const char **prefix_vds);
+
+/* "Getter" routines for FAPL properties cached in API context */
+H5_DLL herr_t H5CX_get_libver_bounds(H5F_libver_t *low_bound, H5F_libver_t *high_bound);
+
/* "Setter" routines for API context info */
H5_DLL void H5CX_set_tag(haddr_t tag);
H5_DLL void H5CX_set_ring(H5AC_ring_t ring);
@@ -108,6 +143,7 @@ H5_DLL void H5CX_set_coll_metadata_read(hbool_t cmdr);
H5_DLL herr_t H5CX_set_mpi_coll_datatypes(MPI_Datatype btype, MPI_Datatype ftype);
H5_DLL herr_t H5CX_set_mpio_coll_opt(H5FD_mpio_collective_opt_t mpio_coll_opt);
H5_DLL void H5CX_set_mpi_file_flushing(hbool_t flushing);
+H5_DLL void H5CX_set_mpio_rank0_bcast(hbool_t rank0_bcast);
#endif /* H5_HAVE_PARALLEL */
/* "Setter" routines for DXPL properties cached in API context */
@@ -133,6 +169,7 @@ H5_DLL herr_t H5CX_test_set_mpio_coll_chunk_link_num_true(int mpio_coll_chunk_li
H5_DLL herr_t H5CX_test_set_mpio_coll_chunk_link_num_false(int mpio_coll_chunk_link_num_false);
H5_DLL herr_t H5CX_test_set_mpio_coll_chunk_multi_ratio_coll(int mpio_coll_chunk_multi_ratio_coll);
H5_DLL herr_t H5CX_test_set_mpio_coll_chunk_multi_ratio_ind(int mpio_coll_chunk_multi_ratio_ind);
+H5_DLL herr_t H5CX_test_set_mpio_coll_rank0_bcast(hbool_t rank0_bcast);
#endif /* H5_HAVE_INSTRUMENTED_LIBRARY */
#endif /* H5_HAVE_PARALLEL */
diff --git a/src/H5Cdbg.c b/src/H5Cdbg.c
index 08c70d9..8e65024 100644
--- a/src/H5Cdbg.c
+++ b/src/H5Cdbg.c
@@ -289,8 +289,8 @@ H5C_dump_cache_skip_list(H5C_t * cache_ptr, char * calling_fcn)
HDassert(calling_fcn != NULL);
HDfprintf(stdout, "\n\nDumping metadata cache skip list from %s.\n", calling_fcn);
- HDfprintf(stdout, " slist len = %u.\n", cache_ptr->slist_len);
- HDfprintf(stdout, " slist size = %lld.\n", (long long)(cache_ptr->slist_size));
+ HDfprintf(stdout, " slist len = %" PRIu32 ".\n", cache_ptr->slist_len);
+ HDfprintf(stdout, " slist size = %zu.\n", cache_ptr->slist_size);
if(cache_ptr->slist_len > 0) {
/* If we get this far, all entries in the cache are listed in the
@@ -310,18 +310,17 @@ H5C_dump_cache_skip_list(H5C_t * cache_ptr, char * calling_fcn)
HDassert( entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC );
HDfprintf(stdout,
- "%s%d 0x%016llx %4lld %d/%d %d %s\n",
+ "%s%d 0x%016" PRIxHADDR " %4zu %d/%d %d %s\n",
cache_ptr->prefix, i,
- (long long)(entry_ptr->addr),
- (long long)(entry_ptr->size),
+ entry_ptr->addr,
+ entry_ptr->size,
(int)(entry_ptr->is_protected),
(int)(entry_ptr->is_pinned),
(int)(entry_ptr->is_dirty),
entry_ptr->type->name);
- HDfprintf(stdout, " node_ptr = 0x%llx, item = %p\n",
- (unsigned long long)node_ptr,
- H5SL_item(node_ptr));
+ HDfprintf(stdout, " node_ptr = %p, item = %p\n",
+ node_ptr, H5SL_item(node_ptr));
/* increment node_ptr before we delete its target */
node_ptr = H5SL_next(node_ptr);
@@ -409,10 +408,10 @@ H5C_dump_coll_write_list(H5C_t * cache_ptr, char * calling_fcn)
HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDfprintf(stdout,
- "%s%d 0x%016llx %4lld %d/%d %d %s\n",
+ "%s%d 0x%016" PRIxHADDR " %4%zu %d/%d %d %s\n",
cache_ptr->prefix, i,
- (long long)(entry_ptr->addr),
- (long long)(entry_ptr->size),
+ entry_ptr->addr,
+ entry_ptr->size,
(int)(entry_ptr->is_protected),
(int)(entry_ptr->is_pinned),
(int)(entry_ptr->is_dirty),
@@ -476,42 +475,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5C_set_trace_file_ptr
- *
- * Purpose: Set the trace_file_ptr field for the cache.
- *
- * This field must either be NULL (which turns of trace
- * file logging), or be a pointer to an open file to which
- * trace file data is to be written.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: John Mainzer
- * 1/20/06
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5C_set_trace_file_ptr(H5C_t * cache_ptr, FILE * trace_file_ptr)
-{
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(FAIL)
-
- /* This would normally be an assert, but we need to use an HGOTO_ERROR
- * call to shut up the compiler.
- */
- if((NULL == cache_ptr) || (cache_ptr->magic != H5C__H5C_T_MAGIC))
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Bad cache_ptr")
-
- cache_ptr->trace_file_ptr = trace_file_ptr;
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5C_set_trace_file_ptr() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5C_stats
*
* Purpose: Prints statistics about the cache.
diff --git a/src/H5Cimage.c b/src/H5Cimage.c
index bdab1a3..db44c7a 100644
--- a/src/H5Cimage.c
+++ b/src/H5Cimage.c
@@ -1065,9 +1065,9 @@ H5C__read_cache_image(H5F_t *f, H5C_t *cache_ptr)
H5C__UPDATE_STATS_FOR_CACHE_IMAGE_READ(cache_ptr)
#ifdef H5_HAVE_PARALLEL
- if ( aux_ptr ) {
+ if ( aux_ptr ) {
- /* Broadcast cache image */
+ /* Broadcast cache image */
if ( MPI_SUCCESS !=
(mpi_result = MPI_Bcast(cache_ptr->image_buffer,
(int)cache_ptr->image_len, MPI_BYTE,
@@ -2020,11 +2020,11 @@ H5C__decode_cache_image_entry(const H5F_t *f, const H5C_t *cache_ptr,
HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed for on disk image buffer")
#if H5C_DO_MEMORY_SANITY_CHECKS
- HDmemcpy(((uint8_t *)image_ptr) + size, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
+ H5MM_memcpy(((uint8_t *)image_ptr) + size, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
#endif /* H5C_DO_MEMORY_SANITY_CHECKS */
/* Copy the entry image from the cache image block */
- HDmemcpy(image_ptr, p, size);
+ H5MM_memcpy(image_ptr, p, size);
p += size;
/* Copy data into target */
@@ -2219,7 +2219,7 @@ H5C__encode_cache_image_header(const H5F_t *f, const H5C_t *cache_ptr,
p = *buf;
/* write signature */
- HDmemcpy(p, H5C__MDCI_BLOCK_SIGNATURE, (size_t)H5C__MDCI_BLOCK_SIGNATURE_LEN);
+ H5MM_memcpy(p, H5C__MDCI_BLOCK_SIGNATURE, (size_t)H5C__MDCI_BLOCK_SIGNATURE_LEN);
p += H5C__MDCI_BLOCK_SIGNATURE_LEN;
/* write version */
@@ -2355,7 +2355,7 @@ H5C__encode_cache_image_entry(H5F_t *f, H5C_t *cache_ptr, uint8_t **buf,
H5F_addr_encode(f, &p, ie_ptr->fd_parent_addrs[u]);
/* Copy entry image */
- HDmemcpy(p, ie_ptr->image_ptr, ie_ptr->size);
+ H5MM_memcpy(p, ie_ptr->image_ptr, ie_ptr->size);
p += ie_ptr->size;
/* Update buffer pointer */
@@ -3422,11 +3422,11 @@ H5C__reconstruct_cache_entry(const H5F_t *f, H5C_t *cache_ptr,
if(NULL == (pf_entry_ptr->image_ptr = H5MM_malloc(pf_entry_ptr->size + H5C_IMAGE_EXTRA_SPACE)))
HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, NULL, "memory allocation failed for on disk image buffer")
#if H5C_DO_MEMORY_SANITY_CHECKS
- HDmemcpy(((uint8_t *)pf_entry_ptr->image_ptr) + size, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
+ H5MM_memcpy(((uint8_t *)pf_entry_ptr->image_ptr) + size, H5C_IMAGE_SANITY_VALUE, H5C_IMAGE_EXTRA_SPACE);
#endif /* H5C_DO_MEMORY_SANITY_CHECKS */
/* Copy the entry image from the cache image block */
- HDmemcpy(pf_entry_ptr->image_ptr, p, pf_entry_ptr->size);
+ H5MM_memcpy(pf_entry_ptr->image_ptr, p, pf_entry_ptr->size);
p += pf_entry_ptr->size;
/* Initialize the rest of the fields in the prefetched entry */
diff --git a/src/H5Clog.c b/src/H5Clog.c
index 3353619..cf9b7e8 100644
--- a/src/H5Clog.c
+++ b/src/H5Clog.c
@@ -13,11 +13,9 @@
/*-------------------------------------------------------------------------
*
- * Created: H5Clog.c
- * May 30 2016
- * Quincey Koziol
+ * Created: H5Clog.c
*
- * Purpose: Functions for generic cache logging in JSON format
+ * Purpose: Functions for metadata cache logging
*
*-------------------------------------------------------------------------
*/
@@ -30,14 +28,12 @@
/***********/
/* Headers */
/***********/
-#include "H5private.h" /* Generic Functions */
-#ifdef H5_HAVE_PARALLEL
-#define H5AC_FRIEND /*suppress error about including H5ACpkg */
-#include "H5ACpkg.h" /* Metadata cache */
-#endif /* H5_HAVE_PARALLEL */
-#include "H5Cpkg.h" /* Metadata cache */
-#include "H5Eprivate.h" /* Error handling */
-#include "H5MMprivate.h" /* Memory management */
+#include "H5private.h" /* Generic Functions */
+#define H5AC_FRIEND /* Suppress error about including H5ACpkg */
+#include "H5ACpkg.h" /* Metadata cache */
+#include "H5Cpkg.h" /* Cache */
+#include "H5Clog.h" /* Cache logging */
+#include "H5Eprivate.h" /* Error handling */
/****************/
@@ -77,133 +73,109 @@
/*-------------------------------------------------------------------------
- * Function: H5C_set_up_logging
+ * Function: H5C_log_set_up
*
* Purpose: Setup for metadata cache logging.
*
- * Metadata logging is enabled and disabled at two levels. This
- * function and the associated tear_down function open and close
- * the log file. the start_ and stop_logging functions are then
- * used to switch logging on/off. Optionally, logging can begin
- * as soon as the log file is opened (set via the start_immediately
- * parameter to this function).
- *
- * The log functionality is split between the H5C and H5AC
- * packages. Log state and direct log manipulation resides in
- * H5C. Log messages are generated in H5AC and sent to
- * the H5C_write_log_message function.
+ * Return: SUCCEED/FAIL
*
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Dana Robinson
- * Sunday, March 16, 2014
+ * Programmer: Dana Robinson
+ * Fall 2018
*
*-------------------------------------------------------------------------
*/
herr_t
-H5C_set_up_logging(H5C_t *cache_ptr, const char log_location[],
- hbool_t start_immediately)
+H5C_log_set_up(H5C_t *cache, const char log_location[], H5C_log_style_t style, hbool_t start_immediately)
{
-#ifdef H5_HAVE_PARALLEL
- H5AC_aux_t *aux_ptr = NULL;
-#endif /*H5_HAVE_PARALLEL*/
- char *file_name = NULL;
- size_t n_chars;
- herr_t ret_value = SUCCEED; /* Return value */
+ int mpi_rank = -1; /* -1 indicates serial (no MPI rank) */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
/* Sanity checks */
- if(NULL == cache_ptr)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "cache_ptr == NULL")
- if(H5C__H5C_T_MAGIC != cache_ptr->magic)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "cache magic value incorrect")
- if(cache_ptr->logging_enabled)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "logging already set up")
- if(NULL == log_location)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL log location not allowed")
-
- /* Possibly fix up the log file name.
- * The extra 39 characters are for adding the rank to the file name
- * under parallel HDF5. 39 characters allows > 2^127 processes which
- * should be enough for anybody.
- *
- * allocation size = <path length> + dot + <rank # length> + \0
- */
- n_chars = HDstrlen(log_location) + 1 + 39 + 1;
- if(NULL == (file_name = (char *)H5MM_calloc(n_chars * sizeof(char))))
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate memory for mdc log file name manipulation")
+ HDassert(cache);
+ HDassert(log_location);
+ /* Check logging flags */
+ if(cache->log_info->enabled)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "logging already set up")
+
+ /* Get the rank when MPI is in use. Logging clients will usually
+ * use that to create per-process logs.
+ */
#ifdef H5_HAVE_PARALLEL
- /* Add the rank to the log file name when MPI is in use */
- aux_ptr = (H5AC_aux_t *)(cache_ptr->aux_ptr);
-
- if(NULL == aux_ptr)
- HDsnprintf(file_name, n_chars, "%s", log_location);
- else {
- if(aux_ptr->magic != H5AC__H5AC_AUX_T_MAGIC)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "bad aux_ptr->magic")
- HDsnprintf(file_name, n_chars, "%s.%d", log_location, aux_ptr->mpi_rank);
- } /* end else */
-#else /* H5_HAVE_PARALLEL */
- HDsnprintf(file_name, n_chars, "%s", log_location);
-#endif /* H5_HAVE_PARALLEL */
-
- /* Open log file */
- if(NULL == (cache_ptr->log_file_ptr = HDfopen(file_name, "w")))
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "can't create mdc log file")
+ if(NULL != cache->aux_ptr)
+ mpi_rank = ((H5AC_aux_t *)(cache->aux_ptr))->mpi_rank;
+#endif /*H5_HAVE_PARALLEL*/
+
+ /* Set up logging */
+ if(H5C_LOG_STYLE_JSON == style) {
+ if(H5C_log_json_set_up(cache->log_info, log_location, mpi_rank) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to set up json logging")
+ }
+ else if(H5C_LOG_STYLE_TRACE == style) {
+ if(H5C_log_trace_set_up(cache->log_info, log_location, mpi_rank) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to set up trace logging")
+ }
+ else
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unknown logging style")
/* Set logging flags */
- cache_ptr->logging_enabled = TRUE;
- cache_ptr->currently_logging = start_immediately;
+ cache->log_info->enabled = TRUE;
+
+ /* Start logging if requested */
+ if(start_immediately)
+ if(H5C_start_logging(cache) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to start logging")
done:
- if(file_name)
- file_name = (char *)H5MM_xfree(file_name);
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5C_set_up_logging() */
+} /* H5C_log_set_up() */
/*-------------------------------------------------------------------------
- * Function: H5C_tear_down_logging
+ * Function: H5C_log_tear_down
*
* Purpose: Tear-down for metadata cache logging.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: SUCCEED/FAIL
*
- * Programmer: Dana Robinson
- * Sunday, March 16, 2014
+ * Programmer: Dana Robinson
+ * Fall 2018
*
*-------------------------------------------------------------------------
*/
herr_t
-H5C_tear_down_logging(H5C_t *cache_ptr)
+H5C_log_tear_down(H5C_t *cache)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
/* Sanity checks */
- if(NULL == cache_ptr)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "cache_ptr == NULL")
- if(H5C__H5C_T_MAGIC != cache_ptr->magic)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "cache magic value incorrect")
- if(FALSE == cache_ptr->logging_enabled)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "logging not enabled")
+ HDassert(cache);
- /* Unset logging flags */
- cache_ptr->logging_enabled = FALSE;
- cache_ptr->currently_logging = FALSE;
+ /* Check logging flags */
+ if(FALSE == cache->log_info->enabled)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "logging not enabled")
- /* Close log file */
- if(EOF == HDfclose(cache_ptr->log_file_ptr))
- HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "problem closing mdc log file")
- cache_ptr->log_file_ptr = NULL;
+ /* Stop logging if that's going on */
+ if(cache->log_info->logging)
+ if(H5C_stop_logging(cache) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to stop logging")
+
+ /* Tear down logging */
+ if(cache->log_info->cls->tear_down_logging)
+ if(cache->log_info->cls->tear_down_logging(cache->log_info) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "log-specific tear down call failed")
+
+ /* Unset logging flags */
+ cache->log_info->enabled = FALSE;
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5C_tear_down_logging() */
+} /* H5C_log_tear_down() */
/*-------------------------------------------------------------------------
@@ -211,37 +183,39 @@ H5C_tear_down_logging(H5C_t *cache_ptr)
*
* Purpose: Start logging metadata cache operations.
*
- * TODO: Add a function that dumps the current state of the
- * metadata cache.
+ * Return: SUCCEED/FAIL
*
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Dana Robinson
- * Sunday, March 16, 2014
+ * Programmer: Dana Robinson
+ * Fall 2018
*
*-------------------------------------------------------------------------
*/
herr_t
-H5C_start_logging(H5C_t *cache_ptr)
+H5C_start_logging(H5C_t *cache)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
/* Sanity checks */
- if(NULL == cache_ptr)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "cache_ptr == NULL")
- if(H5C__H5C_T_MAGIC != cache_ptr->magic)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "cache magic value incorrect")
- if(FALSE == cache_ptr->logging_enabled)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "logging not enabled")
- if(cache_ptr->currently_logging)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "logging already in progress")
+ HDassert(cache);
+
+ /* Check logging flags */
+ if(FALSE == cache->log_info->enabled)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "logging not enabled")
+
+ /* Start logging */
+ if(cache->log_info->cls->start_logging)
+ if(cache->log_info->cls->start_logging(cache->log_info) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "log-specific start call failed")
/* Set logging flags */
- cache_ptr->currently_logging = TRUE;
+ cache->log_info->logging = TRUE;
- /* TODO - Dump cache state */
+ /* Write a log message */
+ if(cache->log_info->cls->write_start_log_msg)
+ if(cache->log_info->cls->write_start_log_msg(cache->log_info->udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "log-specific write start call failed")
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -253,32 +227,41 @@ H5C_start_logging(H5C_t *cache_ptr)
*
* Purpose: Stop logging metadata cache operations.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: SUCCEED/FAIL
*
- * Programmer: Dana Robinson
- * Sunday, March 16, 2014
+ * Programmer: Dana Robinson
+ * Fall 2018
*
*-------------------------------------------------------------------------
*/
herr_t
-H5C_stop_logging(H5C_t *cache_ptr)
+H5C_stop_logging(H5C_t *cache)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
/* Sanity checks */
- if(NULL == cache_ptr)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "cache_ptr == NULL")
- if(H5C__H5C_T_MAGIC != cache_ptr->magic)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "cache magic value incorrect")
- if(FALSE == cache_ptr->logging_enabled)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "logging not enabled")
- if(FALSE == cache_ptr->currently_logging)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "logging not in progress")
+ HDassert(cache);
+
+ /* Check logging flags */
+ if(FALSE == cache->log_info->enabled)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "logging not enabled")
+ if(FALSE == cache->log_info->logging)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "logging not in progress")
+
+ /* Write a log message */
+ if(cache->log_info->cls->write_stop_log_msg)
+ if(cache->log_info->cls->write_stop_log_msg(cache->log_info->udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "log-specific write stop call failed")
+
+ /* Stop logging */
+ if(cache->log_info->cls->stop_logging)
+ if(cache->log_info->cls->stop_logging(cache->log_info) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "log-specific stop call failed")
/* Set logging flags */
- cache_ptr->currently_logging = FALSE;
+ cache->log_info->logging = FALSE;
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -289,80 +272,705 @@ H5C_stop_logging(H5C_t *cache_ptr)
* Function: H5C_get_logging_status
*
* Purpose: Determines if the cache is actively logging (via the OUT
- * parameter).
+ * parameters).
*
- * Return: Non-negative on success/Negative on failure
+ * Return: SUCCEED/FAIL
*
- * Programmer: Dana Robinson
- * Sunday, March 16, 2014
+ * Programmer: Dana Robinson
+ * Fall 2018
*
*-------------------------------------------------------------------------
*/
herr_t
-H5C_get_logging_status(const H5C_t *cache_ptr, /*OUT*/ hbool_t *is_enabled,
+H5C_get_logging_status(const H5C_t *cache, /*OUT*/ hbool_t *is_enabled,
/*OUT*/ hbool_t *is_currently_logging)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ FUNC_ENTER_NOAPI_NOERR
+
+ /* Sanity checks */
+ HDassert(cache);
+ HDassert(is_enabled);
+ HDassert(is_currently_logging);
+
+ /* Get logging flags */
+ *is_enabled = cache->log_info->enabled;
+ *is_currently_logging = cache->log_info->logging;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5C_get_logging_status() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C_log_write_create_cache_msg
+ *
+ * Purpose: Write a log message for cache creation.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C_log_write_create_cache_msg(H5C_t *cache, herr_t fxn_ret_value)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
/* Sanity checks */
- if(NULL == cache_ptr)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "cache_ptr == NULL")
- if(H5C__H5C_T_MAGIC != cache_ptr->magic)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "cache magic value incorrect")
- if(NULL == is_enabled)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "cache magic value incorrect")
- if(NULL == is_currently_logging)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "cache magic value incorrect")
-
- *is_enabled = cache_ptr->logging_enabled;
- *is_currently_logging = cache_ptr->currently_logging;
+ HDassert(cache);
+
+ /* Write a log message */
+ if(cache->log_info->cls->write_create_cache_log_msg)
+ if(cache->log_info->cls->write_create_cache_log_msg(cache->log_info->udata, fxn_ret_value) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "log-specific write create cache call failed")
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5C_get_logging_status() */
+} /* H5C_log_write_create_cache_msg() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5C_log_write_destroy_cache_msg
+ *
+ * Purpose: Write a log message for cache destruction.
+ *
+ * NOTE: This can't print out the H5AC call return value, since we
+ * won't know that until the cache is destroyed and at that
+ * point we no longer have pointers to the logging information.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C_log_write_destroy_cache_msg(H5C_t *cache)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(cache);
+
+ /* Write a log message */
+ if(cache->log_info->cls->write_destroy_cache_log_msg)
+ if(cache->log_info->cls->write_destroy_cache_log_msg(cache->log_info->udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "log-specific write destroy cache call failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C_log_write_destroy_cache_msg() */
/*-------------------------------------------------------------------------
- * Function: H5C_write_log_message
+ * Function: H5C_log_write_evict_cache_msg
*
- * Purpose: Write a message to the log file and flush the file.
- * The message string is neither modified nor freed.
+ * Purpose: Write a log message for eviction of cache entries.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: SUCCEED/FAIL
*
- * Programmer: Dana Robinson
- * Sunday, March 16, 2014
+ * Programmer: Dana Robinson
+ * Fall 2018
*
*-------------------------------------------------------------------------
*/
herr_t
-H5C_write_log_message(const H5C_t *cache_ptr, const char message[])
+H5C_log_write_evict_cache_msg(H5C_t *cache, herr_t fxn_ret_value)
{
- size_t n_chars;
- herr_t ret_value = SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(cache);
+
+ /* Write a log message */
+ if(cache->log_info->cls->write_evict_cache_log_msg)
+ if(cache->log_info->cls->write_evict_cache_log_msg(cache->log_info->udata, fxn_ret_value) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "log-specific write evict cache call failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C_log_write_evict_cache_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C_log_write_expunge_entry_msg
+ *
+ * Purpose: Write a log message for expunge of cache entries.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C_log_write_expunge_entry_msg(H5C_t *cache, haddr_t address,
+ int type_id, herr_t fxn_ret_value)
+{
+ herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
/* Sanity checks */
- if(NULL == cache_ptr)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "cache_ptr == NULL")
- if(H5C__H5C_T_MAGIC != cache_ptr->magic)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "cache magic value incorrect")
- if(FALSE == cache_ptr->currently_logging)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "not currently logging")
- if(NULL == message)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL log message not allowed")
-
- /* Write the log message and flush */
- n_chars = HDstrlen(message);
- if((int)n_chars != HDfprintf(cache_ptr->log_file_ptr, message))
- HGOTO_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "error writing log message")
- if(EOF == HDfflush(cache_ptr->log_file_ptr))
- HGOTO_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "error flushing log message")
+ HDassert(cache);
+
+ /* Write a log message */
+ if(cache->log_info->cls->write_expunge_entry_log_msg)
+ if(cache->log_info->cls->write_expunge_entry_log_msg(cache->log_info->udata, address, type_id, fxn_ret_value) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "log-specific write expunge entry call failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C_log_write_expunge_entry_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C_log_write_flush_cache_msg
+ *
+ * Purpose: Write a log message for cache flushes.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C_log_write_flush_cache_msg(H5C_t *cache, herr_t fxn_ret_value)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(cache);
+
+ /* Write a log message */
+ if(cache->log_info->cls->write_flush_cache_log_msg)
+ if(cache->log_info->cls->write_flush_cache_log_msg(cache->log_info->udata, fxn_ret_value) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "log-specific flush cache call failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C_log_write_flush_cache_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C_log_write_insert_entry_msg
+ *
+ * Purpose: Write a log message for insertion of cache entries.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C_log_write_insert_entry_msg(H5C_t *cache, haddr_t address,
+ int type_id, unsigned flags, size_t size, herr_t fxn_ret_value)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(cache);
+
+ /* Write a log message */
+ if(cache->log_info->cls->write_insert_entry_log_msg)
+ if(cache->log_info->cls->write_insert_entry_log_msg(cache->log_info->udata, address, type_id, flags, size, fxn_ret_value) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "log-specific insert entry call failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C_log_write_insert_entry_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C_log_write_mark_entry_dirty_msg
+ *
+ * Purpose: Write a log message for marking cache entries as dirty.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C_log_write_mark_entry_dirty_msg(H5C_t *cache, const H5C_cache_entry_t *entry,
+ herr_t fxn_ret_value)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(cache);
+
+ /* Write a log message */
+ HDassert(entry);
+ if(cache->log_info->cls->write_mark_entry_dirty_log_msg)
+ if(cache->log_info->cls->write_mark_entry_dirty_log_msg(cache->log_info->udata, entry, fxn_ret_value) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "log-specific mark dirty entry call failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C_log_write_mark_entry_dirty_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C_log_write_mark_entry_clean_msg
+ *
+ * Purpose: Write a log message for marking cache entries as clean.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C_log_write_mark_entry_clean_msg(H5C_t *cache, const H5C_cache_entry_t *entry,
+ herr_t fxn_ret_value)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(cache);
+
+ /* Write a log message */
+ HDassert(entry);
+ if(cache->log_info->cls->write_mark_entry_clean_log_msg)
+ if(cache->log_info->cls->write_mark_entry_clean_log_msg(cache->log_info->udata, entry, fxn_ret_value) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "log-specific mark clean entry call failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C_log_write_mark_entry_clean_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C_log_write_mark_unserialized_entry_msg
+ *
+ * Purpose: Write a log message for marking cache entries as unserialized.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C_log_write_mark_unserialized_entry_msg(H5C_t *cache,
+ const H5C_cache_entry_t *entry, herr_t fxn_ret_value)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(cache);
+
+ /* Write a log message */
+ HDassert(entry);
+ if(cache->log_info->cls->write_mark_unserialized_entry_log_msg)
+ if(cache->log_info->cls->write_mark_unserialized_entry_log_msg(cache->log_info->udata, entry, fxn_ret_value) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "log-specific mark unserialized entry call failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C_log_write_mark_unserialized_entry_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C_log_write_mark_serialized_entry_msg
+ *
+ * Purpose: Write a log message for marking cache entries as serialize.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C_log_write_mark_serialized_entry_msg(H5C_t *cache, const H5C_cache_entry_t *entry,
+ herr_t fxn_ret_value)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(cache);
+
+ /* Write a log message */
+ HDassert(entry);
+ if(cache->log_info->cls->write_mark_serialized_entry_log_msg)
+ if(cache->log_info->cls->write_mark_serialized_entry_log_msg(cache->log_info->udata, entry, fxn_ret_value) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "log-specific mark serialized entry call failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C_log_write_mark_serialized_entry_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C_log_write_move_entry_msg
+ *
+ * Purpose: Write a log message for moving a cache entry.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C_log_write_move_entry_msg(H5C_t *cache, haddr_t old_addr, haddr_t new_addr,
+ int type_id, herr_t fxn_ret_value)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(cache);
+
+ /* Write a log message */
+ if(cache->log_info->cls->write_move_entry_log_msg)
+ if(cache->log_info->cls->write_move_entry_log_msg(cache->log_info->udata, old_addr, new_addr, type_id, fxn_ret_value) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "log-specific move entry call failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C_log_write_move_entry_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C_log_write_pin_entry_msg
+ *
+ * Purpose: Write a log message for pinning a cache entry.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C_log_write_pin_entry_msg(H5C_t *cache, const H5C_cache_entry_t *entry,
+ herr_t fxn_ret_value)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(cache);
+
+ /* Write a log message */
+ HDassert(entry);
+ if(cache->log_info->cls->write_pin_entry_log_msg)
+ if(cache->log_info->cls->write_pin_entry_log_msg(cache->log_info->udata, entry, fxn_ret_value) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "log-specific pin entry call failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C_log_write_pin_entry_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C_log_write_create_fd_msg
+ *
+ * Purpose: Write a log message for creating a flush dependency between
+ * two cache entries.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C_log_write_create_fd_msg(H5C_t *cache, const H5C_cache_entry_t *parent,
+ const H5C_cache_entry_t *child, herr_t fxn_ret_value)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(cache);
+
+ /* Write a log message */
+ HDassert(parent);
+ HDassert(child);
+ if(cache->log_info->cls->write_create_fd_log_msg)
+ if(cache->log_info->cls->write_create_fd_log_msg(cache->log_info->udata, parent, child, fxn_ret_value) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "log-specific create fd call failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C_log_write_create_fd_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C_log_write_protect_entry_msg
+ *
+ * Purpose: Write a log message for protecting a cache entry.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C_log_write_protect_entry_msg(H5C_t *cache, const H5C_cache_entry_t *entry,
+ int type_id, unsigned flags, herr_t fxn_ret_value)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(cache);
+
+ /* Write a log message */
+ HDassert(entry);
+ if(cache->log_info->cls->write_protect_entry_log_msg)
+ if(cache->log_info->cls->write_protect_entry_log_msg(cache->log_info->udata, entry, type_id, flags, fxn_ret_value) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "log-specific protect entry call failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C_log_write_protect_entry_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C_log_write_resize_entry_msg
+ *
+ * Purpose: Write a log message for resizing a cache entry.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C_log_write_resize_entry_msg(H5C_t *cache, const H5C_cache_entry_t *entry,
+ size_t new_size, herr_t fxn_ret_value)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(cache);
+
+ /* Write a log message */
+ HDassert(entry);
+ if(cache->log_info->cls->write_resize_entry_log_msg)
+ if(cache->log_info->cls->write_resize_entry_log_msg(cache->log_info->udata, entry, new_size, fxn_ret_value) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "log-specific resize entry call failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C_log_write_resize_entry_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C_log_write_unpin_entry_msg
+ *
+ * Purpose: Write a log message for unpinning a cache entry.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C_log_write_unpin_entry_msg(H5C_t *cache, const H5C_cache_entry_t *entry,
+ herr_t fxn_ret_value)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(cache);
+
+ /* Write a log message */
+ HDassert(entry);
+ if(cache->log_info->cls->write_unpin_entry_log_msg)
+ if(cache->log_info->cls->write_unpin_entry_log_msg(cache->log_info->udata, entry, fxn_ret_value) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "log-specific unpin entry call failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C_log_write_unpin_entry_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C_log_write_destroy_fd_msg
+ *
+ * Purpose: Write a log message for destroying a flush dependency
+ * between two cache entries.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C_log_write_destroy_fd_msg(H5C_t *cache, const H5C_cache_entry_t *parent,
+ const H5C_cache_entry_t *child, herr_t fxn_ret_value)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(cache);
+
+ /* Write a log message */
+ HDassert(parent);
+ HDassert(child);
+ if(cache->log_info->cls->write_destroy_fd_log_msg)
+ if(cache->log_info->cls->write_destroy_fd_log_msg(cache->log_info->udata, parent, child, fxn_ret_value) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "log-specific destroy fd call failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C_log_write_destroy_fd_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C_log_write_unprotect_entry_msg
+ *
+ * Purpose: Write a log message for unprotecting a cache entry.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C_log_write_unprotect_entry_msg(H5C_t *cache, haddr_t address,
+ int type_id, unsigned flags, herr_t fxn_ret_value)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(cache);
+
+ /* Write a log message */
+ if(cache->log_info->cls->write_unprotect_entry_log_msg)
+ if(cache->log_info->cls->write_unprotect_entry_log_msg(cache->log_info->udata, address, type_id, flags, fxn_ret_value) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "log-specific unprotect entry call failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C_log_write_unprotect_entry_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C_log_write_set_cache_config_msg
+ *
+ * Purpose: Write a log message for setting the cache configuration.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C_log_write_set_cache_config_msg(H5C_t *cache, const H5AC_cache_config_t *config,
+ herr_t fxn_ret_value)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(cache);
+
+ /* Write a log message */
+ HDassert(config);
+ if(cache->log_info->cls->write_set_cache_config_log_msg)
+ if(cache->log_info->cls->write_set_cache_config_log_msg(cache->log_info->udata, config, fxn_ret_value) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "log-specific set cache config call failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C_log_write_set_cache_config_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C_log_write_remove_entry_msg
+ *
+ * Purpose: Write a log message for removing a cache entry.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C_log_write_remove_entry_msg(H5C_t *cache, const H5C_cache_entry_t *entry,
+ herr_t fxn_ret_value)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(cache);
+
+ /* Write a log message */
+ HDassert(entry);
+ if(cache->log_info->cls->write_remove_entry_log_msg)
+ if(cache->log_info->cls->write_remove_entry_log_msg(cache->log_info->udata, entry, fxn_ret_value) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "log-specific remove entry call failed")
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5C_write_log_message() */
+} /* H5C_log_write_remove_entry_msg() */
diff --git a/src/H5Clog.h b/src/H5Clog.h
new file mode 100644
index 0000000..0235c4a
--- /dev/null
+++ b/src/H5Clog.h
@@ -0,0 +1,114 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Purpose: Cache logging header file
+ */
+
+#ifndef _H5Clog_H
+#define _H5Clog_H
+
+/* Get package's private header */
+#include "H5Cprivate.h" /* Cache */
+
+/**************************/
+/* Package Private Macros */
+/**************************/
+
+/****************************/
+/* Package Private Typedefs */
+/****************************/
+
+/* Forward declaration for class struct */
+typedef struct H5C_log_info_t H5C_log_info_t;
+
+/* Class for generating logging messages */
+typedef struct H5C_log_class_t {
+ const char *name; /* String for debugging */
+
+ /* Callbacks for writing log messages */
+ herr_t (*tear_down_logging)(H5C_log_info_t *log_info);
+ herr_t (*start_logging)(H5C_log_info_t *log_info);
+ herr_t (*stop_logging)(H5C_log_info_t *log_info);
+ herr_t (*write_start_log_msg)(void *udata);
+ herr_t (*write_stop_log_msg)(void *udata);
+ herr_t (*write_create_cache_log_msg)(void *udata, herr_t fxn_ret_value);
+ herr_t (*write_destroy_cache_log_msg)(void *udata);
+ herr_t (*write_evict_cache_log_msg)(void *udata, herr_t fxn_ret_value);
+ herr_t (*write_expunge_entry_log_msg)(void *udata, haddr_t address, int type_id, herr_t fxn_ret_value);
+ herr_t (*write_flush_cache_log_msg)(void *udata, herr_t fxn_ret_value);
+ herr_t (*write_insert_entry_log_msg)(void *udata, haddr_t address, int type_id, unsigned flags, size_t size, herr_t fxn_ret_value);
+ herr_t (*write_mark_entry_dirty_log_msg)(void *udata, const H5C_cache_entry_t *entry, herr_t fxn_ret_value);
+ herr_t (*write_mark_entry_clean_log_msg)(void *udata, const H5C_cache_entry_t *entry, herr_t fxn_ret_value);
+ herr_t (*write_mark_unserialized_entry_log_msg)(void *udata, const H5C_cache_entry_t *entry, herr_t fxn_ret_value);
+ herr_t (*write_mark_serialized_entry_log_msg)(void *udata, const H5C_cache_entry_t *entry, herr_t fxn_ret_value);
+ herr_t (*write_move_entry_log_msg)(void *udata, haddr_t old_addr, haddr_t new_addr, int type_id, herr_t fxn_ret_value);
+ herr_t (*write_pin_entry_log_msg)(void *udata, const H5C_cache_entry_t *entry, herr_t fxn_ret_value);
+ herr_t (*write_create_fd_log_msg)(void *udata, const H5C_cache_entry_t *parent, const H5C_cache_entry_t *child, herr_t fxn_ret_value);
+ herr_t (*write_protect_entry_log_msg)(void *udata, const H5C_cache_entry_t *entry, int type_id, unsigned flags, herr_t fxn_ret_value);
+ herr_t (*write_resize_entry_log_msg)(void *udata, const H5C_cache_entry_t *entry, size_t new_size, herr_t fxn_ret_value);
+ herr_t (*write_unpin_entry_log_msg)(void *udata, const H5C_cache_entry_t *entry, herr_t fxn_ret_value);
+ herr_t (*write_destroy_fd_log_msg)(void *udata, const H5C_cache_entry_t *parent, const H5C_cache_entry_t *child, herr_t fxn_ret_value);
+ herr_t (*write_unprotect_entry_log_msg)(void *udata, haddr_t address, int type_id, unsigned flags, herr_t fxn_ret_value);
+ herr_t (*write_set_cache_config_log_msg)(void *udata, const H5AC_cache_config_t *config, herr_t fxn_ret_value);
+ herr_t (*write_remove_entry_log_msg)(void *udata, const H5C_cache_entry_t *entry, herr_t fxn_ret_value);
+
+} H5C_log_class_t;
+
+/* Logging information */
+struct H5C_log_info_t {
+ hbool_t enabled; /* Was the logging set up? */
+ hbool_t logging; /* Are we currently logging? */
+ H5C_log_class_t *cls; /* Callbacks for writing log messages */
+ void *udata; /* Log-specific data */
+};
+
+
+/*****************************/
+/* Package Private Variables */
+/*****************************/
+
+
+/******************************/
+/* Package Private Prototypes */
+/******************************/
+H5_DLL herr_t H5C_log_set_up(H5C_t *cache, const char log_location[], H5C_log_style_t style, hbool_t start_immediately);
+H5_DLL herr_t H5C_log_tear_down(H5C_t *cache);
+
+H5_DLL herr_t H5C_log_write_create_cache_msg(H5C_t *cache, herr_t fxn_ret_value);
+H5_DLL herr_t H5C_log_write_destroy_cache_msg(H5C_t *cache);
+H5_DLL herr_t H5C_log_write_evict_cache_msg(H5C_t *cache, herr_t fxn_ret_value);
+H5_DLL herr_t H5C_log_write_expunge_entry_msg(H5C_t *cache, haddr_t address, int type_id, herr_t fxn_ret_value);
+H5_DLL herr_t H5C_log_write_flush_cache_msg(H5C_t *cache, herr_t fxn_ret_value);
+H5_DLL herr_t H5C_log_write_insert_entry_msg(H5C_t *cache, haddr_t address, int type_id, unsigned flags, size_t size, herr_t fxn_ret_value);
+H5_DLL herr_t H5C_log_write_mark_entry_dirty_msg(H5C_t *cache, const H5C_cache_entry_t *entry, herr_t fxn_ret_value);
+H5_DLL herr_t H5C_log_write_mark_entry_clean_msg(H5C_t *cache, const H5C_cache_entry_t *entry, herr_t fxn_ret_value);
+H5_DLL herr_t H5C_log_write_mark_unserialized_entry_msg(H5C_t *cache, const H5C_cache_entry_t *entry, herr_t fxn_ret_value);
+H5_DLL herr_t H5C_log_write_mark_serialized_entry_msg(H5C_t *cache, const H5C_cache_entry_t *entry, herr_t fxn_ret_value);
+H5_DLL herr_t H5C_log_write_move_entry_msg(H5C_t *cache, haddr_t old_addr, haddr_t new_addr, int type_id, herr_t fxn_ret_value);
+H5_DLL herr_t H5C_log_write_pin_entry_msg(H5C_t *cache, const H5C_cache_entry_t *entry, herr_t fxn_ret_value);
+H5_DLL herr_t H5C_log_write_create_fd_msg(H5C_t *cache, const H5C_cache_entry_t *parent, const H5C_cache_entry_t *child, herr_t fxn_ret_value);
+H5_DLL herr_t H5C_log_write_protect_entry_msg(H5C_t *cache, const H5C_cache_entry_t *entry, int type_id, unsigned flags, herr_t fxn_ret_value);
+H5_DLL herr_t H5C_log_write_resize_entry_msg(H5C_t *cache, const H5C_cache_entry_t *entry, size_t new_size, herr_t fxn_ret_value);
+H5_DLL herr_t H5C_log_write_unpin_entry_msg(H5C_t *cache, const H5C_cache_entry_t *entry, herr_t fxn_ret_value);
+H5_DLL herr_t H5C_log_write_destroy_fd_msg(H5C_t *cache, const H5C_cache_entry_t *parent, const H5C_cache_entry_t *child, herr_t fxn_ret_value);
+H5_DLL herr_t H5C_log_write_unprotect_entry_msg(H5C_t *cache, haddr_t address, int type_id, unsigned flags, herr_t fxn_ret_value);
+H5_DLL herr_t H5C_log_write_set_cache_config_msg(H5C_t *cache, const H5AC_cache_config_t *config, herr_t fxn_ret_value);
+H5_DLL herr_t H5C_log_write_remove_entry_msg(H5C_t *cache, const H5C_cache_entry_t *entry, herr_t fxn_ret_value);
+
+/* Logging-specific setup functions */
+H5_DLL herr_t H5C_log_json_set_up(H5C_log_info_t *log_info, const char log_location[], int mpi_rank);
+H5_DLL herr_t H5C_log_trace_set_up(H5C_log_info_t *log_info, const char log_location[], int mpi_rank);
+
+#endif /* _H5Clog_H */
+
diff --git a/src/H5Clog_json.c b/src/H5Clog_json.c
new file mode 100644
index 0000000..dd9e9b2
--- /dev/null
+++ b/src/H5Clog_json.c
@@ -0,0 +1,1364 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5Clog_json.c
+ *
+ * Purpose: Cache log implementation that emits JSON-formatted log
+ * entries for consumption by new-fangled data analysis tools.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+#include "H5Cmodule.h" /* This source code file is part of the H5C module */
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Cpkg.h" /* Cache */
+#include "H5Clog.h" /* Cache logging */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5MMprivate.h" /* Memory management */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+/* Max log message size */
+#define H5C_MAX_JSON_LOG_MSG_SIZE 1024
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+typedef struct H5C_log_json_udata_t {
+ FILE *outfile;
+ char *message;
+} H5C_log_json_udata_t;
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+/* Internal message handling calls */
+static herr_t H5C__json_write_log_message(H5C_log_json_udata_t *json_udata);
+
+/* Log message callbacks */
+static herr_t H5C__json_tear_down_logging(H5C_log_info_t *log_info);
+static herr_t H5C__json_write_start_log_msg(void *udata);
+static herr_t H5C__json_write_stop_log_msg(void *udata);
+static herr_t H5C__json_write_create_cache_log_msg(void *udata, herr_t fxn_ret_value);
+static herr_t H5C__json_write_destroy_cache_log_msg(void *udata);
+static herr_t H5C__json_write_evict_cache_log_msg(void *udata, herr_t fxn_ret_value);
+static herr_t H5C__json_write_expunge_entry_log_msg(void *udata, haddr_t address, int type_id, herr_t fxn_ret_value);
+static herr_t H5C__json_write_flush_cache_log_msg(void *udata, herr_t fxn_ret_value);
+static herr_t H5C__json_write_insert_entry_log_msg(void *udata, haddr_t address, int type_id, unsigned flags, size_t size, herr_t fxn_ret_value);
+static herr_t H5C__json_write_mark_entry_dirty_log_msg(void *udata, const H5C_cache_entry_t *entry, herr_t fxn_ret_value);
+static herr_t H5C__json_write_mark_entry_clean_log_msg(void *udata, const H5C_cache_entry_t *entry, herr_t fxn_ret_value);
+static herr_t H5C__json_write_mark_unserialized_entry_log_msg(void *udata, const H5C_cache_entry_t *entry, herr_t fxn_ret_value);
+static herr_t H5C__json_write_mark_serialized_entry_log_msg(void *udata, const H5C_cache_entry_t *entry, herr_t fxn_ret_value);
+static herr_t H5C__json_write_move_entry_log_msg(void *udata, haddr_t old_addr, haddr_t new_addr, int type_id, herr_t fxn_ret_value);
+static herr_t H5C__json_write_pin_entry_log_msg(void *udata, const H5C_cache_entry_t *entry, herr_t fxn_ret_value);
+static herr_t H5C__json_write_create_fd_log_msg(void *udata, const H5C_cache_entry_t *parent, const H5C_cache_entry_t *child, herr_t fxn_ret_value);
+static herr_t H5C__json_write_protect_entry_log_msg(void *udata, const H5C_cache_entry_t *entry, int type_id, unsigned flags, herr_t fxn_ret_value);
+static herr_t H5C__json_write_resize_entry_log_msg(void *udata, const H5C_cache_entry_t *entry, size_t new_size, herr_t fxn_ret_value);
+static herr_t H5C__json_write_unpin_entry_log_msg(void *udata, const H5C_cache_entry_t *entry, herr_t fxn_ret_value);
+static herr_t H5C__json_write_destroy_fd_log_msg(void *udata, const H5C_cache_entry_t *parent, const H5C_cache_entry_t *child, herr_t fxn_ret_value);
+static herr_t H5C__json_write_unprotect_entry_log_msg(void *udata, haddr_t address, int type_id, unsigned flags, herr_t fxn_ret_value);
+static herr_t H5C__json_write_set_cache_config_log_msg(void *udata, const H5AC_cache_config_t *config, herr_t fxn_ret_value);
+static herr_t H5C__json_write_remove_entry_log_msg(void *udata, const H5C_cache_entry_t *entry, herr_t fxn_ret_value);
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* Note that there's no cache set up call since that's the
+ * place where this struct is wired into the cache.
+ */
+static H5C_log_class_t H5C_json_log_class_g = {
+ "json",
+ H5C__json_tear_down_logging,
+ NULL, /* start logging */
+ NULL, /* stop logging */
+ H5C__json_write_start_log_msg,
+ H5C__json_write_stop_log_msg,
+ H5C__json_write_create_cache_log_msg,
+ H5C__json_write_destroy_cache_log_msg,
+ H5C__json_write_evict_cache_log_msg,
+ H5C__json_write_expunge_entry_log_msg,
+ H5C__json_write_flush_cache_log_msg,
+ H5C__json_write_insert_entry_log_msg,
+ H5C__json_write_mark_entry_dirty_log_msg,
+ H5C__json_write_mark_entry_clean_log_msg,
+ H5C__json_write_mark_unserialized_entry_log_msg,
+ H5C__json_write_mark_serialized_entry_log_msg,
+ H5C__json_write_move_entry_log_msg,
+ H5C__json_write_pin_entry_log_msg,
+ H5C__json_write_create_fd_log_msg,
+ H5C__json_write_protect_entry_log_msg,
+ H5C__json_write_resize_entry_log_msg,
+ H5C__json_write_unpin_entry_log_msg,
+ H5C__json_write_destroy_fd_log_msg,
+ H5C__json_write_unprotect_entry_log_msg,
+ H5C__json_write_set_cache_config_log_msg,
+ H5C__json_write_remove_entry_log_msg
+};
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__json_write_log_message
+ *
+ * Purpose: Write a message to the log file and flush the file.
+ * The message string is neither modified nor freed.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__json_write_log_message(H5C_log_json_udata_t *json_udata)
+{
+ size_t n_chars;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(json_udata);
+ HDassert(json_udata->outfile);
+ HDassert(json_udata->message);
+
+ /* Write the log message and flush */
+ n_chars = HDstrlen(json_udata->message);
+ if((int)n_chars != HDfprintf(json_udata->outfile, json_udata->message))
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "error writing log message")
+ HDmemset((void *)(json_udata->message), 0, (size_t)(n_chars * sizeof(char)));
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__json_write_log_message() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C_log_json_set_up
+ *
+ * Purpose: Setup for metadata cache logging.
+ *
+ * Metadata logging is enabled and disabled at two levels. This
+ * function and the associated tear_down function open and close
+ * the log file. the start_ and stop_logging functions are then
+ * used to switch logging on/off. Optionally, logging can begin
+ * as soon as the log file is opened (set via the start_immediately
+ * parameter to this function).
+ *
+ * The log functionality is split between the H5C and H5AC
+ * packages. Log state and direct log manipulation resides in
+ * H5C. Log messages are generated in H5AC and sent to
+ * the H5C__json_write_log_message function.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C_log_json_set_up(H5C_log_info_t *log_info, const char log_location[], int mpi_rank)
+{
+ H5C_log_json_udata_t *json_udata = NULL;
+ char *file_name = NULL;
+ size_t n_chars;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(log_info);
+ HDassert(log_location);
+
+ /* Set up the class struct */
+ log_info->cls = &H5C_json_log_class_g;
+
+ /* Allocate memory for the JSON-specific data */
+ if(NULL == (log_info->udata = H5MM_calloc(sizeof(H5C_log_json_udata_t))))
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed")
+ json_udata = (H5C_log_json_udata_t *)(log_info->udata);
+
+ /* Allocate memory for the message buffer */
+ if(NULL == (json_udata->message = (char *)H5MM_calloc(H5C_MAX_JSON_LOG_MSG_SIZE * sizeof(char))))
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed")
+
+ /* Possibly fix up the log file name.
+ * The extra 39 characters are for adding the rank to the file name
+ * under parallel HDF5. 39 characters allows > 2^127 processes which
+ * should be enough for anybody.
+ *
+ * allocation size = "RANK_" + <rank # length> + dot + <path length> + \0
+ */
+ n_chars = 5 + 39 + 1 + HDstrlen(log_location) + 1;
+ if(NULL == (file_name = (char *)H5MM_calloc(n_chars * sizeof(char))))
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "can't allocate memory for mdc log file name manipulation")
+
+ /* Add the rank to the log file name when MPI is in use */
+ if(-1 == mpi_rank)
+ HDsnprintf(file_name, n_chars, "%s", log_location);
+ else
+ HDsnprintf(file_name, n_chars, "RANK_%d.%s", mpi_rank, log_location);
+
+ /* Open log file and set it to be unbuffered */
+ if(NULL == (json_udata->outfile = HDfopen(file_name, "w")))
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "can't create mdc log file")
+ HDsetbuf(json_udata->outfile, NULL);
+
+ done:
+ if(file_name)
+ H5MM_xfree(file_name);
+
+ /* Free and reset the log info struct on errors */
+ if(FAIL == ret_value) {
+ /* Free */
+ if(json_udata && json_udata->message)
+ H5MM_xfree(json_udata->message);
+ if(json_udata)
+ H5MM_xfree(json_udata);
+
+ /* Reset */
+ log_info->udata = NULL;
+ log_info->cls = NULL;
+ }
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C_log_json_set_up() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__json_tear_down_logging
+ *
+ * Purpose: Tear-down for metadata cache logging.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__json_tear_down_logging(H5C_log_info_t *log_info)
+{
+ H5C_log_json_udata_t *json_udata = NULL;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(log_info);
+
+ /* Alias */
+ json_udata = (H5C_log_json_udata_t *)(log_info->udata);
+
+ /* Free the message buffer */
+ H5MM_xfree(json_udata->message);
+
+ /* Close log file */
+ if(EOF == HDfclose(json_udata->outfile))
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "problem closing mdc log file")
+ json_udata->outfile = NULL;
+
+ /* Fre the udata */
+ H5MM_xfree(json_udata);
+
+ /* Reset the log class info and udata */
+ log_info->cls = NULL;
+ log_info->udata = NULL;
+
+ done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__json_tear_down_logging() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__json_write_start_log_msg
+ *
+ * Purpose: Write a log message when logging starts.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__json_write_start_log_msg(void *udata)
+{
+ H5C_log_json_udata_t *json_udata = (H5C_log_json_udata_t *)(udata);
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(json_udata);
+ HDassert(json_udata->message);
+
+ /* Create the log message string (opens the JSON array) */
+ HDsnprintf(json_udata->message, H5C_MAX_JSON_LOG_MSG_SIZE,
+"\
+{\n\
+\"HDF5 metadata cache log messages\" : [\n\
+{\
+\"timestamp\":%lld,\
+\"action\":\"logging start\"\
+},\n\
+"
+ , (long long)HDtime(NULL));
+
+ /* Write the log message to the file */
+ if(H5C__json_write_log_message(json_udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__json_write_start_log_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__json_write_stop_log_msg
+ *
+ * Purpose: Write a log message when logging ends.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__json_write_stop_log_msg(void *udata)
+{
+ H5C_log_json_udata_t *json_udata = (H5C_log_json_udata_t *)(udata);
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(json_udata);
+ HDassert(json_udata->message);
+
+ /* Create the log message string (closes the JSON array) */
+ HDsnprintf(json_udata->message, H5C_MAX_JSON_LOG_MSG_SIZE,
+"\
+{\
+\"timestamp\":%lld,\
+\"action\":\"logging stop\"\
+}\n\
+]}\n\
+"
+ , (long long)HDtime(NULL));
+
+ /* Write the log message to the file */
+ if(H5C__json_write_log_message(json_udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__json_write_stop_log_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__json_write_create_cache_log_msg
+ *
+ * Purpose: Write a log message for cache creation.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__json_write_create_cache_log_msg(void *udata, herr_t fxn_ret_value)
+{
+ H5C_log_json_udata_t *json_udata = (H5C_log_json_udata_t *)(udata);
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(json_udata);
+ HDassert(json_udata->message);
+
+ /* Create the log message string */
+ HDsnprintf(json_udata->message, H5C_MAX_JSON_LOG_MSG_SIZE,
+"\
+{\
+\"timestamp\":%lld,\
+\"action\":\"create\",\
+\"returned\":%d\
+},\n\
+"
+ , (long long)HDtime(NULL), (int)fxn_ret_value);
+
+ /* Write the log message to the file */
+ if(H5C__json_write_log_message(json_udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__json_write_create_cache_log_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__json_write_destroy_cache_log_msg
+ *
+ * Purpose: Write a log message for cache destruction.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__json_write_destroy_cache_log_msg(void *udata)
+{
+ H5C_log_json_udata_t *json_udata = (H5C_log_json_udata_t *)(udata);
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(json_udata);
+ HDassert(json_udata->message);
+
+ /* Create the log message string */
+ HDsnprintf(json_udata->message, H5C_MAX_JSON_LOG_MSG_SIZE,
+"\
+{\
+\"timestamp\":%lld,\
+\"action\":\"destroy\"\
+},\n\
+"
+ , (long long)HDtime(NULL));
+
+ /* Write the log message to the file */
+ if(H5C__json_write_log_message(json_udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__json_write_destroy_cache_log_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__json_write_evict_cache_log_msg
+ *
+ * Purpose: Write a log message for eviction of cache entries.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__json_write_evict_cache_log_msg(void *udata, herr_t fxn_ret_value)
+{
+ H5C_log_json_udata_t *json_udata = (H5C_log_json_udata_t *)(udata);
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(json_udata);
+ HDassert(json_udata->message);
+
+ /* Create the log message string */
+ HDsnprintf(json_udata->message, H5C_MAX_JSON_LOG_MSG_SIZE,
+"\
+{\
+\"timestamp\":%lld,\
+\"action\":\"evict\",\
+\"returned\":%d\
+},\n\
+"
+ , (long long)HDtime(NULL), (int)fxn_ret_value);
+
+ /* Write the log message to the file */
+ if(H5C__json_write_log_message(json_udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__json_write_evict_cache_log_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__json_write_expunge_entry_log_msg
+ *
+ * Purpose: Write a log message for expunge of cache entries.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__json_write_expunge_entry_log_msg(void *udata, haddr_t address,
+ int type_id, herr_t fxn_ret_value)
+{
+ H5C_log_json_udata_t *json_udata = (H5C_log_json_udata_t *)(udata);
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(json_udata);
+ HDassert(json_udata->message);
+
+ /* Create the log message string */
+ HDsnprintf(json_udata->message, H5C_MAX_JSON_LOG_MSG_SIZE,
+"\
+{\
+\"timestamp\":%lld,\
+\"action\":\"expunge\",\
+\"address\":0x%lx,\
+\"type_id\":%d,\
+\"returned\":%d\
+},\n\
+"
+ , (long long)HDtime(NULL), (unsigned long)address, (int)type_id, (int)fxn_ret_value);
+
+
+ /* Write the log message to the file */
+ if(H5C__json_write_log_message(json_udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__json_write_expunge_entry_log_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__json_write_flush_cache_log_msg
+ *
+ * Purpose: Write a log message for cache flushes.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__json_write_flush_cache_log_msg(void *udata, herr_t fxn_ret_value)
+{
+ H5C_log_json_udata_t *json_udata = (H5C_log_json_udata_t *)(udata);
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(json_udata);
+ HDassert(json_udata->message);
+
+ /* Create the log message string */
+ HDsnprintf(json_udata->message, H5C_MAX_JSON_LOG_MSG_SIZE,
+"\
+{\
+\"timestamp\":%lld,\
+\"action\":\"flush\",\
+\"returned\":%d\
+},\n\
+"
+ , (long long)HDtime(NULL), (int)fxn_ret_value);
+
+ /* Write the log message to the file */
+ if(H5C__json_write_log_message(json_udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__json_write_flush_cache_log_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__json_write_insert_entry_log_msg
+ *
+ * Purpose: Write a log message for insertion of cache entries.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__json_write_insert_entry_log_msg(void *udata, haddr_t address,
+ int type_id, unsigned flags, size_t size, herr_t fxn_ret_value)
+{
+ H5C_log_json_udata_t *json_udata = (H5C_log_json_udata_t *)(udata);
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(json_udata);
+ HDassert(json_udata->message);
+
+ /* Create the log message string */
+ HDsnprintf(json_udata->message, H5C_MAX_JSON_LOG_MSG_SIZE,
+"\
+{\
+\"timestamp\":%lld,\
+\"action\":\"insert\",\
+\"address\":0x%lx,\
+\"type_id\":%d,\
+\"flags\":0x%x,\
+\"size\":%d,\
+\"returned\":%d\
+},\n\
+"
+ , (long long)HDtime(NULL), (unsigned long)address, type_id, flags,
+ (int)size, (int)fxn_ret_value);
+
+ /* Write the log message to the file */
+ if(H5C__json_write_log_message(json_udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__json_write_insert_entry_log_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__json_write_mark_entry_dirty_log_msg
+ *
+ * Purpose: Write a log message for marking cache entries as dirty.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__json_write_mark_entry_dirty_log_msg(void *udata, const H5C_cache_entry_t *entry,
+ herr_t fxn_ret_value)
+{
+ H5C_log_json_udata_t *json_udata = (H5C_log_json_udata_t *)(udata);
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(json_udata);
+ HDassert(json_udata->message);
+ HDassert(entry);
+
+ /* Create the log message string */
+ HDsnprintf(json_udata->message, H5C_MAX_JSON_LOG_MSG_SIZE,
+"\
+{\
+\"timestamp\":%lld,\
+\"action\":\"dirty\",\
+\"address\":0x%lx,\
+\"returned\":%d\
+},\n\
+"
+ , (long long)HDtime(NULL), (unsigned long)entry->addr, (int)fxn_ret_value);
+
+ /* Write the log message to the file */
+ if(H5C__json_write_log_message(json_udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__json_write_mark_entry_dirty_log_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__json_write_mark_entry_clean_log_msg
+ *
+ * Purpose: Write a log message for marking cache entries as clean.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__json_write_mark_entry_clean_log_msg(void *udata, const H5C_cache_entry_t *entry,
+ herr_t fxn_ret_value)
+{
+ H5C_log_json_udata_t *json_udata = (H5C_log_json_udata_t *)(udata);
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(json_udata);
+ HDassert(json_udata->message);
+ HDassert(entry);
+
+ /* Create the log message string */
+ HDsnprintf(json_udata->message, H5C_MAX_JSON_LOG_MSG_SIZE,
+"\
+{\
+\"timestamp\":%lld,\
+\"action\":\"clean\",\
+\"address\":0x%lx,\
+\"returned\":%d\
+},\n\
+"
+ , (long long)HDtime(NULL), (unsigned long)entry->addr, (int)fxn_ret_value);
+
+ /* Write the log message to the file */
+ if(H5C__json_write_log_message(json_udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__json_write_mark_entry_clean_log_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__json_write_mark_unserialized_entry_log_msg
+ *
+ * Purpose: Write a log message for marking cache entries as unserialized.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__json_write_mark_unserialized_entry_log_msg(void *udata,
+ const H5C_cache_entry_t *entry, herr_t fxn_ret_value)
+{
+ H5C_log_json_udata_t *json_udata = (H5C_log_json_udata_t *)(udata);
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(json_udata);
+ HDassert(json_udata->message);
+ HDassert(entry);
+
+ /* Create the log message string */
+ HDsnprintf(json_udata->message, H5C_MAX_JSON_LOG_MSG_SIZE,
+"\
+{\
+\"timestamp\":%lld,\
+\"action\":\"unserialized\",\
+\"address\":0x%lx,\
+\"returned\":%d\
+},\n\
+"
+ , (long long)HDtime(NULL), (unsigned long)entry->addr, (int)fxn_ret_value);
+
+ /* Write the log message to the file */
+ if(H5C__json_write_log_message(json_udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__json_write_mark_unserialized_entry_log_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__json_write_mark_serialize_entry_log_msg
+ *
+ * Purpose: Write a log message for marking cache entries as serialize.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__json_write_mark_serialized_entry_log_msg(void *udata, const H5C_cache_entry_t *entry,
+ herr_t fxn_ret_value)
+{
+ H5C_log_json_udata_t *json_udata = (H5C_log_json_udata_t *)(udata);
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(json_udata);
+ HDassert(json_udata->message);
+ HDassert(entry);
+
+ /* Create the log message string */
+ HDsnprintf(json_udata->message, H5C_MAX_JSON_LOG_MSG_SIZE,
+"\
+{\
+\"timestamp\":%lld,\
+\"action\":\"serialized\",\
+\"address\":0x%lx,\
+\"returned\":%d\
+},\n\
+"
+ , (long long)HDtime(NULL), (unsigned long)entry->addr, (int)fxn_ret_value);
+
+ /* Write the log message to the file */
+ if(H5C__json_write_log_message(json_udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__json_write_mark_serialized_entry_log_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__json_write_move_entry_log_msg
+ *
+ * Purpose: Write a log message for moving a cache entry.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__json_write_move_entry_log_msg(void *udata, haddr_t old_addr, haddr_t new_addr,
+ int type_id, herr_t fxn_ret_value)
+{
+ H5C_log_json_udata_t *json_udata = (H5C_log_json_udata_t *)(udata);
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(json_udata);
+ HDassert(json_udata->message);
+
+ /* Create the log message string */
+ HDsnprintf(json_udata->message, H5C_MAX_JSON_LOG_MSG_SIZE,
+"\
+{\
+\"timestamp\":%lld,\
+\"action\":\"move\",\
+\"old_address\":0x%lx,\
+\"new_address\":0x%lx,\
+\"type_id\":%d,\
+\"returned\":%d\
+},\n\
+"
+ , (long long)HDtime(NULL), (unsigned long)old_addr,
+ (unsigned long)new_addr, type_id, (int)fxn_ret_value);
+
+ /* Write the log message to the file */
+ if(H5C__json_write_log_message(json_udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__json_write_move_entry_log_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__json_write_pin_entry_log_msg
+ *
+ * Purpose: Write a log message for pinning a cache entry.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__json_write_pin_entry_log_msg(void *udata, const H5C_cache_entry_t *entry,
+ herr_t fxn_ret_value)
+{
+ H5C_log_json_udata_t *json_udata = (H5C_log_json_udata_t *)(udata);
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(json_udata);
+ HDassert(json_udata->message);
+ HDassert(entry);
+
+ /* Create the log message string */
+ HDsnprintf(json_udata->message, H5C_MAX_JSON_LOG_MSG_SIZE,
+"\
+{\
+\"timestamp\":%lld,\
+\"action\":\"pin\",\
+\"address\":0x%lx,\
+\"returned\":%d\
+},\n\
+"
+ , (long long)HDtime(NULL), (unsigned long)entry->addr,
+ (int)fxn_ret_value);
+
+ /* Write the log message to the file */
+ if(H5C__json_write_log_message(json_udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__json_write_pin_entry_log_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__json_write_create_fd_log_msg
+ *
+ * Purpose: Write a log message for creating a flush dependency between
+ * two cache entries.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__json_write_create_fd_log_msg(void *udata, const H5C_cache_entry_t *parent,
+ const H5C_cache_entry_t *child, herr_t fxn_ret_value)
+{
+ H5C_log_json_udata_t *json_udata = (H5C_log_json_udata_t *)(udata);
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(json_udata);
+ HDassert(json_udata->message);
+ HDassert(parent);
+ HDassert(child);
+
+ /* Create the log message string */
+ HDsnprintf(json_udata->message, H5C_MAX_JSON_LOG_MSG_SIZE,
+"\
+{\
+\"timestamp\":%lld,\
+\"action\":\"create_fd\",\
+\"parent_addr\":0x%lx,\
+\"child_addr\":0x%lx,\
+\"returned\":%d\
+},\n\
+"
+ , (long long)HDtime(NULL), (unsigned long)parent->addr,
+ (unsigned long)child->addr, (int)fxn_ret_value);
+
+ /* Write the log message to the file */
+ if(H5C__json_write_log_message(json_udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__json_write_create_fd_log_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__json_write_protect_entry_log_msg
+ *
+ * Purpose: Write a log message for protecting a cache entry.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__json_write_protect_entry_log_msg(void *udata, const H5C_cache_entry_t *entry,
+ int type_id, unsigned flags, herr_t fxn_ret_value)
+{
+ H5C_log_json_udata_t *json_udata = (H5C_log_json_udata_t *)(udata);
+ char rw_s[16];
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(json_udata);
+ HDassert(json_udata->message);
+ HDassert(entry);
+
+ if(H5C__READ_ONLY_FLAG == flags)
+ HDstrcpy(rw_s, "READ");
+ else
+ HDstrcpy(rw_s, "WRITE");
+
+ /* Create the log message string */
+ HDsnprintf(json_udata->message, H5C_MAX_JSON_LOG_MSG_SIZE,
+"\
+{\
+\"timestamp\":%lld,\
+\"action\":\"protect\",\
+\"address\":0x%lx,\
+\"type_id\":%d,\
+\"readwrite\":\"%s\",\
+\"size\":%d,\
+\"returned\":%d\
+},\n\
+"
+ , (long long)HDtime(NULL), (unsigned long)entry->addr,
+ type_id, rw_s, (int)entry->size, (int)fxn_ret_value);
+
+ /* Write the log message to the file */
+ if(H5C__json_write_log_message(json_udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__json_write_protect_entry_log_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__json_write_resize_entry_log_msg
+ *
+ * Purpose: Write a log message for resizing a cache entry.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__json_write_resize_entry_log_msg(void *udata, const H5C_cache_entry_t *entry,
+ size_t new_size, herr_t fxn_ret_value)
+{
+ H5C_log_json_udata_t *json_udata = (H5C_log_json_udata_t *)(udata);
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(json_udata);
+ HDassert(json_udata->message);
+ HDassert(entry);
+
+ /* Create the log message string */
+ HDsnprintf(json_udata->message, H5C_MAX_JSON_LOG_MSG_SIZE,
+"\
+{\
+\"timestamp\":%lld,\
+\"action\":\"resize\",\
+\"address\":0x%lx,\
+\"new_size\":%d,\
+\"returned\":%d\
+},\n\
+"
+ , (long long)HDtime(NULL), (unsigned long)entry->addr,
+ (int)new_size, (int)fxn_ret_value);
+
+ /* Write the log message to the file */
+ if(H5C__json_write_log_message(json_udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__json_write_resize_entry_log_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__json_write_unpin_entry_log_msg
+ *
+ * Purpose: Write a log message for unpinning a cache entry.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__json_write_unpin_entry_log_msg(void *udata, const H5C_cache_entry_t *entry,
+ herr_t fxn_ret_value)
+{
+ H5C_log_json_udata_t *json_udata = (H5C_log_json_udata_t *)(udata);
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(json_udata);
+ HDassert(json_udata->message);
+ HDassert(entry);
+
+ /* Create the log message string */
+ HDsnprintf(json_udata->message, H5C_MAX_JSON_LOG_MSG_SIZE,
+"\
+{\
+\"timestamp\":%lld,\
+\"action\":\"unpin\",\
+\"address\":0x%lx,\
+\"returned\":%d\
+},\n\
+"
+ , (long long)HDtime(NULL), (unsigned long)entry->addr,
+ (int)fxn_ret_value);
+
+ /* Write the log message to the file */
+ if(H5C__json_write_log_message(json_udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__json_write_unpin_entry_log_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__json_write_destroy_fd_log_msg
+ *
+ * Purpose: Write a log message for destroying a flush dependency
+ * between two cache entries.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__json_write_destroy_fd_log_msg(void *udata, const H5C_cache_entry_t *parent,
+ const H5C_cache_entry_t *child, herr_t fxn_ret_value)
+{
+ H5C_log_json_udata_t *json_udata = (H5C_log_json_udata_t *)(udata);
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(json_udata);
+ HDassert(json_udata->message);
+ HDassert(parent);
+ HDassert(child);
+
+ /* Create the log message string */
+ HDsnprintf(json_udata->message, H5C_MAX_JSON_LOG_MSG_SIZE,
+"\
+{\
+\"timestamp\":%lld,\
+\"action\":\"destroy_fd\",\
+\"parent_addr\":0x%lx,\
+\"child_addr\":0x%lx,\
+\"returned\":%d\
+},\n\
+"
+ , (long long)HDtime(NULL), (unsigned long)parent->addr,
+ (unsigned long)child->addr, (int)fxn_ret_value);
+
+ /* Write the log message to the file */
+ if(H5C__json_write_log_message(json_udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__json_write_destroy_fd_log_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__json_write_unprotect_entry_log_msg
+ *
+ * Purpose: Write a log message for unprotecting a cache entry.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__json_write_unprotect_entry_log_msg(void *udata, haddr_t address,
+ int type_id, unsigned flags, herr_t fxn_ret_value)
+{
+ H5C_log_json_udata_t *json_udata = (H5C_log_json_udata_t *)(udata);
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(json_udata);
+ HDassert(json_udata->message);
+
+ /* Create the log message string */
+ HDsnprintf(json_udata->message, H5C_MAX_JSON_LOG_MSG_SIZE,
+"\
+{\
+\"timestamp\":%lld,\
+\"action\":\"unprotect\",\
+\"address\":0x%lx,\
+\"id\":%d,\
+\"flags\":%x,\
+\"returned\":%d\
+},\n\
+"
+ , (long long)HDtime(NULL), (unsigned long)address,
+ type_id, flags, (int)fxn_ret_value);
+
+ /* Write the log message to the file */
+ if(H5C__json_write_log_message(json_udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__json_write_unprotect_entry_log_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__json_write_set_cache_config_log_msg
+ *
+ * Purpose: Write a log message for setting the cache configuration.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__json_write_set_cache_config_log_msg(void *udata, const H5AC_cache_config_t *config,
+ herr_t fxn_ret_value)
+{
+ H5C_log_json_udata_t *json_udata = (H5C_log_json_udata_t *)(udata);
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(json_udata);
+ HDassert(json_udata->message);
+ HDassert(config);
+
+ /* Create the log message string */
+ HDsnprintf(json_udata->message, H5C_MAX_JSON_LOG_MSG_SIZE,
+"\
+{\
+\"timestamp\":%lld,\
+\"action\":\"set_config\",\
+\"returned\":%d\
+},\n\
+"
+ , (long long)HDtime(NULL), (int)fxn_ret_value);
+
+
+ /* Write the log message to the file */
+ if(H5C__json_write_log_message(json_udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__json_write_set_cache_config_log_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__json_write_remove_entry_log_msg
+ *
+ * Purpose: Write a log message for removing a cache entry.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__json_write_remove_entry_log_msg(void *udata, const H5C_cache_entry_t *entry,
+ herr_t fxn_ret_value)
+{
+ H5C_log_json_udata_t *json_udata = (H5C_log_json_udata_t *)(udata);
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(json_udata);
+ HDassert(json_udata->message);
+ HDassert(entry);
+
+ /* Create the log message string */
+ HDsnprintf(json_udata->message, H5C_MAX_JSON_LOG_MSG_SIZE,
+"\
+{\
+\"timestamp\":%lld,\
+\"action\":\"remove\",\
+\"address\":0x%lx,\
+\"returned\":%d\
+},\n\
+"
+ , (long long)HDtime(NULL), (unsigned long)entry->addr,
+ (int)fxn_ret_value);
+
+ /* Write the log message to the file */
+ if(H5C__json_write_log_message(json_udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__json_write_remove_entry_log_msg() */
+
diff --git a/src/H5Clog_trace.c b/src/H5Clog_trace.c
new file mode 100644
index 0000000..713f333
--- /dev/null
+++ b/src/H5Clog_trace.c
@@ -0,0 +1,1007 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5Clog_trace.c
+ *
+ * Purpose: Cache log implementation that emits trace entries intended
+ * for consumption by a future 'cache replay' feature.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+#include "H5Cmodule.h" /* This source code file is part of the H5C module */
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Cpkg.h" /* Cache */
+#include "H5Clog.h" /* Cache logging */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5MMprivate.h" /* Memory management */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+/* Max log message size */
+#define H5C_MAX_TRACE_LOG_MSG_SIZE 4096
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+typedef struct H5C_log_trace_udata_t {
+ FILE *outfile;
+ char *message;
+} H5C_log_trace_udata_t;
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+/* Internal message handling calls */
+static herr_t H5C__trace_write_log_message(H5C_log_trace_udata_t *trace_udata);
+
+/* Log message callbacks */
+static herr_t H5C__trace_tear_down_logging(H5C_log_info_t *log_info);
+static herr_t H5C__trace_write_expunge_entry_log_msg(void *udata, haddr_t address, int type_id, herr_t fxn_ret_value);
+static herr_t H5C__trace_write_flush_cache_log_msg(void *udata, herr_t fxn_ret_value);
+static herr_t H5C__trace_write_insert_entry_log_msg(void *udata, haddr_t address, int type_id, unsigned flags, size_t size, herr_t fxn_ret_value);
+static herr_t H5C__trace_write_mark_entry_dirty_log_msg(void *udata, const H5C_cache_entry_t *entry, herr_t fxn_ret_value);
+static herr_t H5C__trace_write_mark_entry_clean_log_msg(void *udata, const H5C_cache_entry_t *entry, herr_t fxn_ret_value);
+static herr_t H5C__trace_write_mark_unserialized_entry_log_msg(void *udata, const H5C_cache_entry_t *entry, herr_t fxn_ret_value);
+static herr_t H5C__trace_write_mark_serialized_entry_log_msg(void *udata, const H5C_cache_entry_t *entry, herr_t fxn_ret_value);
+static herr_t H5C__trace_write_move_entry_log_msg(void *udata, haddr_t old_addr, haddr_t new_addr, int type_id, herr_t fxn_ret_value);
+static herr_t H5C__trace_write_pin_entry_log_msg(void *udata, const H5C_cache_entry_t *entry, herr_t fxn_ret_value);
+static herr_t H5C__trace_write_create_fd_log_msg(void *udata, const H5C_cache_entry_t *parent, const H5C_cache_entry_t *child, herr_t fxn_ret_value);
+static herr_t H5C__trace_write_protect_entry_log_msg(void *udata, const H5C_cache_entry_t *entry, int type_id, unsigned flags, herr_t fxn_ret_value);
+static herr_t H5C__trace_write_resize_entry_log_msg(void *udata, const H5C_cache_entry_t *entry, size_t new_size, herr_t fxn_ret_value);
+static herr_t H5C__trace_write_unpin_entry_log_msg(void *udata, const H5C_cache_entry_t *entry, herr_t fxn_ret_value);
+static herr_t H5C__trace_write_destroy_fd_log_msg(void *udata, const H5C_cache_entry_t *parent, const H5C_cache_entry_t *child, herr_t fxn_ret_value);
+static herr_t H5C__trace_write_unprotect_entry_log_msg(void *udata, haddr_t address, int type_id, unsigned flags, herr_t fxn_ret_value);
+static herr_t H5C__trace_write_set_cache_config_log_msg(void *udata, const H5AC_cache_config_t *config, herr_t fxn_ret_value);
+static herr_t H5C__trace_write_remove_entry_log_msg(void *udata, const H5C_cache_entry_t *entry, herr_t fxn_ret_value);
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* Note that there's no cache set up call since that's the
+ * place where this struct is wired into the cache.
+ */
+static H5C_log_class_t H5C_trace_log_class_g = {
+ "trace",
+ H5C__trace_tear_down_logging,
+ NULL, /* start logging */
+ NULL, /* stop logging */
+ NULL, /* write start message */
+ NULL, /* write stop message */
+ NULL, /* write create cache message */
+ NULL, /* write destroy cache message */
+ NULL, /* write evict cache message */
+ H5C__trace_write_expunge_entry_log_msg,
+ H5C__trace_write_flush_cache_log_msg,
+ H5C__trace_write_insert_entry_log_msg,
+ H5C__trace_write_mark_entry_dirty_log_msg,
+ H5C__trace_write_mark_entry_clean_log_msg,
+ H5C__trace_write_mark_unserialized_entry_log_msg,
+ H5C__trace_write_mark_serialized_entry_log_msg,
+ H5C__trace_write_move_entry_log_msg,
+ H5C__trace_write_pin_entry_log_msg,
+ H5C__trace_write_create_fd_log_msg,
+ H5C__trace_write_protect_entry_log_msg,
+ H5C__trace_write_resize_entry_log_msg,
+ H5C__trace_write_unpin_entry_log_msg,
+ H5C__trace_write_destroy_fd_log_msg,
+ H5C__trace_write_unprotect_entry_log_msg,
+ H5C__trace_write_set_cache_config_log_msg,
+ H5C__trace_write_remove_entry_log_msg
+};
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__trace_write_log_message
+ *
+ * Purpose: Write a message to the log file and flush the file.
+ * The message string is neither modified nor freed.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__trace_write_log_message(H5C_log_trace_udata_t *trace_udata)
+{
+ size_t n_chars;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(trace_udata);
+ HDassert(trace_udata->outfile);
+ HDassert(trace_udata->message);
+
+ /* Write the log message and flush */
+ n_chars = HDstrlen(trace_udata->message);
+ if((int)n_chars != HDfprintf(trace_udata->outfile, trace_udata->message))
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "error writing log message")
+ HDmemset((void *)(trace_udata->message), 0, (size_t)(n_chars * sizeof(char)));
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__trace_write_log_message() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C_log_trace_set_up
+ *
+ * Purpose: Setup for metadata cache logging.
+ *
+ * Metadata logging is enabled and disabled at two levels. This
+ * function and the associated tear_down function open and close
+ * the log file. the start_ and stop_logging functions are then
+ * used to switch logging on/off. Optionally, logging can begin
+ * as soon as the log file is opened (set via the start_immediately
+ * parameter to this function).
+ *
+ * The log functionality is split between the H5C and H5AC
+ * packages. Log state and direct log manipulation resides in
+ * H5C. Log messages are generated in H5AC and sent to
+ * the H5C__trace_write_log_message function.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C_log_trace_set_up(H5C_log_info_t *log_info, const char log_location[], int mpi_rank)
+{
+ H5C_log_trace_udata_t *trace_udata = NULL;
+ char *file_name = NULL;
+ size_t n_chars;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(log_info);
+ HDassert(log_location);
+
+ /* Set up the class struct */
+ log_info->cls = &H5C_trace_log_class_g;
+
+ /* Allocate memory for the JSON-specific data */
+ if(NULL == (log_info->udata = H5MM_calloc(sizeof(H5C_log_trace_udata_t))))
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed")
+ trace_udata = (H5C_log_trace_udata_t *)(log_info->udata);
+
+ /* Allocate memory for the message buffer */
+ if(NULL == (trace_udata->message = (char *)H5MM_calloc(H5C_MAX_TRACE_LOG_MSG_SIZE * sizeof(char))))
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "memory allocation failed")
+
+ /* Possibly fix up the log file name.
+ * The extra 39 characters are for adding the rank to the file name
+ * under parallel HDF5. 39 characters allows > 2^127 processes which
+ * should be enough for anybody.
+ *
+ * allocation size = <path length> + dot + <rank # length> + \0
+ */
+ n_chars = HDstrlen(log_location) + 1 + 39 + 1;
+ if(NULL == (file_name = (char *)H5MM_calloc(n_chars * sizeof(char))))
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "can't allocate memory for mdc log file name manipulation")
+
+ /* Add the rank to the log file name when MPI is in use */
+ if(-1 == mpi_rank)
+ HDsnprintf(file_name, n_chars, "%s", log_location);
+ else
+ HDsnprintf(file_name, n_chars, "%s.%d", log_location, mpi_rank);
+
+ /* Open log file and set it to be unbuffered */
+ if(NULL == (trace_udata->outfile = HDfopen(file_name, "w")))
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "can't create mdc log file")
+ HDsetbuf(trace_udata->outfile, NULL);
+
+ /* Write the header */
+ HDfprintf(trace_udata->outfile, "### HDF5 metadata cache trace file version 1 ###\n");
+
+ done:
+ if(file_name)
+ H5MM_xfree(file_name);
+
+ /* Free and reset the log info struct on errors */
+ if(FAIL == ret_value) {
+ /* Free */
+ if(trace_udata && trace_udata->message)
+ H5MM_xfree(trace_udata->message);
+ if(trace_udata)
+ H5MM_xfree(trace_udata);
+
+ /* Reset */
+ log_info->udata = NULL;
+ log_info->cls = NULL;
+ }
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C_log_trace_set_up() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__trace_tear_down_logging
+ *
+ * Purpose: Tear-down for metadata cache logging.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__trace_tear_down_logging(H5C_log_info_t *log_info)
+{
+ H5C_log_trace_udata_t *trace_udata = NULL;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(log_info);
+
+ /* Alias */
+ trace_udata = (H5C_log_trace_udata_t *)(log_info->udata);
+
+ /* Free the message buffer */
+ H5MM_xfree(trace_udata->message);
+
+ /* Close log file */
+ if(EOF == HDfclose(trace_udata->outfile))
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "problem closing mdc log file")
+ trace_udata->outfile = NULL;
+
+ /* Fre the udata */
+ H5MM_xfree(trace_udata);
+
+ /* Reset the log class info and udata */
+ log_info->cls = NULL;
+ log_info->udata = NULL;
+
+ done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__trace_tear_down_logging() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__trace_write_expunge_entry_log_msg
+ *
+ * Purpose: Write a log message for expunge of cache entries.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__trace_write_expunge_entry_log_msg(void *udata, haddr_t address,
+ int type_id, herr_t fxn_ret_value)
+{
+ H5C_log_trace_udata_t *trace_udata = (H5C_log_trace_udata_t *)(udata);
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(trace_udata);
+ HDassert(trace_udata->message);
+
+ /* Create the log message string */
+ HDsnprintf(trace_udata->message, H5C_MAX_TRACE_LOG_MSG_SIZE, "H5AC_expunge_entry 0x%lx %d %d\n",
+ (unsigned long)address, type_id, (int)fxn_ret_value);
+
+ /* Write the log message to the file */
+ if(H5C__trace_write_log_message(trace_udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__trace_write_expunge_entry_log_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__trace_write_flush_cache_log_msg
+ *
+ * Purpose: Write a log message for cache flushes.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__trace_write_flush_cache_log_msg(void *udata, herr_t fxn_ret_value)
+{
+ H5C_log_trace_udata_t *trace_udata = (H5C_log_trace_udata_t *)(udata);
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(trace_udata);
+ HDassert(trace_udata->message);
+
+ /* Create the log message string */
+ HDsnprintf(trace_udata->message, H5C_MAX_TRACE_LOG_MSG_SIZE, "H5AC_flush %d\n",
+ (int)fxn_ret_value);
+
+ /* Write the log message to the file */
+ if(H5C__trace_write_log_message(trace_udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__trace_write_flush_cache_log_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__trace_write_insert_entry_log_msg
+ *
+ * Purpose: Write a log message for insertion of cache entries.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__trace_write_insert_entry_log_msg(void *udata, haddr_t address,
+ int type_id, unsigned flags, size_t size, herr_t fxn_ret_value)
+{
+ H5C_log_trace_udata_t *trace_udata = (H5C_log_trace_udata_t *)(udata);
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(trace_udata);
+ HDassert(trace_udata->message);
+
+ /* Create the log message string */
+ HDsnprintf(trace_udata->message, H5C_MAX_TRACE_LOG_MSG_SIZE, "H5AC_insert_entry 0x%lx %d 0x%x %d %d\n",
+ (unsigned long)address, type_id, flags, (int)size, (int)fxn_ret_value);
+
+ /* Write the log message to the file */
+ if(H5C__trace_write_log_message(trace_udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__trace_write_insert_entry_log_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__trace_write_mark_entry_dirty_log_msg
+ *
+ * Purpose: Write a log message for marking cache entries as dirty.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__trace_write_mark_entry_dirty_log_msg(void *udata, const H5C_cache_entry_t *entry,
+ herr_t fxn_ret_value)
+{
+ H5C_log_trace_udata_t *trace_udata = (H5C_log_trace_udata_t *)(udata);
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(trace_udata);
+ HDassert(trace_udata->message);
+ HDassert(entry);
+
+ /* Create the log message string */
+ HDsnprintf(trace_udata->message, H5C_MAX_TRACE_LOG_MSG_SIZE, "H5AC_mark_entry_dirty 0x%lx %d\n",
+ (unsigned long)(entry->addr), (int)fxn_ret_value);
+
+ /* Write the log message to the file */
+ if(H5C__trace_write_log_message(trace_udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__trace_write_mark_entry_dirty_log_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__trace_write_mark_entry_clean_log_msg
+ *
+ * Purpose: Write a log message for marking cache entries as clean.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__trace_write_mark_entry_clean_log_msg(void *udata, const H5C_cache_entry_t *entry,
+ herr_t fxn_ret_value)
+{
+ H5C_log_trace_udata_t *trace_udata = (H5C_log_trace_udata_t *)(udata);
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(trace_udata);
+ HDassert(trace_udata->message);
+ HDassert(entry);
+
+ /* Create the log message string */
+ HDsnprintf(trace_udata->message, H5C_MAX_TRACE_LOG_MSG_SIZE, "H5AC_mark_entry_clean 0x%lx %d\n",
+ (unsigned long)(entry->addr), (int)fxn_ret_value);
+
+ /* Write the log message to the file */
+ if(H5C__trace_write_log_message(trace_udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__trace_write_mark_entry_clean_log_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__trace_write_mark_unserialized_entry_log_msg
+ *
+ * Purpose: Write a log message for marking cache entries as unserialized.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__trace_write_mark_unserialized_entry_log_msg(void *udata,
+ const H5C_cache_entry_t *entry, herr_t fxn_ret_value)
+{
+ H5C_log_trace_udata_t *trace_udata = (H5C_log_trace_udata_t *)(udata);
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(trace_udata);
+ HDassert(trace_udata->message);
+ HDassert(entry);
+
+ /* Create the log message string */
+ HDsnprintf(trace_udata->message, H5C_MAX_TRACE_LOG_MSG_SIZE, "H5AC_mark_entry_unserialized 0x%lx %d\n",
+ (unsigned long)(entry->addr), (int)fxn_ret_value);
+
+ /* Write the log message to the file */
+ if(H5C__trace_write_log_message(trace_udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__trace_write_mark_unserialized_entry_log_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__trace_write_mark_serialized_entry_log_msg
+ *
+ * Purpose: Write a log message for marking cache entries as serialize.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__trace_write_mark_serialized_entry_log_msg(void *udata, const H5C_cache_entry_t *entry,
+ herr_t fxn_ret_value)
+{
+ H5C_log_trace_udata_t *trace_udata = (H5C_log_trace_udata_t *)(udata);
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(trace_udata);
+ HDassert(trace_udata->message);
+ HDassert(entry);
+
+ /* Create the log message string */
+ HDsnprintf(trace_udata->message, H5C_MAX_TRACE_LOG_MSG_SIZE, "H5AC_mark_entry_serialized 0x%lx %d\n",
+ (unsigned long)(entry->addr), (int)fxn_ret_value);
+
+ /* Write the log message to the file */
+ if(H5C__trace_write_log_message(trace_udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__trace_write_mark_serialized_entry_log_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__trace_write_move_entry_log_msg
+ *
+ * Purpose: Write a log message for moving a cache entry.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__trace_write_move_entry_log_msg(void *udata, haddr_t old_addr, haddr_t new_addr,
+ int type_id, herr_t fxn_ret_value)
+{
+ H5C_log_trace_udata_t *trace_udata = (H5C_log_trace_udata_t *)(udata);
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(trace_udata);
+ HDassert(trace_udata->message);
+
+ /* Create the log message string */
+ HDsnprintf(trace_udata->message, H5C_MAX_TRACE_LOG_MSG_SIZE, "H5AC_move_entry 0x%lx 0x%lx %d %d\n",
+ (unsigned long)old_addr, (unsigned long)new_addr, type_id, (int)fxn_ret_value);
+
+ /* Write the log message to the file */
+ if(H5C__trace_write_log_message(trace_udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__trace_write_move_entry_log_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__trace_write_pin_entry_log_msg
+ *
+ * Purpose: Write a log message for pinning a cache entry.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__trace_write_pin_entry_log_msg(void *udata, const H5C_cache_entry_t *entry,
+ herr_t fxn_ret_value)
+{
+ H5C_log_trace_udata_t *trace_udata = (H5C_log_trace_udata_t *)(udata);
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(trace_udata);
+ HDassert(trace_udata->message);
+ HDassert(entry);
+
+ /* Create the log message string */
+ HDsnprintf(trace_udata->message, H5C_MAX_TRACE_LOG_MSG_SIZE, "H5AC_pin_protected_entry 0x%lx %d\n",
+ (unsigned long)(entry->addr), (int)fxn_ret_value);
+
+ /* Write the log message to the file */
+ if(H5C__trace_write_log_message(trace_udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__trace_write_pin_entry_log_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__trace_write_create_fd_log_msg
+ *
+ * Purpose: Write a log message for creating a flush dependency between
+ * two cache entries.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__trace_write_create_fd_log_msg(void *udata, const H5C_cache_entry_t *parent,
+ const H5C_cache_entry_t *child, herr_t fxn_ret_value)
+{
+ H5C_log_trace_udata_t *trace_udata = (H5C_log_trace_udata_t *)(udata);
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(trace_udata);
+ HDassert(trace_udata->message);
+ HDassert(parent);
+ HDassert(child);
+
+ /* Create the log message string */
+ HDsnprintf(trace_udata->message, H5C_MAX_TRACE_LOG_MSG_SIZE, "H5AC_create_flush_dependency 0x%lx 0x%lx %d\n",
+ (unsigned long)(parent->addr), (unsigned long)(child->addr), (int)fxn_ret_value);
+
+ /* Write the log message to the file */
+ if(H5C__trace_write_log_message(trace_udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__trace_write_create_fd_log_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__trace_write_protect_entry_log_msg
+ *
+ * Purpose: Write a log message for protecting a cache entry.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__trace_write_protect_entry_log_msg(void *udata, const H5C_cache_entry_t *entry,
+ int type_id, unsigned flags, herr_t fxn_ret_value)
+{
+ H5C_log_trace_udata_t *trace_udata = (H5C_log_trace_udata_t *)(udata);
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(trace_udata);
+ HDassert(trace_udata->message);
+ HDassert(entry);
+
+ /* Create the log message string */
+ HDsnprintf(trace_udata->message, H5C_MAX_TRACE_LOG_MSG_SIZE, "H5AC_protect 0x%lx %d 0x%x %d %d\n",
+ (unsigned long)(entry->addr), type_id, flags, (int)(entry->size), (int)fxn_ret_value);
+
+ /* Write the log message to the file */
+ if(H5C__trace_write_log_message(trace_udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__trace_write_protect_entry_log_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__trace_write_resize_entry_log_msg
+ *
+ * Purpose: Write a log message for resizing a cache entry.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__trace_write_resize_entry_log_msg(void *udata, const H5C_cache_entry_t *entry,
+ size_t new_size, herr_t fxn_ret_value)
+{
+ H5C_log_trace_udata_t *trace_udata = (H5C_log_trace_udata_t *)(udata);
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(trace_udata);
+ HDassert(trace_udata->message);
+ HDassert(entry);
+
+ /* Create the log message string */
+ HDsnprintf(trace_udata->message, H5C_MAX_TRACE_LOG_MSG_SIZE, "H5AC_resize_entry 0x%lx %d %d\n",
+ (unsigned long)(entry->addr), (int)new_size, (int)fxn_ret_value);
+
+ /* Write the log message to the file */
+ if(H5C__trace_write_log_message(trace_udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__trace_write_resize_entry_log_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__trace_write_unpin_entry_log_msg
+ *
+ * Purpose: Write a log message for unpinning a cache entry.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__trace_write_unpin_entry_log_msg(void *udata, const H5C_cache_entry_t *entry,
+ herr_t fxn_ret_value)
+{
+ H5C_log_trace_udata_t *trace_udata = (H5C_log_trace_udata_t *)(udata);
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(trace_udata);
+ HDassert(trace_udata->message);
+ HDassert(entry);
+
+ /* Create the log message string */
+ HDsnprintf(trace_udata->message, H5C_MAX_TRACE_LOG_MSG_SIZE, "H5AC_unpin_entry 0x%lx %d\n",
+ (unsigned long)(entry->addr), (int)fxn_ret_value);
+
+ /* Write the log message to the file */
+ if(H5C__trace_write_log_message(trace_udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__trace_write_unpin_entry_log_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__trace_write_destroy_fd_log_msg
+ *
+ * Purpose: Write a log message for destroying a flush dependency
+ * between two cache entries.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__trace_write_destroy_fd_log_msg(void *udata, const H5C_cache_entry_t *parent,
+ const H5C_cache_entry_t *child, herr_t fxn_ret_value)
+{
+ H5C_log_trace_udata_t *trace_udata = (H5C_log_trace_udata_t *)(udata);
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(trace_udata);
+ HDassert(trace_udata->message);
+ HDassert(parent);
+ HDassert(child);
+
+ /* Create the log message string */
+ HDsnprintf(trace_udata->message, H5C_MAX_TRACE_LOG_MSG_SIZE, "H5AC_destroy_flush_dependency 0x%lx 0x%lx %d\n",
+ (unsigned long)(parent->addr), (unsigned long)(child->addr), (int)fxn_ret_value);
+
+ /* Write the log message to the file */
+ if(H5C__trace_write_log_message(trace_udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__trace_write_destroy_fd_log_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__trace_write_unprotect_entry_log_msg
+ *
+ * Purpose: Write a log message for unprotecting a cache entry.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__trace_write_unprotect_entry_log_msg(void *udata, haddr_t address,
+ int type_id, unsigned flags, herr_t fxn_ret_value)
+{
+ H5C_log_trace_udata_t *trace_udata = (H5C_log_trace_udata_t *)(udata);
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(trace_udata);
+ HDassert(trace_udata->message);
+
+ /* Create the log message string */
+ HDsnprintf(trace_udata->message, H5C_MAX_TRACE_LOG_MSG_SIZE, "H5AC_unprotect 0x%lx %d 0x%x %d\n",
+ (unsigned long)(address), type_id, flags, (int)fxn_ret_value);
+
+ /* Write the log message to the file */
+ if(H5C__trace_write_log_message(trace_udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__trace_write_unprotect_entry_log_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__trace_write_set_cache_config_log_msg
+ *
+ * Purpose: Write a log message for setting the cache configuration.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__trace_write_set_cache_config_log_msg(void *udata, const H5AC_cache_config_t *config,
+ herr_t fxn_ret_value)
+{
+ H5C_log_trace_udata_t *trace_udata = (H5C_log_trace_udata_t *)(udata);
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(trace_udata);
+ HDassert(trace_udata->message);
+ HDassert(config);
+
+ /* Create the log message string */
+ HDsnprintf(trace_udata->message, H5C_MAX_TRACE_LOG_MSG_SIZE,
+ "H5AC_set_cache_auto_resize_config %d %d %d %d \"%s\" %d %d %d %f %d %d %ld %d %f %f %d %f %f %d %d %d %f %f %d %d %d %d %f %zu %d %d\n",
+ config->version,
+ (int)(config->rpt_fcn_enabled),
+ (int)(config->open_trace_file),
+ (int)(config->close_trace_file),
+ config->trace_file_name,
+ (int)(config->evictions_enabled),
+ (int)(config->set_initial_size),
+ (int)(config->initial_size),
+ config->min_clean_fraction,
+ (int)(config->max_size),
+ (int)(config->min_size),
+ config->epoch_length,
+ (int)(config->incr_mode),
+ config->lower_hr_threshold,
+ config->increment,
+ (int)(config->flash_incr_mode),
+ config->flash_multiple,
+ config->flash_threshold,
+ (int)(config->apply_max_increment),
+ (int)(config->max_increment),
+ (int)(config->decr_mode),
+ config->upper_hr_threshold,
+ config->decrement,
+ (int)(config->apply_max_decrement),
+ (int)(config->max_decrement),
+ config->epochs_before_eviction,
+ (int)(config->apply_empty_reserve),
+ config->empty_reserve,
+ config->dirty_bytes_threshold,
+ config->metadata_write_strategy,
+ (int)fxn_ret_value);
+
+ /* Write the log message to the file */
+ if(H5C__trace_write_log_message(trace_udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__trace_write_set_cache_config_log_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5C__trace_write_remove_entry_log_msg
+ *
+ * Purpose: Write a log message for removing a cache entry.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Fall 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5C__trace_write_remove_entry_log_msg(void *udata, const H5C_cache_entry_t *entry,
+ herr_t fxn_ret_value)
+{
+ H5C_log_trace_udata_t *trace_udata = (H5C_log_trace_udata_t *)(udata);
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(trace_udata);
+ HDassert(trace_udata->message);
+ HDassert(entry);
+
+ /* Create the log message string */
+ HDsnprintf(trace_udata->message, H5C_MAX_TRACE_LOG_MSG_SIZE, "H5AC_remove_entry 0x%lx %d\n",
+ (unsigned long)(entry->addr), (int)fxn_ret_value);
+
+ /* Write the log message to the file */
+ if(H5C__trace_write_log_message(trace_udata) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_LOGGING, FAIL, "unable to emit log message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C__trace_write_remove_entry_log_msg() */
+
diff --git a/src/H5Cmpio.c b/src/H5Cmpio.c
index ecaed62..e784487 100644
--- a/src/H5Cmpio.c
+++ b/src/H5Cmpio.c
@@ -214,15 +214,15 @@ H5C_apply_candidate_list(H5F_t * f,
HDmemset(tbl_buf, 0, sizeof(tbl_buf));
- sprintf(&(tbl_buf[0]), "candidate list = ");
+ HDsprintf(&(tbl_buf[0]), "candidate list = ");
for(u = 0; u < num_candidates; u++)
- sprintf(&(tbl_buf[HDstrlen(tbl_buf)]), " 0x%llx", (long long)(*(candidates_list_ptr + u)));
- sprintf(&(tbl_buf[HDstrlen(tbl_buf)]), "\n");
+ HDsprintf(&(tbl_buf[HDstrlen(tbl_buf)]), " 0x%llx", (long long)(*(candidates_list_ptr + u)));
+ HDsprintf(&(tbl_buf[HDstrlen(tbl_buf)]), "\n");
HDfprintf(stdout, "%s", tbl_buf);
#endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */
- if(f->coll_md_write) {
+ if(f->shared->coll_md_write) {
/* Sanity check */
HDassert(NULL == cache_ptr->coll_write_list);
@@ -280,10 +280,10 @@ H5C_apply_candidate_list(H5F_t * f,
#if H5C_APPLY_CANDIDATE_LIST__DEBUG
for ( i = 0; i < 1024; i++ )
tbl_buf[i] = '\0';
- sprintf(&(tbl_buf[0]), "candidate assignment table = ");
+ HDsprintf(&(tbl_buf[0]), "candidate assignment table = ");
for(i = 0; i <= mpi_size; i++)
- sprintf(&(tbl_buf[HDstrlen(tbl_buf)]), " %d", candidate_assignment_table[i]);
- sprintf(&(tbl_buf[HDstrlen(tbl_buf)]), "\n");
+ HDsprintf(&(tbl_buf[HDstrlen(tbl_buf)]), " %d", candidate_assignment_table[i]);
+ HDsprintf(&(tbl_buf[HDstrlen(tbl_buf)]), "\n");
HDfprintf(stdout, "%s", tbl_buf);
HDfprintf(stdout, "%s:%d: flush entries [%u, %u].\n",
@@ -386,7 +386,7 @@ H5C_apply_candidate_list(H5F_t * f,
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "flush candidates failed")
/* If we've deferred writing to do it collectively, take care of that now */
- if(f->coll_md_write) {
+ if(f->shared->coll_md_write) {
/* Sanity check */
HDassert(cache_ptr->coll_write_list);
diff --git a/src/H5Cpkg.h b/src/H5Cpkg.h
index b82ba41..f0f7c02 100644
--- a/src/H5Cpkg.h
+++ b/src/H5Cpkg.h
@@ -37,6 +37,7 @@
#include "H5Cprivate.h"
/* Other private headers needed by this file */
+#include "H5Clog.h" /* Cache logging */
#include "H5SLprivate.h" /* Skip lists */
/**************************/
@@ -3563,40 +3564,8 @@ typedef struct H5C_tag_info_t {
* flush_in_progress: Boolean flag indicating whether a flush is in
* progress.
*
- * trace_file_ptr: File pointer pointing to the trace file, which is used
- * to record cache operations for use in simulations and design
- * studies. This field will usually be NULL, indicating that
- * no trace file should be recorded.
- *
- * Since much of the code supporting the parallel metadata
- * cache is in H5AC, we don't write the trace file from
- * H5C. Instead, H5AC reads the trace_file_ptr as needed.
- *
- * When we get to using H5C in other places, we may add
- * code to write trace file data at the H5C level as well.
- *
- * logging_enabled: Boolean flag indicating whether cache logging
- * which is used to record cache operations for use in
- * debugging and performance analysis. When this flag is set
- * to TRUE, it means that the log file is open and ready to
- * receive log entries. It does NOT mean that cache operations
- * are currently being recorded. That is controlled by the
- * currently_logging flag (below).
- *
- * Since much of the code supporting the parallel metadata
- * cache is in H5AC, we don't write the trace file from
- * H5C. Instead, H5AC reads the trace_file_ptr as needed.
- *
- * When we get to using H5C in other places, we may add
- * code to write trace file data at the H5C level as well.
- *
- * currently_logging: Boolean flag that indicates if cache operations are
- * currently being logged. This flag is flipped by the
- * H5Fstart/stop_mdc_logging functions.
- *
- * log_file_ptr: File pointer pointing to the log file. The I/O functions
- * in stdio.h are used to write to the log file regardless of
- * the VFD selected.
+ * log_info: Information used by the MDC logging functionality.
+ * Described in H5Clog.h.
*
* aux_ptr: Pointer to void used to allow wrapper code to associate
* its data with an instance of H5C_t. The H5C cache code
@@ -3950,6 +3919,13 @@ typedef struct H5C_tag_info_t {
*
* ignore_tags: Boolean flag to disable tag validation during entry insertion.
*
+ * num_objs_corked: Unsigned integer field containing the number of objects
+ * that are "corked". The "corked" status of an object is
+ * found by searching the "tag_list". This field is added
+ * for optimization so that the skip list search on "tag_list"
+ * can be skipped if this field is zero, i.e. no "corked"
+ * objects.
+ *
* When a cache entry is protected, it must be removed from the LRU
* list(s) as it cannot be either flushed or evicted until it is unprotected.
* The following fields are used to implement the protected list (pl).
@@ -4772,10 +4748,7 @@ typedef struct H5C_tag_info_t {
struct H5C_t {
uint32_t magic;
hbool_t flush_in_progress;
- FILE * trace_file_ptr;
- hbool_t logging_enabled;
- hbool_t currently_logging;
- FILE * log_file_ptr;
+ H5C_log_info_t *log_info;
void * aux_ptr;
int32_t max_type_id;
const H5C_class_t * const *class_table_ptr;
@@ -4828,6 +4801,7 @@ struct H5C_t {
/* Fields for maintaining list of tagged entries */
H5SL_t * tag_list;
hbool_t ignore_tags;
+ uint32_t num_objs_corked;
/* Fields for tracking protected entries */
uint32_t pl_len;
diff --git a/src/H5Cprivate.h b/src/H5Cprivate.h
index 9bc9197..474857a 100644
--- a/src/H5Cprivate.h
+++ b/src/H5Cprivate.h
@@ -2368,6 +2368,12 @@ typedef struct H5C_cache_image_ctl_t {
unsigned flags;
} H5C_cache_image_ctl_t;
+/* The cache logging output style */
+typedef enum H5C_log_style_t {
+ H5C_LOG_STYLE_JSON,
+ H5C_LOG_STYLE_TRACE
+} H5C_log_style_t;
+
/***************************************/
/* Library-private Function Prototypes */
/***************************************/
@@ -2376,13 +2382,6 @@ H5_DLL H5C_t *H5C_create(size_t max_cache_size, size_t min_clean_size,
int max_type_id, const H5C_class_t * const *class_table_ptr,
H5C_write_permitted_func_t check_write_permitted, hbool_t write_permitted,
H5C_log_flush_func_t log_flush, void *aux_ptr);
-H5_DLL herr_t H5C_set_up_logging(H5C_t *cache_ptr, const char log_location[], hbool_t start_immediately);
-H5_DLL herr_t H5C_tear_down_logging(H5C_t *cache_ptr);
-H5_DLL herr_t H5C_start_logging(H5C_t *cache_ptr);
-H5_DLL herr_t H5C_stop_logging(H5C_t *cache_ptr);
-H5_DLL herr_t H5C_get_logging_status(const H5C_t *cache_ptr, /*OUT*/ hbool_t *is_enabled,
- /*OUT*/ hbool_t *is_currently_logging);
-H5_DLL herr_t H5C_write_log_message(const H5C_t *cache_ptr, const char message[]);
H5_DLL void H5C_def_auto_resize_rpt_fcn(H5C_t *cache_ptr, int32_t version,
double hit_rate, enum H5C_resize_status status,
size_t old_max_cache_size, size_t new_max_cache_size,
@@ -2410,6 +2409,7 @@ H5_DLL herr_t H5C_get_cache_image_config(const H5C_t * cache_ptr,
H5_DLL herr_t H5C_get_cache_size(H5C_t *cache_ptr, size_t *max_size_ptr,
size_t *min_clean_size_ptr, size_t *cur_size_ptr,
uint32_t *cur_num_entries_ptr);
+H5_DLL herr_t H5C_get_cache_flush_in_progress(H5C_t *cache_ptr, hbool_t *flush_in_progress_ptr);
H5_DLL herr_t H5C_get_cache_hit_rate(H5C_t *cache_ptr, double *hit_rate_ptr);
H5_DLL herr_t H5C_get_entry_status(const H5F_t *f, haddr_t addr,
size_t *size_ptr, hbool_t *in_cache_ptr, hbool_t *is_dirty_ptr,
@@ -2419,8 +2419,6 @@ H5_DLL herr_t H5C_get_entry_status(const H5F_t *f, haddr_t addr,
H5_DLL herr_t H5C_get_evictions_enabled(const H5C_t *cache_ptr,
hbool_t *evictions_enabled_ptr);
H5_DLL void * H5C_get_aux_ptr(const H5C_t *cache_ptr);
-H5_DLL FILE *H5C_get_trace_file_ptr(const H5C_t *cache_ptr);
-H5_DLL FILE *H5C_get_trace_file_ptr_from_entry(const H5C_cache_entry_t *entry_ptr);
H5_DLL herr_t H5C_image_stats(H5C_t * cache_ptr, hbool_t print_header);
H5_DLL herr_t H5C_insert_entry(H5F_t *f, const H5C_class_t *type, haddr_t addr,
void *thing, unsigned int flags);
@@ -2448,7 +2446,6 @@ H5_DLL herr_t H5C_set_evictions_enabled(H5C_t *cache_ptr,
H5_DLL herr_t H5C_set_vfd_swmr_reader(H5C_t *cache_ptr,
hbool_t vfd_swmr_reader, hsize_t page_size);
H5_DLL herr_t H5C_set_prefix(H5C_t *cache_ptr, char *prefix);
-H5_DLL herr_t H5C_set_trace_file_ptr(H5C_t *cache_ptr, FILE *trace_file_ptr);
H5_DLL herr_t H5C_stats(H5C_t *cache_ptr, const char *cache_name,
hbool_t display_detailed_stats);
H5_DLL void H5C_stats__reset(H5C_t *cache_ptr);
@@ -2462,11 +2459,11 @@ H5_DLL herr_t H5C_validate_resize_config(H5C_auto_size_ctl_t *config_ptr,
unsigned int tests);
H5_DLL herr_t H5C_ignore_tags(H5C_t *cache_ptr);
H5_DLL hbool_t H5C_get_ignore_tags(const H5C_t *cache_ptr);
-H5_DLL herr_t H5C_retag_entries(H5C_t * cache_ptr, haddr_t src_tag,
- haddr_t dest_tag);
-H5_DLL herr_t H5C_cork(H5C_t *cache_ptr, haddr_t obj_addr, unsigned action,
+H5_DLL uint32_t H5C_get_num_objs_corked(const H5C_t *cache_ptr);
+H5_DLL herr_t H5C_retag_entries(H5C_t * cache_ptr, haddr_t src_tag, haddr_t dest_tag);
+H5_DLL herr_t H5C_cork(H5C_t *cache_ptr, haddr_t obj_addr, unsigned action,
hbool_t *corked);
-H5_DLL herr_t H5C_get_entry_ring(const H5F_t *f, haddr_t addr,
+H5_DLL herr_t H5C_get_entry_ring(const H5F_t *f, haddr_t addr,
H5C_ring_t *ring);
H5_DLL herr_t H5C_unsettle_entry_ring(void *thing);
H5_DLL herr_t H5C_unsettle_ring(H5F_t * f, H5C_ring_t ring);
@@ -2477,6 +2474,11 @@ H5_DLL hbool_t H5C_cache_image_pending(const H5C_t *cache_ptr);
H5_DLL herr_t H5C_get_mdc_image_info(H5C_t *cache_ptr, haddr_t *image_addr,
hsize_t *image_len);
+/* Logging functions */
+H5_DLL herr_t H5C_start_logging(H5C_t *cache);
+H5_DLL herr_t H5C_stop_logging(H5C_t *cache);
+H5_DLL herr_t H5C_get_logging_status(const H5C_t *cache, /*OUT*/ hbool_t *is_enabled, /*OUT*/ hbool_t *is_currently_logging);
+
#ifdef H5_HAVE_PARALLEL
H5_DLL herr_t H5C_apply_candidate_list(H5F_t *f, H5C_t *cache_ptr,
unsigned num_candidates, haddr_t *candidates_list_ptr, int mpi_rank,
diff --git a/src/H5Cquery.c b/src/H5Cquery.c
index 6c927b0..a1267c5 100644
--- a/src/H5Cquery.c
+++ b/src/H5Cquery.c
@@ -156,6 +156,34 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5C_get_cache_flush_in_progress
+ *
+ * Purpose: Return flush_in_progress in *flush_in_progress_ptr
+ * If the parameter is NULL, skip that value.
+ *
+ * Return: SUCCEED on success, and FAIL on failure.
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C_get_cache_flush_in_progress(H5C_t * cache_ptr, hbool_t *flush_in_progress_ptr)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ if((cache_ptr == NULL) || (cache_ptr->magic != H5C__H5C_T_MAGIC))
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Bad cache_ptr on entry.")
+
+ if(flush_in_progress_ptr != NULL)
+ *flush_in_progress_ptr = cache_ptr->flush_in_progress;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5C_get_cache_flush_in_progress() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5C_get_cache_hit_rate
*
* Purpose: Compute and return the current cache hit rate in
@@ -351,64 +379,6 @@ H5C_get_aux_ptr(const H5C_t *cache_ptr)
/*-------------------------------------------------------------------------
- * Function: H5C_get_trace_file_ptr
- *
- * Purpose: Get the trace_file_ptr field from the cache.
- *
- * This field will either be NULL (which indicates that trace
- * file logging is turned off), or contain a pointer to the
- * open file to which trace file data is to be written.
- *
- * Return: Non-NULL trace file pointer (can't fail)
- *
- * Programmer: John Mainzer
- * 1/20/06
- *
- *-------------------------------------------------------------------------
- */
-FILE *
-H5C_get_trace_file_ptr(const H5C_t *cache_ptr)
-{
- FUNC_ENTER_NOAPI_NOERR
-
- /* Check arguments */
- HDassert(cache_ptr);
- HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
-
- FUNC_LEAVE_NOAPI(cache_ptr->trace_file_ptr)
-} /* H5C_get_trace_file_ptr() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5C_get_trace_file_ptr_from_entry
- *
- * Purpose: Get the trace_file_ptr field from the cache, via an entry.
- *
- * This field will either be NULL (which indicates that trace
- * file logging is turned off), or contain a pointer to the
- * open file to which trace file data is to be written.
- *
- * Return: Non-NULL trace file pointer (can't fail)
- *
- * Programmer: Quincey Koziol
- * 6/9/08
- *
- *-------------------------------------------------------------------------
- */
-FILE *
-H5C_get_trace_file_ptr_from_entry(const H5C_cache_entry_t *entry_ptr)
-{
- FUNC_ENTER_NOAPI_NOERR
-
- /* Sanity checks */
- HDassert(entry_ptr);
- HDassert(entry_ptr->cache_ptr);
-
- FUNC_LEAVE_NOAPI(H5C_get_trace_file_ptr(entry_ptr->cache_ptr))
-} /* H5C_get_trace_file_ptr_from_entry() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5C_get_entry_ring
*
* Purpose: Given a file address, retrieve the ring for an entry at that
@@ -472,11 +442,11 @@ H5C_get_mdc_image_info(H5C_t * cache_ptr, haddr_t *image_addr, hsize_t *image_le
if((cache_ptr == NULL) || (cache_ptr->magic != H5C__H5C_T_MAGIC))
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "bad cache_ptr on entry")
- if(image_addr == NULL || image_len == NULL)
- HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "bad image_addr or image_len on entry")
- *image_addr = cache_ptr->image_addr;
- *image_len = cache_ptr->image_len;
+ if(image_addr)
+ *image_addr = cache_ptr->image_addr;
+ if(image_len)
+ *image_len = cache_ptr->image_len;
done:
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5Ctag.c b/src/H5Ctag.c
index e4235a8..5f4f0b6 100644
--- a/src/H5Ctag.c
+++ b/src/H5Ctag.c
@@ -176,6 +176,32 @@ H5C_get_ignore_tags(const H5C_t *cache_ptr)
/*-------------------------------------------------------------------------
*
+ * Function: H5C_get_num_objs_corked
+ *
+ * Purpose: Retrieve the 'num_objs_corked' field for the cache
+ *
+ * Return: 'num_objs_corked' value (can't fail)
+ *
+ * Programmer: Vailin Choi; Feb 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+uint32_t
+H5C_get_num_objs_corked(const H5C_t *cache_ptr)
+{
+ FUNC_ENTER_NOAPI_NOERR
+
+ /* Sanity checks */
+ HDassert(cache_ptr);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+
+ /* Return value for num_objs_corked */
+ FUNC_LEAVE_NOAPI(cache_ptr->num_objs_corked)
+} /* H5C_get_num_objs_corked */
+
+
+/*-------------------------------------------------------------------------
+ *
* Function: H5C__tag_entry
*
* Purpose: Tags an entry with the provided tag (contained in the API context).
diff --git a/src/H5Ctest.c b/src/H5Ctest.c
index 9da6350..340071a 100644
--- a/src/H5Ctest.c
+++ b/src/H5Ctest.c
@@ -40,6 +40,7 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5Fpkg.h" /* Files */
#include "H5Iprivate.h" /* IDs */
+#include "H5VLprivate.h" /* Virtual Object Layer */
/****************/
@@ -142,7 +143,7 @@ H5C__verify_cork_tag_test(hid_t fid, haddr_t tag, hbool_t status)
FUNC_ENTER_PACKAGE
/* Get file pointer */
- if(NULL == (f = (H5F_t *)H5I_object_verify(fid, H5I_FILE)))
+ if(NULL == (f = (H5F_t *)H5VL_object_verify(fid, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file")
/* Get cache pointer */
diff --git a/src/H5D.c b/src/H5D.c
index af99a1f..9d811c6 100644
--- a/src/H5D.c
+++ b/src/H5D.c
@@ -27,6 +27,9 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5FLprivate.h" /* Free lists */
#include "H5Iprivate.h" /* IDs */
+#include "H5VLprivate.h" /* Virtual Object Layer */
+
+#include "H5VLnative_private.h" /* Native VOL connector */
/****************/
@@ -102,26 +105,20 @@ hid_t
H5Dcreate2(hid_t loc_id, const char *name, hid_t type_id, hid_t space_id,
hid_t lcpl_id, hid_t dcpl_id, hid_t dapl_id)
{
- H5D_t *dset = NULL; /* New dataset's info */
- H5G_loc_t loc; /* Object location to insert dataset into */
- const H5S_t *space; /* Dataspace for dataset */
- hid_t ret_value = H5I_INVALID_HID; /* Return value */
+ void *dset = NULL; /* New dataset's info */
+ H5VL_object_t *vol_obj = NULL; /* object token of loc_id */
+ H5VL_loc_params_t loc_params;
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
FUNC_ENTER_API(H5I_INVALID_HID)
H5TRACE7("i", "i*siiiii", loc_id, name, type_id, space_id, lcpl_id, dcpl_id,
dapl_id);
/* Check arguments */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a location ID")
if(!name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "name parameter cannot be NULL")
if(!*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "name parameter cannot be an empty string")
- if(H5I_DATATYPE != H5I_get_type(type_id))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a datatype ID")
- if(NULL == (space = (const H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a dataspace ID")
/* Get link creation property list */
if(H5P_DEFAULT == lcpl_id)
@@ -137,21 +134,32 @@ H5Dcreate2(hid_t loc_id, const char *name, hid_t type_id, hid_t space_id,
if(TRUE != H5P_isa_class(dcpl_id, H5P_DATASET_CREATE))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "dcpl_id is not a dataset create property list ID")
+ /* Set the DCPL for the API context */
+ H5CX_set_dcpl(dcpl_id);
+
/* Verify access property list and set up collective metadata if appropriate */
if(H5CX_set_apl(&dapl_id, H5P_CLS_DACC, loc_id, TRUE) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info")
+ /* Get the location object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier")
+
+ /* Set location parameters */
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
/* Create the dataset */
- if(NULL == (dset = H5D__create_named(&loc, name, type_id, space, lcpl_id, dcpl_id, dapl_id)))
+ if(NULL == (dset = H5VL_dataset_create(vol_obj, &loc_params, name, lcpl_id, type_id, space_id, dcpl_id, dapl_id, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, H5I_INVALID_HID, "unable to create dataset")
/* Get an atom for the dataset */
- if((ret_value = H5I_register(H5I_DATASET, dset, TRUE)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to atomize dataset handle")
+ if((ret_value = H5VL_register(H5I_DATASET, dset, vol_obj->connector, TRUE)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to atomize dataset handle")
done:
if(H5I_INVALID_HID == ret_value)
- if(dset && H5D_close(dset) < 0)
+ if(dset && H5VL_dataset_close(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, H5I_INVALID_HID, "unable to release dataset")
FUNC_LEAVE_API(ret_value)
@@ -194,56 +202,48 @@ hid_t
H5Dcreate_anon(hid_t loc_id, hid_t type_id, hid_t space_id, hid_t dcpl_id,
hid_t dapl_id)
{
- H5G_loc_t loc; /* Object location to insert dataset into */
- H5D_t *dset = NULL; /* New dataset's info */
- const H5S_t *space; /* Dataspace for dataset */
+ void *dset = NULL; /* dset token from VOL connector */
+ H5VL_object_t *vol_obj = NULL; /* object token of loc_id */
+ H5VL_loc_params_t loc_params;
hid_t ret_value = H5I_INVALID_HID; /* Return value */
FUNC_ENTER_API(H5I_INVALID_HID)
H5TRACE5("i", "iiiii", loc_id, type_id, space_id, dcpl_id, dapl_id);
/* Check arguments */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a location ID")
- if(H5I_DATATYPE != H5I_get_type(type_id))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a datatype ID")
- if(NULL == (space = (const H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a dataspace ID")
if(H5P_DEFAULT == dcpl_id)
dcpl_id = H5P_DATASET_CREATE_DEFAULT;
else
if(TRUE != H5P_isa_class(dcpl_id, H5P_DATASET_CREATE))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not dataset create property list ID")
+ /* Set the DCPL for the API context */
+ H5CX_set_dcpl(dcpl_id);
+
/* Verify access property list and set up collective metadata if appropriate */
if(H5CX_set_apl(&dapl_id, H5P_CLS_DACC, loc_id, TRUE) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info")
+ /* get the location object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier")
+
+ /* Set location parameters */
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
/* Create the dataset */
- if(NULL == (dset = H5D__create(loc.oloc->file, type_id, space, dcpl_id, dapl_id)))
+ if(NULL == (dset = H5VL_dataset_create(vol_obj, &loc_params, NULL, H5P_LINK_CREATE_DEFAULT, type_id, space_id, dcpl_id, dapl_id, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, H5I_INVALID_HID, "unable to create dataset")
/* Get an atom for the dataset */
- if((ret_value = H5I_register(H5I_DATASET, dset, TRUE)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register dataset")
+ if((ret_value = H5VL_register(H5I_DATASET, dset, vol_obj->connector, TRUE)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register dataset")
done:
- /* Release the dataset's object header, if it was created */
- if(dset) {
- H5O_loc_t *oloc; /* Object location for dataset */
-
- /* Get the new dataset's object location */
- if(NULL == (oloc = H5D_oloc(dset)))
- HDONE_ERROR(H5E_DATASET, H5E_CANTGET, H5I_INVALID_HID, "unable to get object location of dataset")
-
- /* Decrement refcount on dataset's object header in memory */
- if(H5O_dec_rc_by_loc(oloc) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTDEC, H5I_INVALID_HID, "unable to decrement refcount on newly created object")
- } /* end if */
-
/* Cleanup on failure */
if(H5I_INVALID_HID == ret_value)
- if(dset && H5D_close(dset) < 0)
+ if(dset && H5VL_dataset_close(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, H5I_INVALID_HID, "unable to release dataset")
FUNC_LEAVE_API(ret_value)
@@ -268,16 +268,15 @@ done:
hid_t
H5Dopen2(hid_t loc_id, const char *name, hid_t dapl_id)
{
- H5D_t *dset = NULL;
- H5G_loc_t loc; /* Object location of group */
+ void *dset = NULL; /* dset token from VOL connector */
+ H5VL_object_t *vol_obj = NULL; /* object token of loc_id */
+ H5VL_loc_params_t loc_params;
hid_t ret_value = H5I_INVALID_HID; /* Return value */
FUNC_ENTER_API(H5I_INVALID_HID)
H5TRACE3("i", "i*si", loc_id, name, dapl_id);
/* Check args */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "name parameter cannot be NULL")
if(!*name)
@@ -287,18 +286,27 @@ H5Dopen2(hid_t loc_id, const char *name, hid_t dapl_id)
if(H5CX_set_apl(&dapl_id, H5P_CLS_DACC, loc_id, FALSE) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info")
+ /* get the location object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier")
+
+ /* Set the location parameters */
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
/* Open the dataset */
- if(NULL == (dset = H5D__open_name(&loc, name, dapl_id)))
+ if(NULL == (dset = H5VL_dataset_open(vol_obj, &loc_params, name, dapl_id, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open dataset")
/* Register an atom for the dataset */
- if((ret_value = H5I_register(H5I_DATASET, dset, TRUE)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "can't register dataset atom")
+ if((ret_value = H5VL_register(H5I_DATASET, dset, vol_obj->connector, TRUE)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, H5I_INVALID_HID, "can't register dataset atom")
done:
if(H5I_INVALID_HID == ret_value)
- if(dset && H5D_close(dset) < 0)
+ if(dset && H5VL_dataset_close(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, H5I_INVALID_HID, "unable to release dataset")
+
FUNC_LEAVE_API(ret_value)
} /* end H5Dopen2() */
@@ -323,7 +331,7 @@ H5Dclose(hid_t dset_id)
H5TRACE1("e", "i", dset_id);
/* Check args */
- if(NULL == H5I_object_verify(dset_id, H5I_DATASET))
+ if(H5I_DATASET != H5I_get_type(dset_id))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset ID")
/* Decrement the counter on the dataset. It will be freed if the count
@@ -353,18 +361,18 @@ done:
hid_t
H5Dget_space(hid_t dset_id)
{
- H5D_t *dset = NULL; /* Dataset structure */
+ H5VL_object_t *vol_obj = NULL; /* Dataset structure */
hid_t ret_value = H5I_INVALID_HID; /* Return value */
FUNC_ENTER_API(H5I_INVALID_HID)
H5TRACE1("i", "i", dset_id);
/* Check args */
- if(NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(dset_id, H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid dataset identifier")
/* Get the dataspace */
- if((ret_value = H5D__get_space(dset)) < 0)
+ if(H5VL_dataset_get(vol_obj, H5VL_DATASET_GET_SPACE, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &ret_value) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, H5I_INVALID_HID, "unable to get dataspace")
done:
@@ -384,18 +392,18 @@ done:
herr_t
H5Dget_space_status(hid_t dset_id, H5D_space_status_t *allocation)
{
- H5D_t *dset = NULL; /* Dataset structure */
+ H5VL_object_t *vol_obj = NULL; /* Dataset structure */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE2("e", "i*Ds", dset_id, allocation);
/* Check args */
- if(NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(dset_id, H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid dataset identifier")
/* Get dataspace status */
- if(H5D__get_space_status(dset, allocation) < 0)
+ if((ret_value = H5VL_dataset_get(vol_obj, H5VL_DATASET_GET_SPACE_STATUS, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, allocation)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to get space status")
done:
@@ -419,18 +427,18 @@ done:
hid_t
H5Dget_type(hid_t dset_id)
{
- H5D_t *dset; /* Dataset structure */
+ H5VL_object_t *vol_obj; /* Dataset structure */
hid_t ret_value = H5I_INVALID_HID; /* Return value */
FUNC_ENTER_API(H5I_INVALID_HID)
H5TRACE1("i", "i", dset_id);
/* Check args */
- if(NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(dset_id, H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid dataset identifier")
- /* get the datatype */
- if((ret_value = H5D__get_type(dset)) < 0)
+ /* Get the datatype */
+ if(H5VL_dataset_get(vol_obj, H5VL_DATASET_GET_TYPE, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &ret_value) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, H5I_INVALID_HID, "unable to get datatype")
done:
@@ -449,26 +457,26 @@ done:
*
* Failure: H5I_INVALID_HID
*
- * Programmer: Robb Matzke
- * Tuesday, February 3, 1998
+ * Programmer: Robb Matzke
+ * Tuesday, February 3, 1998
*
*-------------------------------------------------------------------------
*/
hid_t
H5Dget_create_plist(hid_t dset_id)
{
- H5D_t *dataset; /* Dataset structure */
+ H5VL_object_t *vol_obj; /* Dataset structure */
hid_t ret_value = H5I_INVALID_HID; /* Return value */
FUNC_ENTER_API(H5I_INVALID_HID)
H5TRACE1("i", "i", dset_id);
/* Check args */
- if(NULL == (dataset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(dset_id, H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid dataset identifier")
/* Get the dataset creation property list */
- if((ret_value = H5D_get_create_plist(dataset)) < 0)
+ if(H5VL_dataset_get(vol_obj, H5VL_DATASET_GET_DCPL, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &ret_value) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, H5I_INVALID_HID, "unable to get dataset creation properties")
done:
@@ -504,26 +512,26 @@ done:
*
* Failure: H5I_INVALID_HID
*
- * Programmer: Neil Fortner
- * Wednesday, October 29, 2008
+ * Programmer: Neil Fortner
+ * Wednesday, October 29, 2008
*
*-------------------------------------------------------------------------
*/
hid_t
H5Dget_access_plist(hid_t dset_id)
{
- H5D_t *dset; /* Dataset structure */
+ H5VL_object_t *vol_obj; /* Dataset structure */
hid_t ret_value = H5I_INVALID_HID; /* Return value */
FUNC_ENTER_API(H5I_INVALID_HID)
H5TRACE1("i", "i", dset_id);
/* Check args */
- if(NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(dset_id, H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid dataset identifier")
/* Get the dataset access property list */
- if((ret_value = H5D_get_access_plist(dset)) < 0)
+ if(H5VL_dataset_get(vol_obj, H5VL_DATASET_GET_DAPL, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &ret_value) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, H5I_INVALID_HID, "unable to get dataset access properties")
done:
@@ -549,18 +557,18 @@ done:
hsize_t
H5Dget_storage_size(hid_t dset_id)
{
- H5D_t *dset; /* Dataset for this operation */
+ H5VL_object_t *vol_obj; /* Dataset for this operation */
hsize_t ret_value = 0; /* Return value */
FUNC_ENTER_API(0)
H5TRACE1("h", "i", dset_id);
/* Check args */
- if(NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(dset_id, H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "invalid dataset identifier")
/* Get the storage size */
- if(H5D__get_storage_size(dset, &ret_value) < 0)
+ if(H5VL_dataset_get(vol_obj, H5VL_DATASET_GET_STORAGE_SIZE, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &ret_value) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, 0, "unable to get storage size")
done:
@@ -582,18 +590,19 @@ done:
haddr_t
H5Dget_offset(hid_t dset_id)
{
- H5D_t *dset; /* Dataset for this operation */
+ H5VL_object_t *vol_obj; /* Dataset for this operation */
haddr_t ret_value = HADDR_UNDEF; /* Return value */
FUNC_ENTER_API(HADDR_UNDEF)
H5TRACE1("a", "i", dset_id);
/* Check args */
- if(NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(dset_id, H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, HADDR_UNDEF, "invalid dataset identifier")
/* Get the offset */
- ret_value = H5D__get_offset(dset);
+ if(H5VL_dataset_get(vol_obj, H5VL_DATASET_GET_OFFSET, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &ret_value) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, HADDR_UNDEF, "unable to get offset")
done:
FUNC_LEAVE_API(ret_value)
@@ -601,9 +610,9 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5Diterate
+ * Function: H5Diterate
*
- * Purpose: This routine iterates over all the elements selected in a memory
+ * Purpose: This routine iterates over all the elements selected in a memory
* buffer. The callback function is called once for each element selected
* in the dataspace. The selection in the dataspace is modified so
* that any elements already iterated over are removed from the selection
@@ -650,11 +659,11 @@ done:
* indicating failure. The iterator can be restarted at the next
* element.
*
- * Return: Returns the return value of the last operator if it was non-zero,
+ * Return: Returns the return value of the last operator if it was non-zero,
* or zero if all elements were processed. Otherwise returns a
* negative value.
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* Friday, June 11, 1999
*
*-------------------------------------------------------------------------
@@ -697,59 +706,9 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5Dvlen_reclaim
+ * Function: H5Dvlen_get_buf_size
*
- * Purpose: Frees the buffers allocated for storing variable-length data
- * in memory. Only frees the VL data in the selection defined in the
- * dataspace. The dataset transfer property list is required to find the
- * correct allocation/free methods for the VL data in the buffer.
- *
- * Return: Non-negative on success, negative on failure
- *
- * Programmer: Quincey Koziol
- * Thursday, June 10, 1999
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5Dvlen_reclaim(hid_t type_id, hid_t space_id, hid_t dxpl_id, void *buf)
-{
- H5S_t *space; /* Dataspace for iteration */
- herr_t ret_value; /* Return value */
-
- FUNC_ENTER_API(FAIL)
- H5TRACE4("e", "iii*x", type_id, space_id, dxpl_id, buf);
-
- /* Check args */
- if(H5I_DATATYPE != H5I_get_type(type_id) || buf == NULL)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid argument")
- if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid dataspace")
- if(!(H5S_has_extent(space)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dataspace does not have extent set")
-
- /* Get the default dataset transfer property list if the user didn't provide one */
- if(H5P_DEFAULT == dxpl_id)
- dxpl_id = H5P_DATASET_XFER_DEFAULT;
- else
- if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms")
-
- /* Set DXPL for operation */
- H5CX_set_dxpl(dxpl_id);
-
- /* Call internal routine */
- ret_value = H5D_vlen_reclaim(type_id, space, buf);
-
-done:
- FUNC_LEAVE_API(ret_value)
-} /* end H5Dvlen_reclaim() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5Dvlen_get_buf_size
- *
- * Purpose: This routine checks the number of bytes required to store the VL
+ * Purpose: This routine checks the number of bytes required to store the VL
* data from the dataset, using the space_id for the selection in the
* dataset on disk and the type_id for the memory representation of the
* VL data, in memory. The *size value is modified according to how many
@@ -763,9 +722,9 @@ done:
* Kinda kludgy, but easier than the other method of trying to figure out
* the sizes without actually reading the data in... - QAK
*
- * Return: Non-negative on success, negative on failure
+ * Return: Non-negative on success, negative on failure
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* Wednesday, August 11, 1999
*
*-------------------------------------------------------------------------
@@ -775,8 +734,7 @@ H5Dvlen_get_buf_size(hid_t dataset_id, hid_t type_id, hid_t space_id,
hsize_t *size)
{
H5D_vlen_bufsize_t vlen_bufsize = {0, 0, 0, 0, 0, 0};
- H5D_t *dset; /* Dataset for this operation */
- H5S_t *fspace = NULL; /* Dataset's dataspace */
+ H5VL_object_t *vol_obj; /* Dataset for this operation */
H5S_t *mspace = NULL; /* Memory dataspace */
char bogus; /* bogus value to pass to H5Diterate() */
H5S_t *space; /* Dataspace for iteration */
@@ -791,7 +749,7 @@ H5Dvlen_get_buf_size(hid_t dataset_id, hid_t type_id, hid_t space_id,
if(H5I_DATASET != H5I_get_type(dataset_id) ||
H5I_DATATYPE != H5I_get_type(type_id) || size == NULL)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid argument")
- if(NULL == (dset = (H5D_t *)H5I_object(dataset_id)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(dataset_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid dataset identifier")
if(NULL == (type = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an valid base datatype")
@@ -801,21 +759,19 @@ H5Dvlen_get_buf_size(hid_t dataset_id, hid_t type_id, hid_t space_id,
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dataspace does not have extent set")
/* Save the dataset */
- vlen_bufsize.dset = dset;
+ vlen_bufsize.dset_vol_obj = vol_obj;
vlen_bufsize.fspace_id = H5I_INVALID_HID;
vlen_bufsize.mspace_id = H5I_INVALID_HID;
/* Get a copy of the dataset's dataspace */
- if(NULL == (fspace = H5S_copy(dset->shared->space, FALSE, TRUE)))
+ if(H5VL_dataset_get(vol_obj, H5VL_DATASET_GET_SPACE, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &vlen_bufsize.fspace_id) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "can't copy dataspace")
- if((vlen_bufsize.fspace_id = H5I_register(H5I_DATASPACE, fspace, TRUE)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register file dataspace")
/* Create a scalar for the memory dataspace */
if(NULL == (mspace = H5S_create(H5S_SCALAR)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't create dataspace")
if((vlen_bufsize.mspace_id = H5I_register(H5I_DATASPACE, mspace, TRUE)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register memory dataspace")
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace atom")
/* Grab the temporary buffers required */
if(NULL == (vlen_bufsize.fl_tbuf = H5FL_BLK_MALLOC(vlen_fl_buf, (size_t)1)))
@@ -842,17 +798,14 @@ H5Dvlen_get_buf_size(hid_t dataset_id, hid_t type_id, hid_t space_id,
*size = vlen_bufsize.size;
done:
- if(ret_value < 0) {
- if(fspace && H5S_close(fspace) < 0)
- HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release file dataspace")
+ if(ret_value < 0)
if(mspace && H5S_close(mspace) < 0)
- HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release memory dataspace")
- }
+ HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace")
if(vlen_bufsize.fspace_id && H5I_dec_app_ref(vlen_bufsize.fspace_id) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDEC, FAIL, "problem freeing file dataspace id")
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDEC, FAIL, "problem freeing id")
if(vlen_bufsize.mspace_id && H5I_dec_app_ref(vlen_bufsize.mspace_id) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDEC, FAIL, "problem freeing memory dataspace id")
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDEC, FAIL, "problem freeing id")
if(vlen_bufsize.fl_tbuf != NULL)
vlen_bufsize.fl_tbuf = H5FL_BLK_FREE(vlen_fl_buf, vlen_bufsize.fl_tbuf);
if(vlen_bufsize.vl_tbuf != NULL)
@@ -875,14 +828,14 @@ done:
herr_t
H5Dset_extent(hid_t dset_id, const hsize_t size[])
{
- H5D_t *dset; /* Dataset for this operation */
+ H5VL_object_t *vol_obj; /* Dataset for this operation */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE2("e", "i*h", dset_id, size);
/* Check args */
- if(NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(dset_id, H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dset_id parameter is not a valid dataset identifier")
if(!size)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "size array cannot be NULL")
@@ -892,7 +845,7 @@ H5Dset_extent(hid_t dset_id, const hsize_t size[])
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set collective metadata read info")
/* Set the extent */
- if(H5D__set_extent(dset, size) < 0)
+ if ((ret_value = H5VL_dataset_specific(vol_obj, H5VL_DATASET_SET_EXTENT, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, size)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to set dataset extent")
done:
@@ -912,22 +865,25 @@ done:
herr_t
H5Dflush(hid_t dset_id)
{
- H5D_t *dset; /* Dataset for this operation */
+ H5VL_object_t *vol_obj; /* Dataset for this operation */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE1("e", "i", dset_id);
/* Check args */
- if(NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(dset_id, H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dset_id parameter is not a valid dataset identifier")
/* Set up collective metadata if appropriate */
if(H5CX_set_loc(dset_id) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set collective metadata read info")
- /* Flush dataset information cached in memory */
- if(H5D__flush(dset, dset_id) < 0)
+ /* Flush dataset information cached in memory
+ * XXX: Note that we need to pass the ID to the VOL since the H5F_flush_cb_t
+ * callback needs it and that's in the public API.
+ */
+ if((ret_value = H5VL_dataset_specific(vol_obj, H5VL_DATASET_FLUSH, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, dset_id)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTFLUSH, FAIL, "unable to flush dataset")
done:
@@ -947,14 +903,14 @@ done:
herr_t
H5Drefresh(hid_t dset_id)
{
- H5D_t *dset; /* Dataset for this operation */
+ H5VL_object_t *vol_obj; /* Dataset for this operation */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE1("e", "i", dset_id);
/* Check args */
- if(NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(dset_id, H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dset_id parameter is not a valid dataset identifier")
/* Set up collective metadata if appropriate */
@@ -962,7 +918,7 @@ H5Drefresh(hid_t dset_id)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set collective metadata read info")
/* Refresh the dataset object */
- if((H5D__refresh(dset_id, dset)) < 0)
+ if((ret_value = H5VL_dataset_specific(vol_obj, H5VL_DATASET_REFRESH, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, dset_id)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTLOAD, FAIL, "unable to refresh dataset")
done:
@@ -990,47 +946,23 @@ done:
herr_t
H5Dformat_convert(hid_t dset_id)
{
- H5D_t *dset; /* Dataset for this operation */
+ H5VL_object_t *vol_obj; /* Dataset for this operation */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE1("e", "i", dset_id);
/* Check args */
- if(NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(dset_id, H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dset_id parameter is not a valid dataset identifier")
/* Set up collective metadata if appropriate */
if(H5CX_set_loc(dset_id) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set collective metadata read info")
- switch(dset->shared->layout.type) {
- case H5D_CHUNKED:
- /* Convert the chunk indexing type to version 1 B-tree if not */
- if(dset->shared->layout.u.chunk.idx_type != H5D_CHUNK_IDX_BTREE)
- if((H5D__format_convert(dset)) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTLOAD, FAIL, "unable to downgrade chunk indexing type for dataset")
- break;
-
- case H5D_CONTIGUOUS:
- case H5D_COMPACT:
- /* Downgrade the layout version to 3 if greater than 3 */
- if(dset->shared->layout.version > H5O_LAYOUT_VERSION_DEFAULT)
- if((H5D__format_convert(dset)) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTLOAD, FAIL, "unable to downgrade layout version for dataset")
- break;
-
- case H5D_VIRTUAL:
- /* Nothing to do even though layout is version 4 */
- break;
-
- case H5D_LAYOUT_ERROR:
- case H5D_NLAYOUTS:
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid dataset layout type")
-
- default:
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "unknown dataset layout type")
- } /* end switch */
+ /* Convert the dataset */
+ if(H5VL_dataset_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_DATASET_FORMAT_CONVERT) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_INTERNAL, FAIL, "can't convert dataset format")
done:
FUNC_LEAVE_API(ret_value)
@@ -1052,25 +984,21 @@ done:
herr_t
H5Dget_chunk_index_type(hid_t dset_id, H5D_chunk_index_t *idx_type)
{
- H5D_t *dset; /* Dataset for this operation */
+ H5VL_object_t *vol_obj; /* Dataset for this operation */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE2("e", "i*Dk", dset_id, idx_type);
/* Check args */
- if(NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(dset_id, H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dset_id parameter is not a valid dataset identifier")
if(NULL == idx_type)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "idx_type parameter cannot be NULL")
- /* Should be a chunked dataset */
- if(dset->shared->layout.type != H5D_CHUNKED)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dataset is not chunked")
-
/* Get the chunk indexing type */
- if(idx_type)
- *idx_type = dset->shared->layout.u.chunk.idx_type;
+ if(H5VL_dataset_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_DATASET_GET_CHUNK_INDEX_TYPE, idx_type) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk index type")
done:
FUNC_LEAVE_API(ret_value)
@@ -1095,28 +1023,172 @@ done:
herr_t
H5Dget_chunk_storage_size(hid_t dset_id, const hsize_t *offset, hsize_t *chunk_nbytes)
{
- H5D_t *dset; /* Dataset for this operation */
+ H5VL_object_t *vol_obj; /* Dataset for this operation */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE3("e", "i*h*h", dset_id, offset, chunk_nbytes);
/* Check arguments */
- if(NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(dset_id, H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dset_id parameter is not a valid dataset identifier")
if(NULL == offset)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "offset parameter cannot be NULL")
if(NULL == chunk_nbytes)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "chunk_nbytes parameter cannot be NULL")
- if(H5D_CHUNKED != dset->shared->layout.type)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a chunked dataset")
-
/* Get the dataset creation property list */
- if(H5D__get_chunk_storage_size(dset, offset, chunk_nbytes) < 0)
+ if(H5VL_dataset_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_DATASET_GET_CHUNK_STORAGE_SIZE, offset, chunk_nbytes) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get storage size of chunk")
done:
FUNC_LEAVE_API(ret_value);
} /* H5Dget_chunk_storage_size() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5Dget_num_chunks
+ *
+ * Purpose: Retrieves the number of chunks that have non-empty intersection
+ * with a specified selection.
+ *
+ * Note: Currently, this function only gets the number of all written
+ * chunks, regardless the dataspace.
+ *
+ * Parameters:
+ * hid_t dset_id; IN: Chunked dataset ID
+ * hid_t fspace_id; IN: File dataspace ID
+ * hsize_t *nchunks; OUT: Number of non-empty chunks
+ *
+ * Return: Non-negative on success, negative on failure
+ *
+ * Programmer: Binh-Minh Ribler
+ * May 2019 (HDFFV-10677)
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Dget_num_chunks(hid_t dset_id, hid_t fspace_id, hsize_t *nchunks)
+{
+ H5VL_object_t *vol_obj = NULL; /* Dataset for this operation */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE3("e", "ii*h", dset_id, fspace_id, nchunks);
+
+ /* Check arguments */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(dset_id, H5I_DATASET)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid dataset identifier")
+ if(NULL == nchunks)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid argument (null)")
+
+ /* Get the number of written chunks */
+ if(H5VL_dataset_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_DATASET_GET_NUM_CHUNKS, fspace_id, nchunks) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "Can't get number of chunks")
+
+done:
+ FUNC_LEAVE_API(ret_value);
+} /* H5Dget_num_chunks() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Dget_chunk_info
+ *
+ * Purpose: Retrieves information about a chunk specified by its index.
+ *
+ * Parameters:
+ * hid_t dset_id; IN: Chunked dataset ID
+ * hid_t fspace_id; IN: File dataspace ID
+ * hsize_t index; IN: Index of written chunk
+ * hsize_t *offset OUT: Logical position of the chunk’s
+ * first element in the dataspace
+ * unsigned *filter_mask OUT: Mask for identifying the filters in use
+ * haddr_t *addr OUT: Address of the chunk
+ * hsize_t *size OUT: Size of the chunk
+ *
+ * Return: Non-negative on success, negative on failure
+ *
+ * Programmer: Binh-Minh Ribler
+ * May 2019 (HDFFV-10677)
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Dget_chunk_info(hid_t dset_id, hid_t fspace_id, hsize_t chk_index, hsize_t *offset, unsigned *filter_mask, haddr_t *addr, hsize_t *size)
+{
+ H5VL_object_t *vol_obj = NULL; /* Dataset for this operation */
+ hsize_t nchunks = 0;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE7("e", "iih*h*Iu*a*h", dset_id, fspace_id, chk_index, offset,
+ filter_mask, addr, size);
+
+ /* Check arguments */
+ if(NULL == offset && NULL == filter_mask && NULL == addr && NULL == size)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid arguments, must have at least one non-null output argument")
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(dset_id, H5I_DATASET)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid dataset identifier")
+
+ /* Get the number of written chunks to check range */
+ if(H5VL_dataset_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_DATASET_GET_NUM_CHUNKS, fspace_id, &nchunks) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "Can't get number of chunks")
+
+ /* Check range for chunk index */
+ if(chk_index >= nchunks)
+ HGOTO_ERROR(H5E_DATASET, H5E_BADRANGE, FAIL, "chunk index is out of range")
+
+ /* Call private function to get the chunk info given the chunk's index */
+ if(H5VL_dataset_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_DATASET_GET_CHUNK_INFO_BY_IDX, fspace_id, chk_index, offset, filter_mask, addr, size) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "Can't get chunk info by index")
+
+done:
+ FUNC_LEAVE_API(ret_value);
+} /* H5Dget_chunk_info() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Dget_chunk_info_by_coord
+ *
+ * Purpose: Retrieves information about a chunk specified by its logical
+ * coordinates.
+ *
+ * Parameters:
+ * hid_t dset_id; IN: Chunked dataset ID
+ * hsize_t *offset IN: Logical position of the chunk’s
+ * first element in the dataspace
+ * unsigned *filter_mask OUT: Mask for identifying the filters in use
+ * haddr_t *addr OUT: Address of the chunk
+ * hsize_t *size OUT: Size of the chunk
+ *
+ * Return: Non-negative on success, negative on failure
+ *
+ * Programmer: Binh-Minh Ribler
+ * May 2019 (HDFFV-10677)
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Dget_chunk_info_by_coord(hid_t dset_id, const hsize_t *offset, unsigned *filter_mask, haddr_t *addr, hsize_t *size)
+{
+ H5VL_object_t *vol_obj = NULL; /* Dataset for this operation */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE5("e", "i*h*Iu*a*h", dset_id, offset, filter_mask, addr, size);
+
+ /* Check arguments */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(dset_id, H5I_DATASET)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid dataset identifier")
+ if(NULL == filter_mask && NULL == addr && NULL == size)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid arguments, must have at least one non-null output argument")
+ if(NULL == offset)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid argument (null)")
+
+ /* Call private function to get the chunk info given the chunk's index */
+ if(H5VL_dataset_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_DATASET_GET_CHUNK_INFO_BY_COORD, offset, filter_mask, addr, size) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "Can't get chunk info by its logical coordinates")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Dget_chunk_info_by_coord() */
diff --git a/src/H5Dbtree.c b/src/H5Dbtree.c
index b61aed4..c13c36a 100644
--- a/src/H5Dbtree.c
+++ b/src/H5Dbtree.c
@@ -39,6 +39,7 @@
#include "H5FLprivate.h" /* Free Lists */
#include "H5Iprivate.h" /* IDs */
#include "H5MFprivate.h" /* File space management */
+#include "H5MMprivate.h" /* Memory management */
#include "H5Oprivate.h" /* Object headers */
#include "H5Sprivate.h" /* Dataspaces */
#include "H5VMprivate.h" /* Vector and array functions */
@@ -847,7 +848,7 @@ H5D__btree_shared_create(const H5F_t *f, H5O_storage_chunk_t *store,
/* Set up the "local" information for this dataset's chunks */
if(NULL == (my_layout = H5FL_MALLOC(H5O_layout_chunk_t)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "can't allocate chunk layout")
- HDmemcpy(my_layout, layout, sizeof(H5O_layout_chunk_t));
+ H5MM_memcpy(my_layout, layout, sizeof(H5O_layout_chunk_t));
shared->udata = my_layout;
/* Make shared B-tree info reference counted */
@@ -1087,7 +1088,7 @@ H5D__btree_idx_iterate_cb(H5F_t H5_ATTR_UNUSED *f, const void *_lt_key,
HDcompile_assert(sizeof(chunk_rec.filter_mask) == sizeof(lt_key->filter_mask));
/* Compose generic chunk record for callback */
- HDmemcpy(&chunk_rec, lt_key, sizeof(*lt_key));
+ H5MM_memcpy(&chunk_rec, lt_key, sizeof(*lt_key));
chunk_rec.chunk_addr = addr;
/* Make "generic chunk" callback */
diff --git a/src/H5Dbtree2.c b/src/H5Dbtree2.c
index b32f395..56554f8 100644
--- a/src/H5Dbtree2.c
+++ b/src/H5Dbtree2.c
@@ -32,6 +32,7 @@
#include "H5Dpkg.h" /* Datasets */
#include "H5FLprivate.h" /* Free Lists */
#include "H5MFprivate.h" /* File space management */
+#include "H5MMprivate.h" /* Memory management */
#include "H5VMprivate.h" /* Vector and array functions */
@@ -203,9 +204,9 @@ const H5B2_class_t H5D_BT2_FILT[1] = {{ /* B-tree class information */
/* Declare a free list to manage the H5D_bt2_ctx_t struct */
H5FL_DEFINE_STATIC(H5D_bt2_ctx_t);
-/* Declare a free list to manage the page elements */
-H5FL_BLK_DEFINE(chunk_dim);
+/* Declare a free list to manage the page elements */
+H5FL_ARR_DEFINE_STATIC(uint32_t, H5O_LAYOUT_NDIMS);
@@ -246,9 +247,9 @@ H5D__bt2_crt_context(void *_udata)
ctx->ndims = udata->ndims;
/* Set up the "local" information for this dataset's chunk dimension sizes */
- if(NULL == (my_dim = (uint32_t *)H5FL_BLK_MALLOC(chunk_dim, H5O_LAYOUT_NDIMS * sizeof(uint32_t))))
+ if(NULL == (my_dim = (uint32_t *)H5FL_ARR_MALLOC(uint32_t, H5O_LAYOUT_NDIMS)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, NULL, "can't allocate chunk dims")
- HDmemcpy(my_dim, udata->dim, H5O_LAYOUT_NDIMS * sizeof(uint32_t));
+ H5MM_memcpy(my_dim, udata->dim, H5O_LAYOUT_NDIMS * sizeof(uint32_t));
ctx->dim = my_dim;
/*
@@ -291,7 +292,7 @@ H5D__bt2_dst_context(void *_ctx)
/* Free array for chunk dimension sizes */
if(ctx->dim)
- (void)H5FL_BLK_FREE(chunk_dim, ctx->dim);
+ (void)H5FL_ARR_FREE(uint32_t, ctx->dim);
/* Release callback context */
ctx = H5FL_FREE(H5D_bt2_ctx_t, ctx);
diff --git a/src/H5Dchunk.c b/src/H5Dchunk.c
index 30a9a3b..53ca7d1 100644
--- a/src/H5Dchunk.c
+++ b/src/H5Dchunk.c
@@ -216,6 +216,18 @@ typedef struct H5D_chunk_readvv_ud_t {
const H5D_t *dset; /* Dataset to operate on */
} H5D_chunk_readvv_ud_t;
+typedef struct H5D_chunk_info_iter_ud_t {
+ hsize_t scaled[H5O_LAYOUT_NDIMS]; /* Logical offset of the chunk */
+ hsize_t ndims; /* Number of dimensions in the dataset */
+ uint32_t nbytes; /* Size of stored data in the chunk */
+ unsigned filter_mask; /* Excluded filters */
+ haddr_t chunk_addr; /* Address of the chunk in file */
+ hsize_t chunk_idx; /* Chunk index, where the iteration needs to stop */
+ hsize_t curr_idx; /* Current index, where the iteration is */
+ unsigned idx_hint; /* Index of chunk in cache, if present */
+ 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 */
@@ -242,6 +254,8 @@ static herr_t H5D__chunk_init(H5F_t *f, const H5D_t *dset, hid_t dapl_id);
static herr_t H5D__chunk_io_init(const H5D_io_info_t *io_info,
const H5D_type_info_t *type_info, hsize_t nelmts, const H5S_t *file_space,
const 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, const H5S_t *file_space, const H5S_t *mem_space,
H5D_chunk_map_t *fm);
@@ -252,6 +266,11 @@ 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_dest(H5D_t *dset);
+/* Chunk query operation callbacks */
+static int H5D__get_num_chunks_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata);
+static int H5D__get_chunk_info_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata);
+static int H5D__get_chunk_info_by_coord_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,
@@ -265,7 +284,7 @@ static int H5D__chunk_format_convert_cb(const H5D_chunk_rec_t *chunk_rec, void *
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 void *H5D__chunk_mem_alloc(size_t size, const H5O_pline_t *pline);
-static void *H5D__chunk_mem_xfree(void *chk, const H5O_pline_t *pline);
+static void *H5D__chunk_mem_xfree(void *chk, const void *pline);
static void *H5D__chunk_mem_realloc(void *chk, size_t size,
const H5O_pline_t *pline);
static herr_t H5D__chunk_cinfo_cache_reset(H5D_chunk_cached_t *last);
@@ -276,8 +295,13 @@ static hbool_t H5D__chunk_cinfo_cache_found(const H5D_chunk_cached_t *last,
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);
@@ -313,6 +337,7 @@ const H5D_layout_ops_t H5D_LOPS_CHUNK[1] = {{
H5D__chunk_construct,
H5D__chunk_init,
H5D__chunk_is_space_alloc,
+ H5D__chunk_is_data_cached,
H5D__chunk_io_init,
H5D__chunk_read,
H5D__chunk_write,
@@ -340,6 +365,7 @@ const H5D_layout_ops_t H5D_LOPS_NONEXISTENT[1] = {{
NULL,
NULL,
NULL,
+ NULL,
#ifdef H5_HAVE_PARALLEL
NULL,
NULL,
@@ -389,18 +415,24 @@ H5D__chunk_direct_write(const H5D_t *dset, uint32_t filters, hsize_t *offset,
H5D_chk_idx_info_t idx_info; /* Chunked index info */
hsize_t scaled[H5S_MAX_RANK]; /* Scaled coordinates for this chunk */
hbool_t need_insert = FALSE; /* Whether the chunk needs to be inserted into the index */
- H5D_io_info_t io_info; /* to hold the dset info */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE_TAG(dset->oloc.addr)
- io_info.dset = dset;
+ /* Sanity checks */
+ HDassert(layout->type == H5D_CHUNKED);
/* Allocate dataspace and initialize it if it hasn't been. */
- if(!(*layout->ops->is_space_alloc)(&layout->storage))
+ 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)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize storage")
+ } /* end if */
/* Calculate the index of this chunk */
H5VM_chunk_scaled(dset->shared->ndims, offset, layout->u.chunk.dim, scaled);
@@ -435,13 +467,17 @@ H5D__chunk_direct_write(const H5D_t *dset, uint32_t filters, hsize_t *offset,
if(0 == idx_info.pline->nused && H5F_addr_defined(old_chunk.offset))
/* If there are no filters and we are overwriting the chunk we can just set values */
need_insert = FALSE;
- else
+ else {
/* Otherwise, create the chunk it if it doesn't exist, or reallocate the chunk
* if its size has changed.
*/
if(H5D__chunk_file_alloc(&idx_info, &old_chunk, &udata.chunk_block, &need_insert, scaled) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "unable to allocate chunk")
+ /* Cache the new chunk information */
+ H5D__chunk_cinfo_cache_update(&dset->shared->cache.chunk.last, &udata);
+ } /* end else */
+
/* Make sure the address of the chunk is returned. */
if(!H5F_addr_defined(udata.chunk_block.offset))
HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "chunk address isn't defined")
@@ -456,7 +492,7 @@ H5D__chunk_direct_write(const H5D_t *dset, uint32_t filters, hsize_t *offset,
} /* end if */
/* Write the data to the file */
- if(H5F_block_write(dset->oloc.file, H5FD_MEM_DRAW, udata.chunk_block.offset, data_size, buf) < 0)
+ if(H5F_shared_block_write(H5F_SHARED(dset->oloc.file), H5FD_MEM_DRAW, udata.chunk_block.offset, data_size, buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to write raw data to file")
/* Insert the chunk record into the index */
@@ -506,7 +542,8 @@ H5D__chunk_direct_read(const H5D_t *dset, hsize_t *offset, uint32_t* filters,
*filters = 0;
/* Allocate dataspace and initialize it if it hasn't been. */
- if(!(*layout->ops->is_space_alloc)(&layout->storage))
+ if(!H5D__chunk_is_space_alloc(&layout->storage)
+ && !H5D__chunk_is_data_cached(dset->shared))
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "storage is not initialized")
/* Calculate the index of this chunk */
@@ -558,9 +595,9 @@ H5D__chunk_direct_read(const H5D_t *dset, hsize_t *offset, uint32_t* filters,
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "chunk address isn't defined")
/* Read the chunk data into the supplied buffer */
- if(H5F_block_read(dset->oloc.file, H5FD_MEM_DRAW, udata.chunk_block.offset, udata.chunk_block.length, buf) < 0)
+ if(H5F_shared_block_read(H5F_SHARED(dset->oloc.file), H5FD_MEM_DRAW, udata.chunk_block.offset, udata.chunk_block.length, buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk")
-
+
/* Return the filter mask */
*filters = udata.filter_mask;
@@ -700,7 +737,13 @@ H5D__chunk_set_info_real(H5O_layout_chunk_t *layout, unsigned ndims,
if(H5S_UNLIMITED == max_dims[u])
layout->max_chunks[u] = H5S_UNLIMITED;
else
+ {
+ /* Sanity check */
+ if(layout->dim[u] == 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "dimension size must be > 0, dim = %u ", u)
+
layout->max_chunks[u] = ((max_dims[u] + layout->dim[u]) - 1) / layout->dim[u];
+ }
/* Accumulate the # of chunks */
layout->nchunks *= layout->chunks[u];
@@ -949,7 +992,10 @@ H5D__chunk_init(H5F_t *f, const H5D_t *dset, hid_t dapl_id)
/* Initial scaled dimension sizes */
if(dset->shared->layout.u.chunk.dim[u] == 0)
HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "chunk size must be > 0, dim = %u ", u)
- rdcc->scaled_dims[u] = dset->shared->curr_dims[u] / dset->shared->layout.u.chunk.dim[u];
+
+ /* Round up to the next integer # of chunks, to accommodate partial chunks */
+ rdcc->scaled_dims[u] = (dset->shared->curr_dims[u] + dset->shared->layout.u.chunk.dim[u] - 1) /
+ dset->shared->layout.u.chunk.dim[u];
if( !(scaled_power2up = H5VM_power2up(rdcc->scaled_dims[u])) )
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to get the next power of 2")
@@ -1013,6 +1059,30 @@ H5D__chunk_is_space_alloc(const H5O_storage_t *storage)
/*-------------------------------------------------------------------------
+ * Function: H5D__chunk_is_data_cached
+ *
+ * Purpose: Query if raw data is cached for dataset
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * Wednessday, March 6, 2016
+ *
+ *-------------------------------------------------------------------------
+ */
+hbool_t
+H5D__chunk_is_data_cached(const H5D_shared_t *shared_dset)
+{
+ FUNC_ENTER_PACKAGE_NOERR
+
+ /* Sanity checks */
+ HDassert(shared_dset);
+
+ FUNC_LEAVE_NOAPI(shared_dset->cache.chunk.nused > 0)
+} /* end H5D__chunk_is_data_cached() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5D__chunk_io_init
*
* Purpose: Performs initialization before any sort of I/O on the raw data
@@ -1030,7 +1100,6 @@ H5D__chunk_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t *type_inf
H5D_chunk_map_t *fm)
{
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 */
hssize_t old_offset[H5O_LAYOUT_NDIMS]; /* Old selection offset */
htri_t file_space_normalized = FALSE; /* File dataspace was normalized */
@@ -1038,7 +1107,6 @@ H5D__chunk_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t *type_inf
hbool_t iter_init = FALSE; /* Selection iteration info has been initialized */
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) */
- H5SL_node_t *curr_node; /* Current node in skip list */
char bogus; /* "bogus" buffer to pass to selection iterator */
unsigned u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
@@ -1067,21 +1135,19 @@ H5D__chunk_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t *type_inf
if((file_space_normalized = H5S_hyper_normalize_offset((H5S_t *)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++) {
+ /* 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];
- } /* end for */
#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(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 */
@@ -1094,13 +1160,54 @@ H5D__chunk_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t *type_inf
fm->file_space = file_space;
fm->mem_space = mem_space;
+ if(H5D__chunk_io_init_selections(io_info, type_info, fm) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create file and memory chunk selections")
+
+done:
+ /* Reset the global dataspace info */
+ fm->file_space = NULL;
+ fm->mem_space = NULL;
+
+ if(file_space_normalized == TRUE)
+ if(H5S_hyper_denormalize_offset((H5S_t *)file_space, old_offset) < 0) /* (Casting away const OK -QAK) */
+ HDONE_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't denormalize selection")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D__chunk_io_init() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D__chunk_io_init_selections
+ *
+ * Purpose: Initialize the chunk mappings
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, March 20, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+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)
+{
+ 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 */
+
+ FUNC_ENTER_STATIC
+
/* Special case for only one element in selection */
/* (usually appending a record) */
- if(nelmts == 1
+ if(fm->nelmts == 1
#ifdef H5_HAVE_PARALLEL
&& !(io_info->using_mpi_vfd)
#endif /* H5_HAVE_PARALLEL */
- && H5S_SEL_ALL != H5S_GET_SELECT_TYPE(file_space)) {
+ && H5S_SEL_ALL != H5S_GET_SELECT_TYPE(fm->file_space)) {
/* Initialize skip list for chunk selections */
fm->sel_chunks = NULL;
fm->use_single = TRUE;
@@ -1108,7 +1215,7 @@ H5D__chunk_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t *type_inf
/* 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(file_space, TRUE, FALSE)) == NULL)
+ if((dataset->shared->cache.chunk.single_space = H5S_copy(fm->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 */
@@ -1123,10 +1230,9 @@ H5D__chunk_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t *type_inf
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)
if(NULL == (dataset->shared->cache.chunk.single_chunk_info = H5FL_MALLOC(H5D_chunk_info_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate chunk info")
- } /* end if */
fm->single_chunk_info = dataset->shared->cache.chunk.single_chunk_info;
HDassert(fm->single_chunk_info);
@@ -1141,10 +1247,9 @@ H5D__chunk_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t *type_inf
hbool_t sel_hyper_flag; /* Whether file selection is a hyperslab */
/* Initialize skip list for chunk selections */
- if(NULL == dataset->shared->cache.chunk.sel_chunks) {
+ 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")
- } /* end if */
fm->sel_chunks = dataset->shared->cache.chunk.sel_chunks;
HDassert(fm->sel_chunks);
@@ -1152,9 +1257,9 @@ H5D__chunk_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t *type_inf
fm->use_single = FALSE;
/* Get type of selection on disk & in memory */
- if((fm->fsel_type = H5S_GET_SELECT_TYPE(file_space)) < H5S_SEL_NONE)
+ if((fm->fsel_type = H5S_GET_SELECT_TYPE(fm->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(mem_space)) < H5S_SEL_NONE)
+ if((fm->msel_type = H5S_GET_SELECT_TYPE(fm->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 */
@@ -1163,30 +1268,22 @@ H5D__chunk_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t *type_inf
else
sel_hyper_flag = TRUE;
- /* Check if file selection is a not a hyperslab selection */
- if(sel_hyper_flag) {
- /* Build the file selection for each chunk */
- if(H5D__create_chunk_file_map_hyper(fm, io_info) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create file chunk selections")
-
- /* Clean file chunks' hyperslab span "scratch" information */
- curr_node = H5SL_first(fm->sel_chunks);
- while(curr_node) {
- H5D_chunk_info_t *chunk_info; /* Pointer chunk information */
-
- /* Get pointer to chunk's information */
- chunk_info = (H5D_chunk_info_t *)H5SL_item(curr_node);
- HDassert(chunk_info);
-
- /* Clean hyperslab span's "scratch" information */
- if(H5S_hyper_reset_scratch(chunk_info->fspace) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "unable to reset span scratch info")
+ /* Check if file selection is a not a hyperslab selection */
+ 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)
+ 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);
- /* Get the next chunk node in the skip list */
- curr_node = H5SL_next(curr_node);
- } /* end while */
- } /* end if */
- else {
+ if(H5D__create_chunk_file_map_hyper(fm, 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 */
@@ -1204,7 +1301,7 @@ H5D__chunk_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t *type_inf
iter_op.u.lib_op = H5D__chunk_file_cb;
/* Spaces might not be the same shape, iterate over the file selection directly */
- if(H5S_select_iterate(&bogus, file_type, file_space, &iter_op, &udata) < 0)
+ if(H5S_select_iterate(&bogus, file_type, fm->file_space, &iter_op, &udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create file chunk selections")
/* Reset "last chunk" info */
@@ -1213,7 +1310,7 @@ H5D__chunk_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t *type_inf
} /* end else */
/* Build the memory selection for each chunk */
- if(sel_hyper_flag && H5S_select_shape_same(file_space, mem_space) == TRUE) {
+ if(sel_hyper_flag && H5S_SELECT_SHAPE_SAME(fm->file_space, fm->mem_space) == TRUE) {
/* Reset chunk template information */
fm->mchunk_tmpl = NULL;
@@ -1223,12 +1320,19 @@ H5D__chunk_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t *type_inf
if(H5D__create_chunk_mem_map_hyper(fm) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create memory chunk selections")
} /* end if */
- else {
+ 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)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create file chunk selections")
+
+ } else {
H5S_sel_iter_op_t iter_op; /* Operator for iteration */
size_t elmt_size; /* Memory datatype size */
/* Make a copy of equivalent memory space */
- if((tmp_mspace = H5S_copy(mem_space, TRUE, FALSE)) == NULL)
+ if((tmp_mspace = H5S_copy(fm->mem_space, TRUE, FALSE)) == NULL)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy memory space")
/* De-select the mem space copy */
@@ -1239,15 +1343,14 @@ H5D__chunk_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t *type_inf
fm->mchunk_tmpl = tmp_mspace;
/* Create temporary datatypes for selection iteration */
- if(!file_type) {
- if(NULL == (file_type = H5T_copy(dataset->shared->type, H5T_COPY_ALL)))
+ if(!file_type)
+ if(NULL == (file_type = H5T_copy(dataset->shared->type, H5T_COPY_ALL)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "unable to copy file datatype")
- } /* end if */
/* 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), mem_space, elmt_size) < 0)
+ if(H5S_select_iter_init(&(fm->mem_iter), fm->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 */
@@ -1255,28 +1358,8 @@ H5D__chunk_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t *type_inf
iter_op.u.lib_op = H5D__chunk_mem_cb;
/* Spaces aren't the same shape, iterate over the memory selection directly */
- if(H5S_select_iterate(&bogus, file_type, file_space, &iter_op, fm) < 0)
+ if(H5S_select_iterate(&bogus, file_type, fm->file_space, &iter_op, fm) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create memory chunk selections")
-
- /* Clean up hyperslab stuff, if necessary */
- if(fm->msel_type != H5S_SEL_POINTS) {
- /* Clean memory chunks' hyperslab span "scratch" information */
- curr_node = H5SL_first(fm->sel_chunks);
- while(curr_node) {
- H5D_chunk_info_t *chunk_info; /* Pointer chunk information */
-
- /* Get pointer to chunk's information */
- chunk_info = (H5D_chunk_info_t *)H5SL_item(curr_node);
- HDassert(chunk_info);
-
- /* Clean hyperslab span's "scratch" information */
- if(H5S_hyper_reset_scratch(chunk_info->mspace) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "unable to reset span scratch info")
-
- /* Get the next chunk node in the skip list */
- curr_node = H5SL_next(curr_node);
- } /* end while */
- } /* end if */
} /* end else */
} /* end else */
@@ -1292,20 +1375,13 @@ done:
HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release chunk mapping")
} /* end if */
- /* Reset the global dataspace info */
- fm->file_space = NULL;
- fm->mem_space = NULL;
-
if(iter_init && H5S_SELECT_ITER_RELEASE(&(fm->mem_iter)) < 0)
HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator")
if(file_type && (H5T_close_real(file_type) < 0))
HDONE_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "Can't free temporary datatype")
- if(file_space_normalized == TRUE)
- if(H5S_hyper_denormalize_offset((H5S_t *)file_space, old_offset) < 0) /* (Casting away const OK -QAK) */
- HDONE_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't denormalize selection")
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D__chunk_io_init() */
+} /* end H5D__chunk_io_init_selections() */
/*-------------------------------------------------------------------------
@@ -1343,7 +1419,7 @@ H5D__chunk_mem_alloc(size_t size, const H5O_pline_t *pline)
/*-------------------------------------------------------------------------
* Function: H5D__chunk_mem_xfree
*
- * Purpose: Free space for a chunk in memory. This routine allocates
+ * Purpose: Free space for a chunk in memory. This routine releases
* memory space for non-filtered chunks from a block free list
* and uses malloc()/free() for filtered chunks.
*
@@ -1355,8 +1431,10 @@ H5D__chunk_mem_alloc(size_t size, const H5O_pline_t *pline)
*-------------------------------------------------------------------------
*/
static void *
-H5D__chunk_mem_xfree(void *chk, const H5O_pline_t *pline)
+H5D__chunk_mem_xfree(void *chk, const void *_pline)
{
+ const H5O_pline_t *pline = (const H5O_pline_t *)_pline;
+
FUNC_ENTER_STATIC_NOERR
if(chk) {
@@ -1487,6 +1565,9 @@ H5D__create_chunk_map_single(H5D_chunk_map_t *fm, const H5D_io_info_t
/* 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)
+ 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];
@@ -1529,9 +1610,214 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5D__create_chunk_file_map_all
+ *
+ * Purpose: Create all chunk selections in file, for an "all" selection.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Monday, January 21, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+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)
+{
+ 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 */
+ unsigned num_partial_dims; /* Current number of partial dimensions */
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity check */
+ HDassert(fm->f_ndims > 0);
+
+ /* Get number of elements selected in file */
+ sel_points = fm->nelmts;
+
+ /* Get dataspace dimensions */
+ if(H5S_get_simple_extent_dims(fm->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 */
+ num_partial_dims = 0;
+ 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)
+ HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "chunk size must be > 0, dim = %u ", u)
+
+ /* Set up start / end coordinates for first chunk */
+ scaled[u] = 0;
+ coords[u] = 0;
+ end[u] = fm->chunk_dim[u] - 1;
+
+ /* Iniitialize partial chunk dimension information */
+ partial_dim_size[u] = file_dims[u] % fm->chunk_dim[u];
+ if(file_dims[u] < fm->chunk_dim[u]) {
+ curr_partial_clip[u] = partial_dim_size[u];
+ is_partial_dim[u] = TRUE;
+ num_partial_dims++;
+ } /* end if */
+ else {
+ curr_partial_clip[u] = fm->chunk_dim[u];
+ is_partial_dim[u] = FALSE;
+ } /* end else */
+ } /* end for */
+
+ /* Set the index of this chunk */
+ chunk_index = 0;
+
+ /* Create "temporary" chunk for selection operations (copy file space) */
+ if(NULL == (tmp_fchunk = H5S_create_simple(fm->f_ndims, fm->chunk_dim, NULL)))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTCREATE, FAIL, "unable to create dataspace for chunk")
+
+ /* Iterate through each chunk in the dataset */
+ while(sel_points) {
+ H5D_chunk_info_t *new_chunk_info; /* chunk information to insert into skip list */
+ hssize_t schunk_points; /* Number of elements in chunk selection */
+
+ /* 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)))
+ 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 */
+
+ /* Set the file chunk dataspace */
+ if(NULL == (new_chunk_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;
+
+ /* 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, 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;
+
+ /* 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;
+
+ /* 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")
+ } /* end if */
+
+ /* Get number of elements selected in chunk */
+ if((schunk_points = H5S_GET_SELECT_NPOINTS(new_chunk_info->fspace)) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection # of elements")
+ H5_CHECKED_ASSIGN(new_chunk_info->chunk_points, uint32_t, schunk_points, hssize_t);
+
+ /* Decrement # of points left in file selection */
+ sel_points -= (hsize_t)schunk_points;
+
+ /* Advance to next chunk if we are not done */
+ if(sel_points > 0) {
+ int curr_dim; /* Current dimension to increment */
+
+ /* Increment chunk index */
+ chunk_index++;
+
+ /* Set current increment dimension */
+ curr_dim = (int)fm->f_ndims - 1;
+
+ /* Increment chunk location in fastest changing dimension */
+ coords[curr_dim] += fm->chunk_dim[curr_dim];
+ scaled[curr_dim]++;
+ end[curr_dim] += fm->chunk_dim[curr_dim];
+
+ /* Bring chunk location back into bounds, if necessary */
+ if(coords[curr_dim] >= file_dims[curr_dim]) {
+ do {
+ /* Reset current dimension's location to 0 */
+ coords[curr_dim] = 0;
+ scaled[curr_dim] = 0;
+ end[curr_dim] = fm->chunk_dim[curr_dim] - 1;
+
+ /* Check for previous partial chunk in this dimension */
+ if(is_partial_dim[curr_dim] && end[curr_dim] < file_dims[curr_dim]) {
+ /* Sanity check */
+ HDassert(num_partial_dims > 0);
+
+ /* Reset partial chunk information for this dimension */
+ curr_partial_clip[curr_dim] = fm->chunk_dim[curr_dim];
+ is_partial_dim[curr_dim] = FALSE;
+ num_partial_dims--;
+ } /* end if */
+
+ /* Decrement current dimension */
+ curr_dim--;
+
+ /* Check for valid current dim */
+ if(curr_dim >= 0) {
+ /* Increment chunk location in current dimension */
+ coords[curr_dim] += fm->chunk_dim[curr_dim];
+ scaled[curr_dim]++;
+ end[curr_dim] = (coords[curr_dim] + fm->chunk_dim[curr_dim]) - 1;
+ } /* end if */
+ } while(curr_dim >= 0 && (coords[curr_dim] >= file_dims[curr_dim]));
+ } /* end if */
+
+ /* Check for valid current dim */
+ if(curr_dim >= 0) {
+ /* Check for partial chunk in this dimension */
+ if(!is_partial_dim[curr_dim] && file_dims[curr_dim] <= end[curr_dim]) {
+ /* Set partial chunk information for this dimension */
+ curr_partial_clip[curr_dim] = partial_dim_size[curr_dim];
+ is_partial_dim[curr_dim] = TRUE;
+ num_partial_dims++;
+
+ /* Sanity check */
+ HDassert(num_partial_dims <= fm->f_ndims);
+ } /* end if */
+ } /* end if */
+ } /* end if */
+ } /* end while */
+
+done:
+ /* Clean up */
+ if(tmp_fchunk && H5S_close(tmp_fchunk) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "can't release temporary dataspace")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D__create_chunk_file_map_all() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5D__create_chunk_file_map_hyper
*
- * Purpose: Create all chunk selections in file.
+ * Purpose: Create all chunk selections in file, for a hyperslab selection.
*
* Return: Non-negative on success/Negative on failure
*
@@ -1547,8 +1833,9 @@ H5D__create_chunk_file_map_hyper(H5D_chunk_map_t *fm, const H5D_io_info_t
#endif /* H5_HAVE_PARALLEL */
*io_info)
{
- 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 */
+ 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 */
@@ -1563,7 +1850,7 @@ H5D__create_chunk_file_map_hyper(H5D_chunk_map_t *fm, const H5D_io_info_t
FUNC_ENTER_STATIC
/* Sanity check */
- HDassert(fm->f_ndims>0);
+ HDassert(fm->f_ndims > 0);
/* Get number of elements selected in file */
sel_points = fm->nelmts;
@@ -1574,6 +1861,9 @@ H5D__create_chunk_file_map_hyper(H5D_chunk_map_t *fm, const H5D_io_info_t
/* 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)
+ 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];
end[u] = (coords[u] + fm->chunk_dim[u]) - 1;
@@ -1584,53 +1874,36 @@ H5D__create_chunk_file_map_hyper(H5D_chunk_map_t *fm, const H5D_io_info_t
/* Iterate through each chunk in the dataset */
while(sel_points) {
- /* Check for intersection of temporary chunk and file selection */
+ /* Check for intersection of current chunk and file selection */
/* (Casting away const OK - QAK) */
- if(TRUE == H5S_hyper_intersect_block((H5S_t *)fm->file_space, coords, end)) {
- H5S_t *tmp_fchunk; /* Temporary file dataspace */
+ 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 */
hssize_t schunk_points; /* Number of elements in chunk selection */
- /* Create "temporary" chunk for selection operations (copy file space) */
- if(NULL == (tmp_fchunk = H5S_copy(fm->file_space, TRUE, FALSE)))
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy memory space")
-
- /* Make certain selections are stored in span tree form (not "optimized hyperslab" or "all") */
- if(H5S_hyper_convert(tmp_fchunk) < 0) {
- (void)H5S_close(tmp_fchunk);
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to convert selection to span trees")
- } /* end if */
-
- /* "AND" temporary chunk and current chunk */
- if(H5S_select_hyperslab(tmp_fchunk,H5S_SELECT_AND,coords,NULL,fm->chunk_dim,NULL) < 0) {
- (void)H5S_close(tmp_fchunk);
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't create chunk selection")
- } /* end if */
+ /* 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, &tmp_fchunk) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to combine file space selection with chunk block")
/* Resize chunk's dataspace dimensions to size of chunk */
- if(H5S_set_extent_real(tmp_fchunk,fm->chunk_dim) < 0) {
- (void)H5S_close(tmp_fchunk);
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't adjust chunk dimensions")
- } /* end if */
+ if(H5S_set_extent_real(tmp_fchunk, fm->chunk_dim) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTSELECT, FAIL, "can't adjust chunk dimensions")
/* Move selection back to have correct offset in chunk */
- if(H5S_SELECT_ADJUST_U(tmp_fchunk, coords) < 0) {
- (void)H5S_close(tmp_fchunk);
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't adjust chunk selection")
- }
+ if(H5S_SELECT_ADJUST_U(tmp_fchunk, coords) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTSELECT, FAIL, "can't adjust chunk selection")
/* 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))) {
- (void)H5S_close(tmp_fchunk);
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate chunk info")
- } /* end if */
+ if(NULL == (new_chunk_info = H5FL_MALLOC(H5D_chunk_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;
+ new_chunk_info->index = chunk_index;
#ifdef H5_HAVE_PARALLEL
/* Store chunk selection information, for multi-chunk I/O */
@@ -1641,18 +1914,16 @@ H5D__create_chunk_file_map_hyper(H5D_chunk_map_t *fm, const H5D_io_info_t
/* Set the file chunk dataspace */
new_chunk_info->fspace = tmp_fchunk;
new_chunk_info->fspace_shared = FALSE;
+ tmp_fchunk = NULL;
/* Set the memory chunk dataspace */
- new_chunk_info->mspace=NULL;
+ new_chunk_info->mspace = NULL;
new_chunk_info->mspace_shared = FALSE;
/* Copy the chunk's scaled coordinates */
- HDmemcpy(new_chunk_info->scaled, scaled, sizeof(hsize_t) * fm->f_ndims);
+ H5MM_memcpy(new_chunk_info->scaled, scaled, sizeof(hsize_t) * fm->f_ndims);
new_chunk_info->scaled[fm->f_ndims] = 0;
- /* Copy the chunk's scaled coordinates */
- HDmemcpy(new_chunk_info->scaled, scaled, sizeof(hsize_t) * fm->f_ndims);
-
/* 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);
@@ -1660,7 +1931,7 @@ H5D__create_chunk_file_map_hyper(H5D_chunk_map_t *fm, const H5D_io_info_t
} /* end if */
/* Get number of elements selected in chunk */
- if((schunk_points = H5S_GET_SELECT_NPOINTS(tmp_fchunk)) < 0)
+ if((schunk_points = H5S_GET_SELECT_NPOINTS(new_chunk_info->fspace)) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection # of elements")
H5_CHECKED_ASSIGN(new_chunk_info->chunk_points, uint32_t, schunk_points, hssize_t);
@@ -1676,12 +1947,11 @@ H5D__create_chunk_file_map_hyper(H5D_chunk_map_t *fm, const H5D_io_info_t
chunk_index++;
/* Set current increment dimension */
- curr_dim=(int)fm->f_ndims-1;
+ curr_dim = (int)fm->f_ndims - 1;
/* Increment chunk location in fastest changing dimension */
- H5_CHECK_OVERFLOW(fm->chunk_dim[curr_dim],hsize_t,hssize_t);
- coords[curr_dim]+=fm->chunk_dim[curr_dim];
- end[curr_dim]+=fm->chunk_dim[curr_dim];
+ coords[curr_dim] += fm->chunk_dim[curr_dim];
+ end[curr_dim] += fm->chunk_dim[curr_dim];
scaled[curr_dim]++;
/* Bring chunk location back into bounds, if necessary */
@@ -1695,11 +1965,14 @@ H5D__create_chunk_file_map_hyper(H5D_chunk_map_t *fm, const H5D_io_info_t
/* Decrement current dimension */
curr_dim--;
- /* Increment chunk location in current dimension */
- scaled[curr_dim]++;
- coords[curr_dim] += fm->chunk_dim[curr_dim];
- end[curr_dim] = (coords[curr_dim] + fm->chunk_dim[curr_dim]) - 1;
- } while(coords[curr_dim] > sel_end[curr_dim]);
+ /* Check for valid current dim */
+ if(curr_dim >= 0) {
+ /* Increment chunk location in current dimension */
+ scaled[curr_dim]++;
+ coords[curr_dim] += fm->chunk_dim[curr_dim];
+ end[curr_dim] = (coords[curr_dim] + fm->chunk_dim[curr_dim]) - 1;
+ } /* end if */
+ } 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);
@@ -1707,6 +1980,11 @@ H5D__create_chunk_file_map_hyper(H5D_chunk_map_t *fm, const H5D_io_info_t
} /* end while */
done:
+ /* Clean up on failure */
+ if(ret_value < 0)
+ if(tmp_fchunk && H5S_close(tmp_fchunk) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "can't release temporary dataspace")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__create_chunk_file_map_hyper() */
@@ -1730,13 +2008,13 @@ done:
static herr_t
H5D__create_chunk_mem_map_hyper(const H5D_chunk_map_t *fm)
{
+ H5D_chunk_info_t *chunk_info; /* Pointer to chunk information */
H5SL_node_t *curr_node; /* Current node in skip list */
- hsize_t file_sel_start[H5O_LAYOUT_NDIMS]; /* Offset of low bound of file selection */
- hsize_t file_sel_end[H5O_LAYOUT_NDIMS]; /* Offset of high bound of file selection */
- hsize_t mem_sel_start[H5O_LAYOUT_NDIMS]; /* Offset of low bound of file selection */
- hsize_t mem_sel_end[H5O_LAYOUT_NDIMS]; /* Offset of high bound of file selection */
- hssize_t adjust[H5O_LAYOUT_NDIMS]; /* Adjustment to make to all file chunks */
- hssize_t chunk_adjust[H5O_LAYOUT_NDIMS]; /* Adjustment to make to a particular chunk */
+ 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 */
+ hsize_t mem_sel_start[H5S_MAX_RANK]; /* Offset of low bound of file selection */
+ hsize_t mem_sel_end[H5S_MAX_RANK]; /* Offset of high bound of file selection */
+ hssize_t adjust[H5S_MAX_RANK]; /* Adjustment to make to all file chunks */
unsigned u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
@@ -1747,10 +2025,8 @@ H5D__create_chunk_mem_map_hyper(const H5D_chunk_map_t *fm)
/* Check for all I/O going to a single chunk */
if(H5SL_count(fm->sel_chunks)==1) {
- H5D_chunk_info_t *chunk_info; /* Pointer to chunk information */
-
/* Get the node */
- curr_node=H5SL_first(fm->sel_chunks);
+ curr_node = H5SL_first(fm->sel_chunks);
/* Get pointer to chunk's information */
chunk_info = (H5D_chunk_info_t *)H5SL_item(curr_node);
@@ -1773,54 +2049,70 @@ H5D__create_chunk_mem_map_hyper(const H5D_chunk_map_t *fm)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection bound info")
/* Calculate the adjustment for memory selection from file selection */
- HDassert(fm->m_ndims==fm->f_ndims);
- for(u=0; u<fm->f_ndims; u++) {
- H5_CHECK_OVERFLOW(file_sel_start[u],hsize_t,hssize_t);
- H5_CHECK_OVERFLOW(mem_sel_start[u],hsize_t,hssize_t);
- adjust[u]=(hssize_t)file_sel_start[u]-(hssize_t)mem_sel_start[u];
+ HDassert(fm->m_ndims == fm->f_ndims);
+ for(u = 0; u < fm->f_ndims; u++) {
+ H5_CHECK_OVERFLOW(file_sel_start[u], hsize_t, hssize_t);
+ H5_CHECK_OVERFLOW(mem_sel_start[u], hsize_t, hssize_t);
+ adjust[u] = (hssize_t)file_sel_start[u] - (hssize_t)mem_sel_start[u];
} /* end for */
/* Iterate over each chunk in the chunk list */
- curr_node=H5SL_first(fm->sel_chunks);
+ curr_node = H5SL_first(fm->sel_chunks);
while(curr_node) {
- H5D_chunk_info_t *chunk_info; /* Pointer to chunk information */
+ hsize_t coords[H5S_MAX_RANK]; /* Current coordinates of chunk */
+ hssize_t chunk_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);
+ /* 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];
+
/* Copy the information */
/* Copy the memory dataspace */
if((chunk_info->mspace = H5S_copy(fm->mem_space, TRUE, FALSE)) == NULL)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy memory space")
- /* Release the current selection */
- if(H5S_SELECT_RELEASE(chunk_info->mspace) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection")
+ /* Get the chunk's selection type */
+ if((chunk_sel_type = H5S_GET_SELECT_TYPE(chunk_info->fspace)) < H5S_SEL_NONE)
+ HGOTO_ERROR(H5E_DATASET, H5E_BADSELECT, FAIL, "unable to get type of selection")
- /* Copy the file chunk's selection */
- if(H5S_select_copy(chunk_info->mspace,chunk_info->fspace,FALSE) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy selection")
+ /* Set memory selection for "all" chunk selections */
+ if(H5S_SEL_ALL == chunk_sel_type) {
+ /* Adjust the chunk coordinates */
+ for(u = 0; u < fm->f_ndims; u++)
+ coords[u] = (hsize_t)((hssize_t)coords[u] - adjust[u]);
- /* Compute the adjustment for this chunk */
- for(u = 0; u < fm->f_ndims; u++) {
- hsize_t coords[H5O_LAYOUT_NDIMS]; /* Current coordinates of chunk */
+ /* Set to same shape as chunk */
+ if(H5S_select_hyperslab(chunk_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 */
+ else {
+ /* Sanity check */
+ HDassert(H5S_SEL_HYPERSLABS == chunk_sel_type);
- /* Compute the chunk coordinates from the scaled coordinates */
- coords[u] = chunk_info->scaled[u] * fm->layout->u.chunk.dim[u];
+ /* Copy the file chunk's selection */
+ if(H5S_SELECT_COPY(chunk_info->mspace, chunk_info->fspace, FALSE) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy selection")
- /* Compensate for the chunk offset */
- H5_CHECK_OVERFLOW(coords[u], hsize_t, hssize_t);
- chunk_adjust[u] = adjust[u] - (hssize_t)coords[u]; /*lint !e771 The adjust array will always be initialized */
- } /* end for */
+ /* 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]; /*lint !e771 The adjust array will always be initialized */
+ } /* end for */
- /* Adjust the selection */
- if(H5S_hyper_adjust_s(chunk_info->mspace, chunk_adjust) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to adjust selection")
+ /* Adjust the selection */
+ if(H5S_hyper_adjust_s(chunk_info->mspace, chunk_adjust) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to adjust selection")
+ } /* end else */
/* Get the next chunk node in the skip list */
- curr_node=H5SL_next(curr_node);
+ curr_node = H5SL_next(curr_node);
} /* end while */
} /* end else */
@@ -1828,6 +2120,93 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__create_chunk_mem_map_hyper() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D__create_mem_map_1d
+ *
+ * Purpose: Create all chunk selections for 1-dimensional regular memory space
+ * that has only one single block in the selection
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Vailin Choi
+ * Sept 18, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D__create_chunk_mem_map_1d(const H5D_chunk_map_t *fm)
+{
+ H5D_chunk_info_t *chunk_info; /* Pointer to chunk 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 */
+ hsize_t mem_sel_start[H5S_MAX_RANK]; /* Offset of low bound of file selection */
+ hsize_t mem_sel_end[H5S_MAX_RANK]; /* Offset of high bound of file selection */
+ hssize_t adjust[H5S_MAX_RANK]; /* Adjustment to make to all file chunks */
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity check */
+ HDassert(fm->f_ndims>0);
+
+ /* Check for all I/O going to a single chunk */
+ if(H5SL_count(fm->sel_chunks)==1) {
+ /* Get the node */
+ curr_node = H5SL_first(fm->sel_chunks);
+
+ /* Get pointer to chunk's information */
+ chunk_info = (H5D_chunk_info_t *)H5SL_item(curr_node);
+ HDassert(chunk_info);
+
+ /* Just point at the memory dataspace & selection */
+ /* (Casting away const OK -QAK) */
+ chunk_info->mspace = (H5S_t *)fm->mem_space;
+
+ /* Indicate that the chunk's memory space is shared */
+ chunk_info->mspace_shared = TRUE;
+ } /* end if */
+ else {
+ HDassert(fm->m_ndims == 1);
+ hsize_t mem_sel_start[H5S_MAX_RANK]; /* Offset of low bound of file selection */
+ hsize_t mem_sel_end[H5S_MAX_RANK]; /* Offset of high bound of file selection */
+
+ if(H5S_SELECT_BOUNDS(fm->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);
+ while(curr_node) {
+ hssize_t schunk_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);
+
+ /* Copy the memory dataspace */
+ if((chunk_info->mspace = H5S_copy(fm->mem_space, TRUE, FALSE)) == NULL)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy memory space")
+
+ schunk_points = H5S_GET_SELECT_NPOINTS(chunk_info->fspace);
+
+ if(H5S_select_hyperslab(chunk_info->mspace, H5S_SELECT_SET, mem_sel_start, NULL, &tmp_count, &schunk_points) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTSELECT, FAIL, "can't create chunk memory selection")
+
+ mem_sel_start[0] += schunk_points;
+
+ /* Get the next chunk 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_1d() */
+
/*-------------------------------------------------------------------------
* Function: H5D__chunk_file_cb
@@ -1908,9 +2287,9 @@ H5D__chunk_file_cb(void H5_ATTR_UNUSED *elem, const H5T_t H5_ATTR_UNUSED *type,
chunk_info->chunk_points = 0;
/* Set the chunk's scaled coordinates */
- HDmemcpy(chunk_info->scaled, scaled, sizeof(hsize_t) * fm->f_ndims);
+ H5MM_memcpy(chunk_info->scaled, scaled, sizeof(hsize_t) * fm->f_ndims);
chunk_info->scaled[fm->f_ndims] = 0;
- HDmemcpy(chunk_info->scaled, scaled, sizeof(hsize_t) * fm->f_ndims);
+ H5MM_memcpy(chunk_info->scaled, scaled, sizeof(hsize_t) * fm->f_ndims);
/* Insert the new chunk into the skip list */
if(H5SL_insert(fm->sel_chunks,chunk_info,&chunk_info->index) < 0) {
@@ -1964,7 +2343,7 @@ H5D__chunk_mem_cb(void H5_ATTR_UNUSED *elem, const H5T_t H5_ATTR_UNUSED *type, u
{
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[H5O_LAYOUT_NDIMS]; /* Coordinates of element in memory */
+ 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 */
@@ -1986,14 +2365,13 @@ H5D__chunk_mem_cb(void H5_ATTR_UNUSED *elem, const H5T_t H5_ATTR_UNUSED *type, u
*/
/* 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, FAIL, "can't locate chunk in skip list")
+ HGOTO_ERROR(H5E_DATASPACE, H5E_NOTFOUND, H5_ITER_ERROR, "can't locate chunk in skip list")
/* Check if the chunk already has a memory space */
- if(NULL == chunk_info->mspace) {
+ if(NULL == chunk_info->mspace)
/* Copy the template memory chunk dataspace */
if(NULL == (chunk_info->mspace = H5S_copy(fm->mchunk_tmpl, FALSE, FALSE)))
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy file space")
- } /* end else */
+ 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;
@@ -2002,21 +2380,21 @@ H5D__chunk_mem_cb(void H5_ATTR_UNUSED *elem, const H5T_t H5_ATTR_UNUSED *type, u
/* Get coordinates of selection iterator for memory */
if(H5S_SELECT_ITER_COORDS(&fm->mem_iter, coords_in_mem) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get iterator coordinates")
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, H5_ITER_ERROR, "unable to get iterator coordinates")
/* 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)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "unable to select element")
+ 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)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "unable to select element")
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, H5_ITER_ERROR, "unable to select element")
} /* end else */
/* Move memory selection iterator to next element in selection */
if(H5S_SELECT_ITER_NEXT(&fm->mem_iter, (size_t)1) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTNEXT, FAIL, "unable to move to next iterator location")
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTNEXT, H5_ITER_ERROR, "unable to move to next iterator location")
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -2152,11 +2530,11 @@ H5D__chunk_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
HDassert(fm);
/* Set up "nonexistent" I/O info object */
- HDmemcpy(&nonexistent_io_info, io_info, sizeof(nonexistent_io_info));
+ H5MM_memcpy(&nonexistent_io_info, io_info, sizeof(nonexistent_io_info));
nonexistent_io_info.layout_ops = *H5D_LOPS_NONEXISTENT;
/* Set up contiguous I/O info object */
- HDmemcpy(&ctg_io_info, io_info, sizeof(ctg_io_info));
+ 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;
@@ -2164,7 +2542,7 @@ H5D__chunk_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
H5_CHECKED_ASSIGN(ctg_store.contig.dset_size, hsize_t, io_info->dset->shared->layout.u.chunk.size, uint32_t);
/* Set up compact I/O info object */
- HDmemcpy(&cpt_io_info, io_info, sizeof(cpt_io_info));
+ 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;
@@ -2302,7 +2680,7 @@ H5D__chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
HDassert(fm);
/* Set up contiguous I/O info object */
- HDmemcpy(&ctg_io_info, io_info, sizeof(ctg_io_info));
+ 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;
@@ -2310,7 +2688,7 @@ H5D__chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
H5_CHECKED_ASSIGN(ctg_store.contig.dset_size, hsize_t, io_info->dset->shared->layout.u.chunk.size, uint32_t);
/* Set up compact I/O info object */
- HDmemcpy(&cpt_io_info, io_info, sizeof(cpt_io_info));
+ 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;
@@ -2665,7 +3043,7 @@ H5D__chunk_cinfo_cache_update(H5D_chunk_cached_t *last, const H5D_chunk_ud_t *ud
HDassert(udata->common.scaled);
/* Stored the information to cache */
- HDmemcpy(last->scaled, udata->common.scaled, sizeof(hsize_t) * udata->common.layout->ndims);
+ H5MM_memcpy(last->scaled, udata->common.scaled, sizeof(hsize_t) * udata->common.layout->ndims);
last->addr = udata->chunk_block.offset;
H5_CHECKED_ASSIGN(last->nbytes, uint32_t, udata->chunk_block.length, hsize_t);
last->chunk_idx = udata->chunk_idx;
@@ -2784,8 +3162,8 @@ done:
/*-------------------------------------------------------------------------
* Function: H5D__chunk_hash_val
*
- * Purpose: To calculate an index based on the dataset's scaled coordinates and
- * sizes of the faster dimensions.
+ * Purpose: To calculate an index based on the dataset's scaled
+ * coordinates and sizes of the faster dimensions.
*
* Return: Hash value index
*
@@ -2799,6 +3177,7 @@ H5D__chunk_hash_val(const H5D_shared_t *shared, const hsize_t *scaled)
hsize_t val; /* Intermediate value */
unsigned ndims = shared->ndims; /* Rank of dataset */
unsigned ret = 0; /* Value to return */
+ unsigned u; /* Local index variable */
FUNC_ENTER_STATIC_NOERR
@@ -2809,17 +3188,11 @@ H5D__chunk_hash_val(const H5D_shared_t *shared, const hsize_t *scaled)
/* If the fastest changing dimension doesn't have enough entropy, use
* other dimensions too
*/
- if(ndims > 1 && shared->cache.chunk.scaled_dims[ndims - 1] <= shared->cache.chunk.nslots) {
- unsigned u; /* Local index variable */
-
- val = scaled[0];
- for(u = 1; u < ndims; u++) {
- val <<= shared->cache.chunk.scaled_encode_bits[u];
- val ^= scaled[u];
- } /* end for */
- } /* end if */
- else
- val = scaled[ndims - 1];
+ val = scaled[0];
+ for(u = 1; u < ndims; u++) {
+ val <<= shared->cache.chunk.scaled_encode_bits[u];
+ val ^= scaled[u];
+ } /* end for */
/* Modulo value against the number of array slots */
ret = (unsigned)(val % shared->cache.chunk.nslots);
@@ -2907,9 +3280,6 @@ H5D__chunk_lookup(const H5D_t *dset, const hsize_t *scaled,
/* Check for cached information */
if(!H5D__chunk_cinfo_cache_found(&dset->shared->cache.chunk.last, udata)) {
H5D_chk_idx_info_t idx_info; /* Chunked index info */
-#ifdef H5_HAVE_PARALLEL
- H5P_coll_md_read_flag_t temp_cmr; /* Temp value to hold the coll metadata read setting */
-#endif /* H5_HAVE_PARALLEL */
/* Compose chunked index info struct */
idx_info.f = dset->oloc.file;
@@ -2918,25 +3288,18 @@ H5D__chunk_lookup(const H5D_t *dset, const hsize_t *scaled,
idx_info.storage = &dset->shared->layout.storage.u.chunk;
#ifdef H5_HAVE_PARALLEL
- if(H5F_HAS_FEATURE(idx_info.f, H5FD_FEAT_HAS_MPI)) {
- /* disable collective metadata read for chunk indexes
- as it is highly unlikely that users would read the
- same chunks from all processes. MSC - might turn on
- for root node? */
- temp_cmr = H5F_COLL_MD_READ(idx_info.f);
- H5F_set_coll_md_read(idx_info.f, H5P_FORCE_FALSE);
- } /* end if */
+ /* Disable collective metadata read for chunk indexes as it is
+ * highly unlikely that users would read the same chunks from all
+ * processes.
+ */
+ if(H5F_HAS_FEATURE(idx_info.f, H5FD_FEAT_HAS_MPI))
+ H5CX_set_coll_metadata_read(FALSE);
#endif /* H5_HAVE_PARALLEL */
/* Go get the chunk information */
if((dset->shared->layout.storage.u.chunk.ops->get_addr)(&idx_info, udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't query chunk address")
-#ifdef H5_HAVE_PARALLEL
- if(H5F_HAS_FEATURE(idx_info.f, H5FD_FEAT_HAS_MPI))
- H5F_set_coll_md_read(idx_info.f, temp_cmr);
-#endif /* H5_HAVE_PARALLEL */
-
/*
* Cache the information retrieved.
*
@@ -3049,7 +3412,7 @@ H5D__chunk_flush_entry(const H5D_t *dset, H5D_rdcc_ent_t *ent, hbool_t reset)
*/
if(NULL == (buf = H5MM_malloc(alloc)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for pipeline")
- HDmemcpy(buf, ent->chunk, alloc);
+ H5MM_memcpy(buf, ent->chunk, alloc);
} /* end if */
else {
/*
@@ -3121,7 +3484,7 @@ H5D__chunk_flush_entry(const H5D_t *dset, H5D_rdcc_ent_t *ent, hbool_t reset)
/* Write the data to the file */
HDassert(H5F_addr_defined(udata.chunk_block.offset));
H5_CHECK_OVERFLOW(udata.chunk_block.length, hsize_t, size_t);
- if(H5F_block_write(dset->oloc.file, H5FD_MEM_DRAW, udata.chunk_block.offset, (size_t)udata.chunk_block.length, buf) < 0)
+ if(H5F_shared_block_write(H5F_SHARED(dset->oloc.file), H5FD_MEM_DRAW, udata.chunk_block.offset, (size_t)udata.chunk_block.length, buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to write raw data to file")
/* Insert the chunk record into the index */
@@ -3462,7 +3825,7 @@ H5D__chunk_lock(const H5D_io_info_t *io_info, H5D_chunk_ud_t *udata,
*/
if(NULL == (chunk = H5D__chunk_mem_alloc(chunk_size, pline)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for raw data chunk")
- HDmemcpy(chunk, ent->chunk, chunk_size);
+ H5MM_memcpy(chunk, ent->chunk, chunk_size);
ent->chunk = (uint8_t *)H5D__chunk_mem_xfree(ent->chunk, old_pline);
ent->chunk = (uint8_t *)chunk;
chunk = NULL;
@@ -3488,7 +3851,7 @@ H5D__chunk_lock(const H5D_io_info_t *io_info, H5D_chunk_ud_t *udata,
*/
if(NULL == (chunk = H5D__chunk_mem_alloc(chunk_size, pline)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for raw data chunk")
- HDmemcpy(chunk, ent->chunk, chunk_size);
+ H5MM_memcpy(chunk, ent->chunk, chunk_size);
ent->chunk = (uint8_t *)H5D__chunk_mem_xfree(ent->chunk, old_pline);
ent->chunk = (uint8_t *)chunk;
@@ -3592,7 +3955,7 @@ H5D__chunk_lock(const H5D_io_info_t *io_info, H5D_chunk_ud_t *udata,
* size in memory, so allocate memory big enough. */
if(NULL == (chunk = H5D__chunk_mem_alloc(my_chunk_alloc, (udata->new_unfilt_chunk ? old_pline : pline))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for raw data chunk")
- if(H5F_block_read(dset->oloc.file, H5FD_MEM_DRAW, chunk_addr, my_chunk_alloc, chunk) < 0)
+ if(H5F_shared_block_read(H5F_SHARED(dset->oloc.file), H5FD_MEM_DRAW, chunk_addr, my_chunk_alloc, chunk) < 0)
HGOTO_ERROR(H5E_IO, H5E_READERROR, NULL, "unable to read raw data chunk")
if(old_pline && old_pline->nused) {
@@ -3617,7 +3980,7 @@ H5D__chunk_lock(const H5D_io_info_t *io_info, H5D_chunk_ud_t *udata,
(void)H5D__chunk_mem_xfree(tmp_chunk, old_pline);
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for raw data chunk")
} /* end if */
- HDmemcpy(chunk, tmp_chunk, chunk_size);
+ H5MM_memcpy(chunk, tmp_chunk, chunk_size);
(void)H5D__chunk_mem_xfree(tmp_chunk, old_pline);
} /* end if */
} /* end if */
@@ -3698,7 +4061,7 @@ H5D__chunk_lock(const H5D_io_info_t *io_info, H5D_chunk_ud_t *udata,
ent->chunk_block.offset = chunk_addr;
ent->chunk_block.length = chunk_alloc;
ent->chunk_idx = udata->chunk_idx;
- HDmemcpy(ent->scaled, udata->common.scaled, sizeof(hsize_t) * layout->u.chunk.ndims);
+ H5MM_memcpy(ent->scaled, udata->common.scaled, sizeof(hsize_t) * layout->u.chunk.ndims);
H5_CHECKED_ASSIGN(ent->rd_count, uint32_t, chunk_size, size_t);
H5_CHECKED_ASSIGN(ent->wr_count, uint32_t, chunk_size, size_t);
ent->chunk = (uint8_t *)chunk;
@@ -3826,7 +4189,7 @@ H5D__chunk_unlock(const H5D_io_info_t *io_info, const H5D_chunk_ud_t *udata,
fake_ent.edge_chunk_state = H5D_RDCC_DISABLE_FILTERS;
if(udata->new_unfilt_chunk)
fake_ent.edge_chunk_state |= H5D_RDCC_NEWLY_DISABLED_FILTERS;
- HDmemcpy(fake_ent.scaled, udata->common.scaled, sizeof(hsize_t) * layout->u.chunk.ndims);
+ H5MM_memcpy(fake_ent.scaled, udata->common.scaled, sizeof(hsize_t) * layout->u.chunk.ndims);
HDassert(layout->u.chunk.size > 0);
fake_ent.chunk_idx = udata->chunk_idx;
fake_ent.chunk_block.offset = udata->chunk_block.offset;
@@ -4042,6 +4405,9 @@ H5D__chunk_allocate(const H5D_io_info_t *io_info, hbool_t full_overwrite, hsize_
* assume here that all elements of space_dim are > 0. This is checked at
* the top of this function. */
for(op_dim=0; op_dim<space_ndims; op_dim++) {
+ /* Validate this chunk dimension */
+ if(chunk_dim[op_dim] == 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "chunk size must be > 0, dim = %u ", op_dim)
min_unalloc[op_dim] = (old_dim[op_dim] + chunk_dim[op_dim] - 1) / chunk_dim[op_dim];
max_unalloc[op_dim] = (space_dim[op_dim] - 1) / chunk_dim[op_dim];
@@ -4110,7 +4476,7 @@ H5D__chunk_allocate(const H5D_io_info_t *io_info, hbool_t full_overwrite, hsize_
if(has_unfilt_edge_chunks) {
if(NULL == (unfilt_fill_buf = H5D__chunk_mem_alloc(orig_chunk_size, &def_pline)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for raw data chunk")
- HDmemcpy(unfilt_fill_buf, fb_info.fill_buf, orig_chunk_size);
+ H5MM_memcpy(unfilt_fill_buf, fb_info.fill_buf, orig_chunk_size);
} /* end if */
/* Retrieve filter settings from API context */
@@ -4319,7 +4685,7 @@ H5D__chunk_allocate(const H5D_io_info_t *io_info, hbool_t full_overwrite, hsize_
} /* end if */
else {
#endif /* H5_HAVE_PARALLEL */
- if(H5F_block_write(dset->oloc.file, H5FD_MEM_DRAW, udata.chunk_block.offset, chunk_size, *fill_buf) < 0)
+ if(H5F_shared_block_write(H5F_SHARED(dset->oloc.file), H5FD_MEM_DRAW, udata.chunk_block.offset, chunk_size, *fill_buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write raw data to file")
#ifdef H5_HAVE_PARALLEL
} /* end else */
@@ -4483,13 +4849,17 @@ H5D__chunk_update_old_edge_chunks(H5D_t *dset, hsize_t old_dim[])
/* Start off with this dimension marked as not needing to be modified */
new_full_dim[op_dim] = FALSE;
+ /* Validate this chunk dimension */
+ if(chunk_dim[op_dim] == 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "chunk size must be > 0, dim = %u ", op_dim)
+
/* Calculate offset of first previously incomplete chunk in this
* dimension */
- old_edge_chunk_sc[op_dim] = (old_dim[op_dim] / chunk_dim[op_dim]);
+ old_edge_chunk_sc[op_dim] = (old_dim[op_dim] / chunk_dim[op_dim]);
/* Calculate the largest offset of chunks that might need to be
* modified in this dimension */
- max_edge_chunk_sc[op_dim] = MIN((old_dim[op_dim] - 1) / chunk_dim[op_dim],
+ max_edge_chunk_sc[op_dim] = MIN((old_dim[op_dim] - 1) / chunk_dim[op_dim],
MAX((space_dim[op_dim] / chunk_dim[op_dim]), 1) - 1);
/* Check for old_dim aligned with chunk boundary in this dimension, if
@@ -4625,6 +4995,8 @@ H5D__chunk_collective_fill(const H5D_t *dset, H5D_chunk_coll_info_t *chunk_info,
HGOTO_ERROR(H5E_INTERNAL, H5E_MPI, FAIL, "Can't retrieve MPI size")
/* Distribute evenly the number of blocks between processes. */
+ if(mpi_size == 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "Resulted in division by zero")
num_blocks = chunk_info->num_io / mpi_size; /* value should be the same on all procs */
/* after evenly distributing the blocks between processes, are
@@ -4698,7 +5070,7 @@ H5D__chunk_collective_fill(const H5D_t *dset, H5D_chunk_coll_info_t *chunk_info,
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set transfer mode")
/* Low-level write (collective) */
- if(H5F_block_write(dset->oloc.file, H5FD_MEM_DRAW, (haddr_t)0, (blocks) ? (size_t)1 : (size_t)0, fill_buf) < 0)
+ if(H5F_shared_block_write(H5F_SHARED(dset->oloc.file), H5FD_MEM_DRAW, (haddr_t)0, (blocks) ? (size_t)1 : (size_t)0, fill_buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write raw data to file")
/* Barrier so processes don't race ahead */
@@ -4822,12 +5194,12 @@ H5D__chunk_prune_fill(H5D_chunk_it_ud1_t *udata, hbool_t new_unfilt_chunk)
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "can't allocate chunk selection iterator")
/* Create a selection iterator for scattering the elements to memory buffer */
- if(H5S_select_iter_init(chunk_iter, udata->chunk_space, layout->u.chunk.dim[rank]) < 0)
+ if(H5S_select_iter_init(chunk_iter, udata->chunk_space, layout->u.chunk.dim[rank], 0) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize chunk selection information")
chunk_iter_init = TRUE;
/* Scatter the data into memory */
- if(H5D__scatter_mem(udata->fb_info.fill_buf, udata->chunk_space, chunk_iter, (size_t)sel_nelmts, chunk/*out*/) < 0)
+ if(H5D__scatter_mem(udata->fb_info.fill_buf, chunk_iter, (size_t)sel_nelmts, chunk/*out*/) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "scatter failed")
@@ -5065,6 +5437,10 @@ H5D__chunk_prune_by_extent(H5D_t *dset, const hsize_t *old_dim)
HDmemset(min_mod_chunk_sc, 0, sizeof(min_mod_chunk_sc));
HDmemset(max_mod_chunk_sc, 0, sizeof(max_mod_chunk_sc));
for(op_dim = 0; op_dim < (unsigned)space_ndims; op_dim++) {
+ /* Validate this chunk dimension */
+ if(chunk_dim[op_dim] == 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "chunk size must be > 0, dim = %u ", op_dim)
+
/* Calculate the largest offset of chunks that might need to be
* modified in this dimension */
max_mod_chunk_sc[op_dim] = (old_dim[op_dim] - 1) / chunk_dim[op_dim];
@@ -5634,7 +6010,7 @@ H5D__chunk_copy_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata)
if(udata->chunk_in_cache && udata->chunk) {
HDassert(!H5F_addr_defined(chunk_rec->chunk_addr));
- HDmemcpy(buf, udata->chunk, nbytes);
+ H5MM_memcpy(buf, udata->chunk, nbytes);
udata->chunk = NULL;
}
else {
@@ -5668,7 +6044,7 @@ H5D__chunk_copy_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata)
HDassert(H5F_addr_defined(ent->chunk_block.offset));
H5_CHECKED_ASSIGN(nbytes, size_t, shared_fo->layout.u.chunk.size, uint32_t);
- HDmemcpy(buf, ent->chunk, nbytes);
+ H5MM_memcpy(buf, ent->chunk, nbytes);
}
else {
/* read chunk data from the source file */
@@ -5702,7 +6078,7 @@ H5D__chunk_copy_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5_ITER_ERROR, "datatype conversion failed")
/* Copy into another buffer, to reclaim memory later */
- HDmemcpy(reclaim_buf, buf, reclaim_buf_size);
+ H5MM_memcpy(reclaim_buf, buf, reclaim_buf_size);
/* Set background buffer to all zeros */
HDmemset(bkg, 0, buf_size);
@@ -5712,25 +6088,20 @@ H5D__chunk_copy_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5_ITER_ERROR, "datatype conversion failed")
/* Reclaim space from variable length data */
- if(H5D_vlen_reclaim(tid_mem, buf_space, reclaim_buf) < 0)
+ if(H5T_reclaim(tid_mem, buf_space, reclaim_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_BADITER, H5_ITER_ERROR, "unable to reclaim variable-length data")
} /* end if */
else if(fix_ref) {
/* Check for expanding references */
/* (background buffer has already been zeroed out, if not expanding) */
if(udata->cpy_info->expand_ref) {
- size_t ref_count;
-
- /* Determine # of reference elements to copy */
- ref_count = nbytes / H5T_get_size(udata->dt_src);
-
/* Copy the reference elements */
- if(H5O_copy_expand_ref(udata->file_src, buf, udata->idx_info_dst->f, bkg, ref_count, H5T_get_ref_type(udata->dt_src), udata->cpy_info) < 0)
+ if(H5O_copy_expand_ref(udata->file_src, udata->tid_src, udata->dt_src, buf, nbytes, udata->idx_info_dst->f, bkg, udata->cpy_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, H5_ITER_ERROR, "unable to copy reference attribute")
} /* end if */
/* After fix ref, copy the new reference elements to the buffer to write out */
- HDmemcpy(buf, bkg, buf_size);
+ H5MM_memcpy(buf, bkg, buf_size);
} /* end if */
/* Set up destination chunk callback information for insertion */
@@ -6030,7 +6401,7 @@ H5D__chunk_copy(H5F_t *f_src, H5O_storage_chunk_t *storage_src,
for(ent = shared_fo->cache.chunk.head; ent; ent = next) {
if(!H5F_addr_defined(ent->chunk_block.offset)) {
- HDmemcpy(chunk_rec.scaled, ent->scaled, sizeof(chunk_rec.scaled));
+ H5MM_memcpy(chunk_rec.scaled, ent->scaled, sizeof(chunk_rec.scaled));
udata.chunk = ent->chunk;
udata.chunk_in_cache = TRUE;
if(H5D__chunk_copy_cb(&chunk_rec, &udata) < 0)
@@ -6280,15 +6651,16 @@ H5D__chunk_stats(const H5D_t *dset, hbool_t headers)
HGOTO_DONE(SUCCEED)
if (headers) {
- fprintf(H5DEBUG(AC), "H5D: raw data cache statistics\n");
- fprintf(H5DEBUG(AC), " %-18s %8s %8s %8s %8s+%-8s\n",
+ HDfprintf(H5DEBUG(AC), "H5D: raw data cache statistics\n");
+ HDfprintf(H5DEBUG(AC), " %-18s %8s %8s %8s %8s+%-8s\n",
"Layer", "Hits", "Misses", "MissRate", "Inits", "Flushes");
- fprintf(H5DEBUG(AC), " %-18s %8s %8s %8s %8s-%-8s\n",
+ HDfprintf(H5DEBUG(AC), " %-18s %8s %8s %8s %8s-%-8s\n",
"-----", "----", "------", "--------", "-----", "-------");
}
#ifdef H5AC_DEBUG
- if (H5DEBUG(AC)) headers = TRUE;
+ if (H5DEBUG(AC))
+ headers = TRUE;
#endif
if (headers) {
@@ -6299,12 +6671,12 @@ H5D__chunk_stats(const H5D_t *dset, hbool_t headers)
miss_rate = 0.0;
}
if (miss_rate > 100) {
- sprintf(ascii, "%7d%%", (int) (miss_rate + 0.5));
+ HDsprintf(ascii, "%7d%%", (int) (miss_rate + 0.5));
} else {
- sprintf(ascii, "%7.2f%%", miss_rate);
+ HDsprintf(ascii, "%7.2f%%", miss_rate);
}
- fprintf(H5DEBUG(AC), " %-18s %8u %8u %7s %8d+%-9ld\n",
+ HDfprintf(H5DEBUG(AC), " %-18s %8u %8u %7s %8d+%-9ld\n",
"raw data chunks", rdcc->stats.nhits, rdcc->stats.nmisses, ascii,
rdcc->stats.ninits, (long)(rdcc->stats.nflushes)-(long)(rdcc->stats.ninits));
}
@@ -6473,7 +6845,7 @@ done:
*/
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, hsize_t scaled[])
+ H5F_block_t *new_chunk, hbool_t *need_insert, const hsize_t *scaled)
{
hbool_t alloc_chunk = FALSE; /* Whether to allocate chunk */
herr_t ret_value = SUCCEED; /* Return value */
@@ -6725,3 +7097,373 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__chunk_format_convert() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5D__get_num_chunks_cb
+ *
+ * Purpose: Callback function that increments the number of written
+ * chunks in the dataset.
+ *
+ * Note: Currently, this function only gets the number of all written
+ * chunks, regardless the dataspace.
+ *
+ * Return: H5_ITER_CONT
+ *
+ * Programmer: Binh-Minh Ribler
+ * June 2019 (HDFFV-10677)
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+H5D__get_num_chunks_cb(const H5D_chunk_rec_t H5_ATTR_UNUSED *chunk_rec, void *_udata)
+{
+ hsize_t *num_chunks = (hsize_t *)_udata;
+ int ret_value = H5_ITER_CONT; /* Callback return value */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ HDassert(num_chunks);
+
+ (*num_chunks)++;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5D__get_num_chunks_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D__get_num_chunks
+ *
+ * Purpose: Gets the number of written chunks in a dataset.
+ *
+ * Note: Currently, this function only gets the number of all written
+ * chunks, regardless the dataspace.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Binh-Minh Ribler
+ * June 2019 (HDFFV-10677)
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5D__get_num_chunks(const H5D_t *dset, const H5S_t H5_ATTR_UNUSED *space, hsize_t *nchunks)
+{
+ H5D_chk_idx_info_t idx_info; /* Chunked index info */
+ hsize_t num_chunks = 0; /* Number of written chunks */
+ H5D_rdcc_ent_t *ent; /* Cache entry */
+ const H5D_rdcc_t *rdcc = NULL; /* Raw data chunk cache */
+ const H5O_layout_t *layout; /* Dataset layout */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE_TAG(dset->oloc.addr)
+
+ HDassert(dset);
+ HDassert(dset->shared);
+ HDassert(space);
+ HDassert(nchunks);
+
+ layout = &(dset->shared->layout); /* Dataset layout */
+ rdcc = &(dset->shared->cache.chunk); /* raw data chunk cache */
+ HDassert(rdcc);
+
+ /* Search for cached chunks that haven't been written out */
+ for(ent = rdcc->head; ent; ent = ent->next)
+ /* Flush the chunk out to disk, to make certain the size is correct later */
+ if(H5D__chunk_flush_entry(dset, ent, FALSE) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "cannot flush indexed storage buffer")
+
+ /* Compose chunked index info struct */
+ idx_info.f = dset->oloc.file;
+ idx_info.pline = &dset->shared->dcpl_cache.pline;
+ idx_info.layout = &dset->shared->layout.u.chunk;
+ idx_info.storage = &dset->shared->layout.storage.u.chunk;
+
+ /* If the dataset is not written, number of chunks will be 0 */
+ if(!H5F_addr_defined(idx_info.storage->idx_addr)) {
+ *nchunks = 0;
+ }
+ else {
+ /* Iterate over the allocated chunks */
+ if((dset->shared->layout.storage.u.chunk.ops->iterate)(&idx_info, H5D__get_num_chunks_cb, &num_chunks) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to retrieve allocated chunk information from index")
+ *nchunks = num_chunks;
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D__get_num_chunks() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D__get_chunk_info_cb
+ *
+ * Purpose: Get the chunk info of the queried chunk, given by its index.
+ *
+ * Return: Success: H5_ITER_CONT or H5_ITER_STOP
+ * H5_ITER_STOP indicates the queried chunk is found
+ * Failure: Negative (H5_ITER_ERROR)
+ *
+ * Programmer: Binh-Minh Ribler
+ * June 2019 (HDFFV-10677)
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+H5D__get_chunk_info_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata)
+{
+ H5D_chunk_info_iter_ud_t *chunk_info = (H5D_chunk_info_iter_ud_t *)_udata;
+ hsize_t ii = 0; /* Dimension index */
+ int ret_value = H5_ITER_CONT; /* Callback return value */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Check args */
+ HDassert(chunk_rec);
+ HDassert(chunk_info);
+
+ /* If this is the queried chunk, retrieve its info and stop iterating */
+ if (chunk_info->curr_idx == chunk_info->chunk_idx) {
+ chunk_info->filter_mask = chunk_rec->filter_mask;
+ chunk_info->chunk_addr = chunk_rec->chunk_addr;
+ chunk_info->nbytes = chunk_rec->nbytes;
+ for (ii = 0; ii < chunk_info->ndims; ii++)
+ chunk_info->scaled[ii] = chunk_rec->scaled[ii];
+ chunk_info->found = TRUE;
+
+ /* Stop iterating */
+ ret_value = H5_ITER_STOP;
+ }
+ /* Go to the next chunk */
+ else
+ chunk_info->curr_idx++;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5D__get_chunk_info_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D__get_chunk_info
+ *
+ * Purpose: Iterate over the chunks in the dataset to get the info
+ * of the desired chunk.
+ *
+ * Note: Currently, the domain of the index in this function is of all
+ * the written chunks, regardless the dataspace.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: Binh-Minh Ribler
+ * June 2019 (HDFFV-10677)
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5D__get_chunk_info(const H5D_t *dset, const H5S_t H5_ATTR_UNUSED *space, hsize_t chk_index, hsize_t *offset, unsigned *filter_mask, haddr_t *addr, hsize_t *size)
+{
+ H5D_chk_idx_info_t idx_info; /* Chunked index info */
+ H5D_chunk_info_iter_ud_t udata; /* User data for callback */
+ const H5D_rdcc_t *rdcc = NULL; /* Raw data chunk cache */
+ H5D_rdcc_ent_t *ent; /* Cache entry index */
+ hsize_t ii = 0; /* Dimension index */
+ herr_t ret_value = SUCCEED;/* Return value */
+
+ FUNC_ENTER_PACKAGE_TAG(dset->oloc.addr)
+
+ HDassert(dset);
+ HDassert(dset->shared);
+ HDassert(space);
+
+ /* Get the raw data chunk cache */
+ rdcc = &(dset->shared->cache.chunk);
+ HDassert(rdcc);
+
+ /* Search for cached chunks that haven't been written out */
+ for(ent = rdcc->head; ent; ent = ent->next)
+ /* Flush the chunk out to disk, to make certain the size is correct later */
+ if(H5D__chunk_flush_entry(dset, ent, FALSE) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "cannot flush indexed storage buffer")
+
+ /* Compose chunked index info struct */
+ idx_info.f = dset->oloc.file;
+ idx_info.pline = &dset->shared->dcpl_cache.pline;
+ idx_info.layout = &dset->shared->layout.u.chunk;
+ idx_info.storage = &dset->shared->layout.storage.u.chunk;
+
+ /* Set addr & size for when dset is not written or queried chunk is not found */
+ if (addr)
+ *addr = HADDR_UNDEF;
+ if (size)
+ *size = 0;
+
+ /* If the chunk is written, get its info, otherwise, return without error */
+ if(H5F_addr_defined(idx_info.storage->idx_addr)) {
+ /* Initialize before iteration */
+ udata.chunk_idx = chk_index;
+ udata.curr_idx = 0;
+ udata.ndims = dset->shared->ndims;
+ udata.nbytes = 0;
+ udata.filter_mask = 0;
+ udata.chunk_addr = HADDR_UNDEF;
+ udata.found = FALSE;
+
+ /* Iterate over the allocated chunks */
+ if((dset->shared->layout.storage.u.chunk.ops->iterate)(&idx_info, H5D__get_chunk_info_cb, &udata) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to retrieve allocated chunk information from index")
+
+ /* Obtain requested info if the chunk is found */
+ if(udata.found) {
+ if(filter_mask)
+ *filter_mask = udata.filter_mask;
+ if(addr)
+ *addr = udata.chunk_addr;
+ if(size)
+ *size = udata.nbytes;
+ if(offset)
+ for(ii = 0; ii < udata.ndims; ii++)
+ offset[ii] = udata.scaled[ii] * dset->shared->layout.u.chunk.dim[ii];
+ }
+ } /* end if H5F_addr_defined */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D__get_chunk_info() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D__get_chunk_info_by_coord_cb
+ *
+ * Purpose: Get the chunk info of the desired chunk, given its offset
+ * coordinates.
+ *
+ * Return: Success: H5_ITER_CONT or H5_ITER_STOP
+ * Failure: Negative (H5_ITER_ERROR)
+ *
+ * Programmer: Binh-Minh Ribler
+ * June 2019 (HDFFV-10677)
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+H5D__get_chunk_info_by_coord_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata)
+{
+ hsize_t ii;
+ H5D_chunk_info_iter_ud_t *chunk_info = (H5D_chunk_info_iter_ud_t *)_udata;
+ hbool_t different = FALSE; /* TRUE when a scaled value pair mismatch */
+ int ret_value = H5_ITER_CONT; /* Callback return value */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Check args */
+ HDassert(chunk_rec);
+ HDassert(chunk_info);
+
+ /* Going through the scaled, stop when a mismatch is found */
+ for (ii = 0; ii < chunk_info->ndims && !different; ii++)
+ if (chunk_info->scaled[ii] != chunk_rec->scaled[ii])
+ different = TRUE;
+
+ /* Same scaled coords means the chunk is found, copy the chunk info */
+ if (!different) {
+ chunk_info->nbytes = chunk_rec->nbytes;
+ chunk_info->filter_mask = chunk_rec->filter_mask;
+ chunk_info->chunk_addr = chunk_rec->chunk_addr;
+ chunk_info->found = TRUE;
+
+ /* Stop iterating */
+ ret_value = H5_ITER_STOP;
+ }
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5D__get_chunk_info_by_coord_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D__get_chunk_info_by_coord
+ *
+ * Purpose: Iterate over the chunks in the dataset to get the info
+ * of the desired chunk, given by its offset coordinates.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Binh-Minh Ribler
+ * June 2019 (HDFFV-10677)
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5D__get_chunk_info_by_coord(const H5D_t *dset, const hsize_t *offset, unsigned* filter_mask, haddr_t *addr, hsize_t *size)
+{
+ const H5O_layout_t *layout = NULL; /* Dataset layout */
+ const H5D_rdcc_t *rdcc = NULL; /* Raw data chunk cache */
+ H5D_rdcc_ent_t *ent; /* Cache entry index */
+ H5D_chk_idx_info_t idx_info; /* Chunked index info */
+ H5D_chunk_info_iter_ud_t udata; /* User data for callback */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE_TAG(dset->oloc.addr)
+
+ /* Check args */
+ HDassert(dset);
+ HDassert(dset->shared);
+ HDassert(offset);
+
+ /* Get dataset layout and raw data chunk cache */
+ layout = &(dset->shared->layout);
+ rdcc = &(dset->shared->cache.chunk);
+ HDassert(layout);
+ HDassert(rdcc);
+ HDassert(H5D_CHUNKED == layout->type);
+
+ /* Search for cached chunks that haven't been written out */
+ for(ent = rdcc->head; ent; ent = ent->next)
+ /* Flush the chunk out to disk, to make certain the size is correct later */
+ if(H5D__chunk_flush_entry(dset, ent, FALSE) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "cannot flush indexed storage buffer")
+
+ /* Set addr & size for when dset is not written or queried chunk is not found */
+ if (addr)
+ *addr = HADDR_UNDEF;
+ if (size)
+ *size = 0;
+
+ /* Compose chunked index info struct */
+ idx_info.f = dset->oloc.file;
+ idx_info.pline = &dset->shared->dcpl_cache.pline;
+ idx_info.layout = &dset->shared->layout.u.chunk;
+ idx_info.storage = &dset->shared->layout.storage.u.chunk;
+
+ /* If the dataset is not written, return without errors */
+ if(H5F_addr_defined(idx_info.storage->idx_addr)) {
+ /* Calculate the scaled of this chunk */
+ H5VM_chunk_scaled(dset->shared->ndims, offset, layout->u.chunk.dim, udata.scaled);
+ udata.scaled[dset->shared->ndims] = 0;
+
+ /* Initialize before iteration */
+ udata.ndims = dset->shared->ndims;
+ udata.nbytes = 0;
+ udata.filter_mask = 0;
+ udata.chunk_addr = HADDR_UNDEF;
+ udata.found = FALSE;
+
+ /* Iterate over the allocated chunks to find the requested chunk */
+ if((dset->shared->layout.storage.u.chunk.ops->iterate)(&idx_info, H5D__get_chunk_info_by_coord_cb, &udata) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to retrieve information of the chunk by its scaled coordinates")
+
+ /* Obtain requested info if the chunk is found */
+ if (udata.found) {
+ if(filter_mask)
+ *filter_mask = udata.filter_mask;
+ if(addr)
+ *addr = udata.chunk_addr;
+ if(size)
+ *size = udata.nbytes;
+ }
+ } /* end if H5F_addr_defined */
+
+done:
+ FUNC_LEAVE_NOAPI_TAG(ret_value)
+} /* end H5D__get_chunk_info_by_coord() */
+
diff --git a/src/H5Dcompact.c b/src/H5Dcompact.c
index c0c2a80..edad3c5 100644
--- a/src/H5Dcompact.c
+++ b/src/H5Dcompact.c
@@ -80,6 +80,7 @@ const H5D_layout_ops_t H5D_LOPS_COMPACT[1] = {{
H5D__compact_construct,
NULL,
H5D__compact_is_space_alloc,
+ NULL,
H5D__compact_io_init,
H5D__contig_read,
H5D__contig_write,
@@ -528,7 +529,7 @@ H5D__compact_copy(H5F_t *f_src, H5O_storage_compact_t *_storage_src, H5F_t *f_ds
if(NULL == (buf = H5FL_BLK_MALLOC(type_conv, buf_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
- HDmemcpy(buf, storage_src->buf, storage_src->size);
+ H5MM_memcpy(buf, storage_src->buf, storage_src->size);
/* allocate temporary bkg buff for data conversion */
if(NULL == (bkg = H5FL_BLK_MALLOC(type_conv, buf_size)))
@@ -539,7 +540,7 @@ H5D__compact_copy(H5F_t *f_src, H5O_storage_compact_t *_storage_src, H5F_t *f_ds
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "datatype conversion failed")
/* Copy into another buffer, to reclaim memory later */
- HDmemcpy(reclaim_buf, buf, buf_size);
+ H5MM_memcpy(reclaim_buf, buf, buf_size);
/* Set background buffer to all zeros */
HDmemset(bkg, 0, buf_size);
@@ -548,23 +549,18 @@ H5D__compact_copy(H5F_t *f_src, H5O_storage_compact_t *_storage_src, H5F_t *f_ds
if(H5T_convert(tpath_mem_dst, tid_mem, tid_dst, nelmts, (size_t)0, (size_t)0, buf, bkg) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "datatype conversion failed")
- HDmemcpy(storage_dst->buf, buf, storage_dst->size);
+ H5MM_memcpy(storage_dst->buf, buf, storage_dst->size);
- if(H5D_vlen_reclaim(tid_mem, buf_space, reclaim_buf) < 0)
+ if(H5T_reclaim(tid_mem, buf_space, reclaim_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_BADITER, FAIL, "unable to reclaim variable-length data")
} /* end if */
else if(H5T_get_class(dt_src, FALSE) == H5T_REFERENCE) {
if(f_src != f_dst) {
/* Check for expanding references */
if(cpy_info->expand_ref) {
- size_t ref_count;
-
- /* Determine # of reference elements to copy */
- ref_count = storage_src->size / H5T_get_size(dt_src);
-
/* Copy objects referenced in source buffer to destination file and set destination elements */
- if(H5O_copy_expand_ref(f_src, storage_src->buf, f_dst,
- storage_dst->buf, ref_count, H5T_get_ref_type(dt_src), cpy_info) < 0)
+ if (H5O_copy_expand_ref(f_src, tid_src, dt_src, storage_src->buf,
+ storage_src->size, f_dst, storage_dst->buf, cpy_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "unable to copy reference attribute")
} /* end if */
else
@@ -573,11 +569,11 @@ H5D__compact_copy(H5F_t *f_src, H5O_storage_compact_t *_storage_src, H5F_t *f_ds
} /* end if */
else
/* Type conversion not necessary */
- HDmemcpy(storage_dst->buf, storage_src->buf, storage_src->size);
+ H5MM_memcpy(storage_dst->buf, storage_src->buf, storage_src->size);
} /* end if */
else
/* Type conversion not necessary */
- HDmemcpy(storage_dst->buf, storage_src->buf, storage_src->size);
+ H5MM_memcpy(storage_dst->buf, storage_src->buf, storage_src->size);
/* Mark destination buffer as dirty */
storage_dst->dirty = TRUE;
diff --git a/src/H5Dcontig.c b/src/H5Dcontig.c
index ad12ba0..0be7364 100644
--- a/src/H5Dcontig.c
+++ b/src/H5Dcontig.c
@@ -40,6 +40,7 @@
#include "H5FLprivate.h" /* Free Lists */
#include "H5Iprivate.h" /* IDs */
#include "H5MFprivate.h" /* File memory management */
+#include "H5MMprivate.h" /* Memory management */
#include "H5FOprivate.h" /* File objects */
#include "H5Oprivate.h" /* Object headers */
#include "H5Pprivate.h" /* Property lists */
@@ -57,7 +58,7 @@
/* Callback info for sieve buffer readvv operation */
typedef struct H5D_contig_readvv_sieve_ud_t {
- H5F_t *file; /* File for dataset */
+ H5F_shared_t *f_sh; /* Shared file for dataset */
H5D_rdcdc_t *dset_contig; /* Cached information about contiguous data */
const H5D_contig_storage_t *store_contig; /* Contiguous storage info for this I/O operation */
unsigned char *rbuf; /* Pointer to buffer to fill */
@@ -65,14 +66,14 @@ typedef struct H5D_contig_readvv_sieve_ud_t {
/* Callback info for [plain] readvv operation */
typedef struct H5D_contig_readvv_ud_t {
- H5F_t *file; /* File for dataset */
+ H5F_shared_t *f_sh; /* Shared file for dataset */
haddr_t dset_addr; /* Address of dataset */
unsigned char *rbuf; /* Pointer to buffer to fill */
} H5D_contig_readvv_ud_t;
/* Callback info for sieve buffer writevv operation */
typedef struct H5D_contig_writevv_sieve_ud_t {
- H5F_t *file; /* File for dataset */
+ H5F_shared_t *f_sh; /* Shared file for dataset */
H5D_rdcdc_t *dset_contig; /* Cached information about contiguous data */
const H5D_contig_storage_t *store_contig; /* Contiguous storage info for this I/O operation */
const unsigned char *wbuf; /* Pointer to buffer to write */
@@ -80,7 +81,7 @@ typedef struct H5D_contig_writevv_sieve_ud_t {
/* Callback info for [plain] writevv operation */
typedef struct H5D_contig_writevv_ud_t {
- H5F_t *file; /* File for dataset */
+ H5F_shared_t *f_sh; /* Shared file for dataset */
haddr_t dset_addr; /* Address of dataset */
const unsigned char *wbuf; /* Pointer to buffer to write */
} H5D_contig_writevv_ud_t;
@@ -118,6 +119,7 @@ const H5D_layout_ops_t H5D_LOPS_CONTIG[1] = {{
H5D__contig_construct,
H5D__contig_init,
H5D__contig_is_space_alloc,
+ H5D__contig_is_data_cached,
H5D__contig_io_init,
H5D__contig_read,
H5D__contig_write,
@@ -538,6 +540,30 @@ H5D__contig_is_space_alloc(const H5O_storage_t *storage)
/*-------------------------------------------------------------------------
+ * Function: H5D__contig_is_data_cached
+ *
+ * Purpose: Query if raw data is cached for dataset
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * Wednessday, March 6, 2016
+ *
+ *-------------------------------------------------------------------------
+ */
+hbool_t
+H5D__contig_is_data_cached(const H5D_shared_t *shared_dset)
+{
+ FUNC_ENTER_PACKAGE_NOERR
+
+ /* Sanity checks */
+ HDassert(shared_dset);
+
+ FUNC_LEAVE_NOAPI(shared_dset->cache.contig.sieve_size > 0)
+} /* end H5D__contig_is_data_cached() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5D__contig_io_init
*
* Purpose: Performs initialization before any sort of I/O on the raw data
@@ -692,7 +718,7 @@ H5D__contig_readvv_sieve_cb(hsize_t dst_off, hsize_t src_off, size_t len,
void *_udata)
{
H5D_contig_readvv_sieve_ud_t *udata = (H5D_contig_readvv_sieve_ud_t *)_udata; /* User data for H5VM_opvv() operator */
- H5F_t *file = udata->file; /* File for dataset */
+ H5F_shared_t *f_sh = udata->f_sh; /* Shared file for dataset */
H5D_rdcdc_t *dset_contig = udata->dset_contig; /* Cached information about contiguous data */
const H5D_contig_storage_t *store_contig = udata->store_contig; /* Contiguous storage info for this I/O operation */
unsigned char *buf; /* Pointer to buffer to fill */
@@ -724,7 +750,7 @@ H5D__contig_readvv_sieve_cb(hsize_t dst_off, hsize_t src_off, size_t len,
if(NULL == dset_contig->sieve_buf) {
/* Check if we can actually hold the I/O request in the sieve buffer */
if(len > dset_contig->sieve_buf_size) {
- if(H5F_block_read(file, H5FD_MEM_DRAW, addr, len, buf) < 0)
+ if(H5F_shared_block_read(f_sh, H5FD_MEM_DRAW, addr, len, buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "block read failed")
} /* end if */
else {
@@ -736,7 +762,7 @@ H5D__contig_readvv_sieve_cb(hsize_t dst_off, hsize_t src_off, size_t len,
dset_contig->sieve_loc = addr;
/* Make certain we don't read off the end of the file */
- if(HADDR_UNDEF == (rel_eoa = H5F_get_eoa(file, H5FD_MEM_DRAW)))
+ if(HADDR_UNDEF == (rel_eoa = H5F_shared_get_eoa(f_sh, H5FD_MEM_DRAW)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to determine file size")
/* Set up the buffer parameters */
@@ -747,19 +773,14 @@ H5D__contig_readvv_sieve_cb(hsize_t dst_off, hsize_t src_off, size_t len,
H5_CHECKED_ASSIGN(dset_contig->sieve_size, size_t, min, hsize_t);
/* Read the new sieve buffer */
- if(H5F_block_read(file, H5FD_MEM_DRAW, dset_contig->sieve_loc, dset_contig->sieve_size, dset_contig->sieve_buf) < 0)
+ if(H5F_shared_block_read(f_sh, H5FD_MEM_DRAW, dset_contig->sieve_loc, dset_contig->sieve_size, dset_contig->sieve_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "block read failed")
/* Grab the data out of the buffer (must be first piece of data in buffer ) */
- HDmemcpy(buf, dset_contig->sieve_buf, len);
+ H5MM_memcpy(buf, dset_contig->sieve_buf, len);
/* Reset sieve buffer dirty flag */
dset_contig->sieve_dirty = FALSE;
-
- /* Stash local copies of these value */
- sieve_start = dset_contig->sieve_loc;
- sieve_size = dset_contig->sieve_size;
- sieve_end = sieve_start+sieve_size;
} /* end else */
} /* end if */
else {
@@ -771,7 +792,7 @@ H5D__contig_readvv_sieve_cb(hsize_t dst_off, hsize_t src_off, size_t len,
unsigned char *base_sieve_buf = dset_contig->sieve_buf + (addr - sieve_start);
/* Grab the data out of the buffer */
- HDmemcpy(buf, base_sieve_buf, len);
+ H5MM_memcpy(buf, base_sieve_buf, len);
} /* end if */
/* Entire request is not within this data sieve buffer */
else {
@@ -783,7 +804,7 @@ H5D__contig_readvv_sieve_cb(hsize_t dst_off, hsize_t src_off, size_t len,
/* Flush the sieve buffer, if it's dirty */
if(dset_contig->sieve_dirty) {
/* Write to file */
- if(H5F_block_write(file, H5FD_MEM_DRAW, sieve_start, sieve_size, dset_contig->sieve_buf) < 0)
+ if(H5F_shared_block_write(f_sh, H5FD_MEM_DRAW, sieve_start, sieve_size, dset_contig->sieve_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "block write failed")
/* Reset sieve buffer dirty flag */
@@ -792,7 +813,7 @@ H5D__contig_readvv_sieve_cb(hsize_t dst_off, hsize_t src_off, size_t len,
} /* end if */
/* Read directly into the user's buffer */
- if(H5F_block_read(file, H5FD_MEM_DRAW, addr, len, buf) < 0)
+ if(H5F_shared_block_read(f_sh, H5FD_MEM_DRAW, addr, len, buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "block read failed")
} /* end if */
/* Element size fits within the buffer size */
@@ -800,7 +821,7 @@ H5D__contig_readvv_sieve_cb(hsize_t dst_off, hsize_t src_off, size_t len,
/* Flush the sieve buffer if it's dirty */
if(dset_contig->sieve_dirty) {
/* Write to file */
- if(H5F_block_write(file, H5FD_MEM_DRAW, sieve_start, sieve_size, dset_contig->sieve_buf) < 0)
+ if(H5F_shared_block_write(f_sh, H5FD_MEM_DRAW, sieve_start, sieve_size, dset_contig->sieve_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "block write failed")
/* Reset sieve buffer dirty flag */
@@ -811,7 +832,7 @@ H5D__contig_readvv_sieve_cb(hsize_t dst_off, hsize_t src_off, size_t len,
dset_contig->sieve_loc = addr;
/* Make certain we don't read off the end of the file */
- if(HADDR_UNDEF == (rel_eoa = H5F_get_eoa(file, H5FD_MEM_DRAW)))
+ if(HADDR_UNDEF == (rel_eoa = H5F_shared_get_eoa(f_sh, H5FD_MEM_DRAW)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to determine file size")
/* Only need this when resizing sieve buffer */
@@ -825,17 +846,12 @@ H5D__contig_readvv_sieve_cb(hsize_t dst_off, hsize_t src_off, size_t len,
min = MIN3(rel_eoa - dset_contig->sieve_loc, max_data, dset_contig->sieve_buf_size);
H5_CHECKED_ASSIGN(dset_contig->sieve_size, size_t, min, hsize_t);
- /* Update local copies of sieve information */
- sieve_start = dset_contig->sieve_loc;
- sieve_size = dset_contig->sieve_size;
- sieve_end = sieve_start + sieve_size;
-
/* Read the new sieve buffer */
- if(H5F_block_read(file, H5FD_MEM_DRAW, dset_contig->sieve_loc, dset_contig->sieve_size, dset_contig->sieve_buf) < 0)
+ if(H5F_shared_block_read(f_sh, H5FD_MEM_DRAW, dset_contig->sieve_loc, dset_contig->sieve_size, dset_contig->sieve_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "block read failed")
/* Grab the data out of the buffer (must be first piece of data in buffer ) */
- HDmemcpy(buf, dset_contig->sieve_buf, len);
+ H5MM_memcpy(buf, dset_contig->sieve_buf, len);
/* Reset sieve buffer dirty flag */
dset_contig->sieve_dirty = FALSE;
@@ -869,7 +885,7 @@ H5D__contig_readvv_cb(hsize_t dst_off, hsize_t src_off, size_t len, void *_udata
FUNC_ENTER_STATIC
/* Write data */
- if(H5F_block_read(udata->file, H5FD_MEM_DRAW, (udata->dset_addr + dst_off),
+ if(H5F_shared_block_read(udata->f_sh, H5FD_MEM_DRAW, (udata->dset_addr + dst_off),
len, (udata->rbuf + src_off)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "block write failed")
@@ -915,11 +931,11 @@ H5D__contig_readvv(const H5D_io_info_t *io_info,
HDassert(mem_off_arr);
/* Check if data sieving is enabled */
- if(H5F_HAS_FEATURE(io_info->dset->oloc.file, H5FD_FEAT_DATA_SIEVE)) {
+ if(H5F_SHARED_HAS_FEATURE(io_info->f_sh, H5FD_FEAT_DATA_SIEVE)) {
H5D_contig_readvv_sieve_ud_t udata; /* User data for H5VM_opvv() operator */
/* Set up user data for H5VM_opvv() */
- udata.file = io_info->dset->oloc.file;
+ 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;
@@ -934,7 +950,7 @@ H5D__contig_readvv(const H5D_io_info_t *io_info,
H5D_contig_readvv_ud_t udata; /* User data for H5VM_opvv() operator */
/* Set up user data for H5VM_opvv() */
- udata.file = io_info->dset->oloc.file;
+ udata.f_sh = io_info->f_sh;
udata.dset_addr = io_info->store->contig.dset_addr;
udata.rbuf = (unsigned char *)io_info->u.rbuf;
@@ -967,7 +983,7 @@ H5D__contig_writevv_sieve_cb(hsize_t dst_off, hsize_t src_off, size_t len,
void *_udata)
{
H5D_contig_writevv_sieve_ud_t *udata = (H5D_contig_writevv_sieve_ud_t *)_udata; /* User data for H5VM_opvv() operator */
- H5F_t *file = udata->file; /* File for dataset */
+ H5F_shared_t *f_sh = udata->f_sh; /* Shared file for dataset */
H5D_rdcdc_t *dset_contig = udata->dset_contig; /* Cached information about contiguous data */
const H5D_contig_storage_t *store_contig = udata->store_contig; /* Contiguous storage info for this I/O operation */
const unsigned char *buf; /* Pointer to buffer to fill */
@@ -999,7 +1015,7 @@ H5D__contig_writevv_sieve_cb(hsize_t dst_off, hsize_t src_off, size_t len,
if(NULL == dset_contig->sieve_buf) {
/* Check if we can actually hold the I/O request in the sieve buffer */
if(len > dset_contig->sieve_buf_size) {
- if(H5F_block_write(file, H5FD_MEM_DRAW, addr, len, buf) < 0)
+ if(H5F_shared_block_write(f_sh, H5FD_MEM_DRAW, addr, len, buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "block write failed")
} /* end if */
else {
@@ -1015,7 +1031,7 @@ H5D__contig_writevv_sieve_cb(hsize_t dst_off, hsize_t src_off, size_t len,
dset_contig->sieve_loc = addr;
/* Make certain we don't read off the end of the file */
- if(HADDR_UNDEF == (rel_eoa = H5F_get_eoa(file, H5FD_MEM_DRAW)))
+ if(HADDR_UNDEF == (rel_eoa = H5F_shared_get_eoa(f_sh, H5FD_MEM_DRAW)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to determine file size")
/* Set up the buffer parameters */
@@ -1028,12 +1044,12 @@ H5D__contig_writevv_sieve_cb(hsize_t dst_off, hsize_t src_off, size_t len,
/* Check if there is any point in reading the data from the file */
if(dset_contig->sieve_size > len) {
/* Read the new sieve buffer */
- if(H5F_block_read(file, H5FD_MEM_DRAW, dset_contig->sieve_loc, dset_contig->sieve_size, dset_contig->sieve_buf) < 0)
+ if(H5F_shared_block_read(f_sh, H5FD_MEM_DRAW, dset_contig->sieve_loc, dset_contig->sieve_size, dset_contig->sieve_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "block read failed")
} /* end if */
/* Grab the data out of the buffer (must be first piece of data in buffer ) */
- HDmemcpy(dset_contig->sieve_buf, buf, len);
+ H5MM_memcpy(dset_contig->sieve_buf, buf, len);
/* Set sieve buffer dirty flag */
dset_contig->sieve_dirty = TRUE;
@@ -1053,7 +1069,7 @@ H5D__contig_writevv_sieve_cb(hsize_t dst_off, hsize_t src_off, size_t len,
unsigned char *base_sieve_buf = dset_contig->sieve_buf + (addr - sieve_start);
/* Put the data into the sieve buffer */
- HDmemcpy(base_sieve_buf, buf, len);
+ H5MM_memcpy(base_sieve_buf, buf, len);
/* Set sieve buffer dirty flag */
dset_contig->sieve_dirty = TRUE;
@@ -1068,7 +1084,7 @@ H5D__contig_writevv_sieve_cb(hsize_t dst_off, hsize_t src_off, size_t len,
/* Flush the sieve buffer, if it's dirty */
if(dset_contig->sieve_dirty) {
/* Write to file */
- if(H5F_block_write(file, H5FD_MEM_DRAW, sieve_start, sieve_size, dset_contig->sieve_buf) < 0)
+ if(H5F_shared_block_write(f_sh, H5FD_MEM_DRAW, sieve_start, sieve_size, dset_contig->sieve_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "block write failed")
/* Reset sieve buffer dirty flag */
@@ -1081,7 +1097,7 @@ H5D__contig_writevv_sieve_cb(hsize_t dst_off, hsize_t src_off, size_t len,
} /* end if */
/* Write directly from the user's buffer */
- if(H5F_block_write(file, H5FD_MEM_DRAW, addr, len, buf) < 0)
+ if(H5F_shared_block_write(f_sh, H5FD_MEM_DRAW, addr, len, buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "block write failed")
} /* end if */
/* Element size fits within the buffer size */
@@ -1096,7 +1112,7 @@ H5D__contig_writevv_sieve_cb(hsize_t dst_off, hsize_t src_off, size_t len,
HDmemmove(dset_contig->sieve_buf + len, dset_contig->sieve_buf, dset_contig->sieve_size);
/* Copy in new information (must be first in sieve buffer) */
- HDmemcpy(dset_contig->sieve_buf, buf, len);
+ H5MM_memcpy(dset_contig->sieve_buf, buf, len);
/* Adjust sieve location */
dset_contig->sieve_loc = addr;
@@ -1105,23 +1121,18 @@ H5D__contig_writevv_sieve_cb(hsize_t dst_off, hsize_t src_off, size_t len,
/* Append to existing sieve buffer */
else {
/* Copy in new information */
- HDmemcpy(dset_contig->sieve_buf + sieve_size, buf, len);
+ H5MM_memcpy(dset_contig->sieve_buf + sieve_size, buf, len);
} /* end else */
/* Adjust sieve size */
dset_contig->sieve_size += len;
-
- /* Update local copies of sieve information */
- sieve_start = dset_contig->sieve_loc;
- sieve_size = dset_contig->sieve_size;
- sieve_end = sieve_start + sieve_size;
} /* end if */
/* Can't add the new data onto the existing sieve buffer */
else {
/* Flush the sieve buffer if it's dirty */
if(dset_contig->sieve_dirty) {
/* Write to file */
- if(H5F_block_write(file, H5FD_MEM_DRAW, sieve_start, sieve_size, dset_contig->sieve_buf) < 0)
+ if(H5F_shared_block_write(f_sh, H5FD_MEM_DRAW, sieve_start, sieve_size, dset_contig->sieve_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "block write failed")
/* Reset sieve buffer dirty flag */
@@ -1132,7 +1143,7 @@ H5D__contig_writevv_sieve_cb(hsize_t dst_off, hsize_t src_off, size_t len,
dset_contig->sieve_loc = addr;
/* Make certain we don't read off the end of the file */
- if(HADDR_UNDEF == (rel_eoa = H5F_get_eoa(file, H5FD_MEM_DRAW)))
+ if(HADDR_UNDEF == (rel_eoa = H5F_shared_get_eoa(f_sh, H5FD_MEM_DRAW)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to determine file size")
/* Only need this when resizing sieve buffer */
@@ -1146,20 +1157,15 @@ H5D__contig_writevv_sieve_cb(hsize_t dst_off, hsize_t src_off, size_t len,
min = MIN3(rel_eoa - dset_contig->sieve_loc, max_data, dset_contig->sieve_buf_size);
H5_CHECKED_ASSIGN(dset_contig->sieve_size, size_t, min, hsize_t);
- /* Update local copies of sieve information */
- sieve_start = dset_contig->sieve_loc;
- sieve_size = dset_contig->sieve_size;
- sieve_end = sieve_start + sieve_size;
-
/* Check if there is any point in reading the data from the file */
if(dset_contig->sieve_size > len) {
/* Read the new sieve buffer */
- if(H5F_block_read(file, H5FD_MEM_DRAW, dset_contig->sieve_loc, dset_contig->sieve_size, dset_contig->sieve_buf) < 0)
+ if(H5F_shared_block_read(f_sh, H5FD_MEM_DRAW, dset_contig->sieve_loc, dset_contig->sieve_size, dset_contig->sieve_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "block read failed")
} /* end if */
/* Grab the data out of the buffer (must be first piece of data in buffer ) */
- HDmemcpy(dset_contig->sieve_buf, buf, len);
+ H5MM_memcpy(dset_contig->sieve_buf, buf, len);
/* Set sieve buffer dirty flag */
dset_contig->sieve_dirty = TRUE;
@@ -1194,7 +1200,7 @@ H5D__contig_writevv_cb(hsize_t dst_off, hsize_t src_off, size_t len, void *_udat
FUNC_ENTER_STATIC
/* Write data */
- if(H5F_block_write(udata->file, H5FD_MEM_DRAW, (udata->dset_addr + dst_off), len, (udata->wbuf + src_off)) < 0)
+ if(H5F_shared_block_write(udata->f_sh, H5FD_MEM_DRAW, (udata->dset_addr + dst_off), len, (udata->wbuf + src_off)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "block write failed")
done:
@@ -1239,11 +1245,11 @@ H5D__contig_writevv(const H5D_io_info_t *io_info,
HDassert(mem_off_arr);
/* Check if data sieving is enabled */
- if(H5F_HAS_FEATURE(io_info->dset->oloc.file, H5FD_FEAT_DATA_SIEVE)) {
+ if(H5F_SHARED_HAS_FEATURE(io_info->f_sh, H5FD_FEAT_DATA_SIEVE)) {
H5D_contig_writevv_sieve_ud_t udata; /* User data for H5VM_opvv() operator */
/* Set up user data for H5VM_opvv() */
- udata.file = io_info->dset->oloc.file;
+ 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;
@@ -1258,7 +1264,7 @@ H5D__contig_writevv(const H5D_io_info_t *io_info,
H5D_contig_writevv_ud_t udata; /* User data for H5VM_opvv() operator */
/* Set up user data for H5VM_opvv() */
- udata.file = io_info->dset->oloc.file;
+ 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;
@@ -1514,7 +1520,7 @@ H5D__contig_copy(H5F_t *f_src, const H5O_storage_contig_t *storage_src,
if(try_sieve && (addr_src >= sieve_start) && ((addr_src + src_nbytes -1) < sieve_end)) {
unsigned char *base_sieve_buf = shared_fo->cache.contig.sieve_buf + (addr_src - sieve_start);
- HDmemcpy(buf, base_sieve_buf, src_nbytes);
+ H5MM_memcpy(buf, base_sieve_buf, src_nbytes);
} else
/* Read raw data from source file */
if(H5F_block_read(f_src, H5FD_MEM_DRAW, addr_src, src_nbytes, buf) < 0)
@@ -1527,7 +1533,7 @@ H5D__contig_copy(H5F_t *f_src, const H5O_storage_contig_t *storage_src,
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "datatype conversion failed")
/* Copy into another buffer, to reclaim memory later */
- HDmemcpy(reclaim_buf, buf, mem_nbytes);
+ H5MM_memcpy(reclaim_buf, buf, mem_nbytes);
/* Set background buffer to all zeros */
HDmemset(bkg, 0, buf_size);
@@ -1537,23 +1543,18 @@ H5D__contig_copy(H5F_t *f_src, const H5O_storage_contig_t *storage_src,
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "datatype conversion failed")
/* Reclaim space from variable length data */
- if(H5D_vlen_reclaim(tid_mem, buf_space, reclaim_buf) < 0)
+ if(H5T_reclaim(tid_mem, buf_space, reclaim_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_BADITER, FAIL, "unable to reclaim variable-length data")
} /* end if */
else if(fix_ref) {
/* Check for expanding references */
if(cpy_info->expand_ref) {
- size_t ref_count;
-
- /* Determine # of reference elements to copy */
- ref_count = src_nbytes / H5T_get_size(dt_src);
-
/* Copy the reference elements */
- if(H5O_copy_expand_ref(f_src, buf, f_dst, bkg, ref_count, H5T_get_ref_type(dt_src), cpy_info) < 0)
+ if(H5O_copy_expand_ref(f_src, tid_src, dt_src, buf, buf_size, f_dst, bkg, cpy_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "unable to copy reference attribute")
/* After fix ref, copy the new reference elements to the buffer to write out */
- HDmemcpy(buf, bkg, buf_size);
+ H5MM_memcpy(buf, bkg, buf_size);
} /* end if */
else
/* Reset value to zero */
diff --git a/src/H5Ddbg.c b/src/H5Ddbg.c
index 7220868..d11a5d8 100644
--- a/src/H5Ddbg.c
+++ b/src/H5Ddbg.c
@@ -26,6 +26,7 @@
#include "H5Dpkg.h" /* Datasets */
#include "H5Eprivate.h" /* Error handling */
#include "H5Iprivate.h" /* IDs */
+#include "H5VLprivate.h" /* Virtual Object Layer */
/****************/
@@ -79,7 +80,7 @@ H5Ddebug(hid_t dset_id)
H5TRACE1("e", "i", dset_id);
/* Check args */
- if(NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
+ if(NULL == (dset = (H5D_t *)H5VL_object_verify(dset_id, H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset")
/* Print B-tree information */
diff --git a/src/H5Ddeprec.c b/src/H5Ddeprec.c
index ed520c4..f321c82 100644
--- a/src/H5Ddeprec.c
+++ b/src/H5Ddeprec.c
@@ -40,6 +40,7 @@
#include "H5Dpkg.h" /* Datasets */
#include "H5Eprivate.h" /* Error handling */
#include "H5Iprivate.h" /* IDs */
+#include "H5VLprivate.h" /* Virtual Object Layer */
/****************/
@@ -112,9 +113,10 @@ hid_t
H5Dcreate1(hid_t loc_id, const char *name, hid_t type_id, hid_t space_id,
hid_t dcpl_id)
{
- H5G_loc_t loc; /* Object location to insert dataset into */
- H5D_t *dset = NULL; /* New dataset's info */
- const H5S_t *space; /* Dataspace for dataset */
+ void *dset = NULL; /* dset token from VOL connector */
+ H5VL_object_t *vol_obj = NULL; /* object token of loc_id */
+ H5VL_loc_params_t loc_params;
+ hid_t lcpl_id = H5P_LINK_CREATE_DEFAULT;
hid_t dapl_id = H5P_DEFAULT; /* DAPL used by library */
hid_t ret_value = H5I_INVALID_HID; /* Return value */
@@ -126,33 +128,39 @@ H5Dcreate1(hid_t loc_id, const char *name, hid_t type_id, hid_t space_id,
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "name parameter cannot be NULL")
if(!*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "name parameter cannot be an empty string")
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a location ID")
- if(H5I_DATATYPE != H5I_get_type(type_id))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a datatype ID")
- if(NULL == (space = (const H5S_t *)H5I_object_verify(space_id,H5I_DATASPACE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a dataspace ID")
+
if(H5P_DEFAULT == dcpl_id)
dcpl_id = H5P_DATASET_CREATE_DEFAULT;
else
if(TRUE != H5P_isa_class(dcpl_id, H5P_DATASET_CREATE))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not dataset create property list ID")
+ /* Set the DCPL for the API context */
+ H5CX_set_dcpl(dcpl_id);
+
/* Verify access property list and set up collective metadata if appropriate */
if(H5CX_set_apl(&dapl_id, H5P_CLS_DACC, loc_id, TRUE) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info")
- /* Build and open the new dataset */
- if(NULL == (dset = H5D__create_named(&loc, name, type_id, space, H5P_LINK_CREATE_DEFAULT, dcpl_id, dapl_id)))
+ /* Set location parameters */
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* get the location object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier")
+
+ /* Create the dataset through the VOL */
+ if(NULL == (dset = H5VL_dataset_create(vol_obj, &loc_params, name, lcpl_id, type_id, space_id, dcpl_id, H5P_DATASET_ACCESS_DEFAULT, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, H5I_INVALID_HID, "unable to create dataset")
/* Get an atom for the dataset */
- if((ret_value = H5I_register(H5I_DATASET, dset, TRUE)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register dataset")
+ if((ret_value = H5VL_register(H5I_DATASET, dset, vol_obj->connector, TRUE)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register dataset")
done:
if (H5I_INVALID_HID == ret_value)
- if(dset && H5D_close(dset) < 0)
+ if(dset && H5VL_dataset_close(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, H5I_INVALID_HID, "unable to release dataset")
FUNC_LEAVE_API(ret_value)
@@ -179,8 +187,9 @@ done:
hid_t
H5Dopen1(hid_t loc_id, const char *name)
{
- H5D_t *dset = NULL;
- H5G_loc_t loc; /* Object location of group */
+ void *dset = NULL; /* dset token from VOL connector */
+ H5VL_object_t *vol_obj = NULL; /* object token of loc_id */
+ H5VL_loc_params_t loc_params;
hid_t ret_value = H5I_INVALID_HID; /* Return value */
FUNC_ENTER_API(H5I_INVALID_HID)
@@ -191,20 +200,26 @@ H5Dopen1(hid_t loc_id, const char *name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "name parameter cannot be NULL")
if (!*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "name parameter cannot be an empty string")
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a location")
+
+ /* Set location parameters */
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* get the location object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier")
/* Open the dataset */
- if(NULL == (dset = H5D__open_name(&loc, name, H5P_DATASET_ACCESS_DEFAULT)))
+ if(NULL == (dset = H5VL_dataset_open(vol_obj, &loc_params, name, H5P_DATASET_ACCESS_DEFAULT, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open dataset")
/* Get an atom for the dataset */
- if((ret_value = H5I_register(H5I_DATASET, dset, TRUE)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "can't register dataset atom")
+ if((ret_value = H5VL_register(H5I_DATASET, dset, vol_obj->connector, TRUE)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, H5I_INVALID_HID, "can't register dataset atom")
done:
if(H5I_INVALID_HID == ret_value)
- if(dset && H5D_close(dset) < 0)
+ if(dset && H5VL_dataset_close(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, H5I_INVALID_HID, "unable to release dataset")
FUNC_LEAVE_API(ret_value)
@@ -230,38 +245,113 @@ done:
herr_t
H5Dextend(hid_t dset_id, const hsize_t size[])
{
- H5D_t *dset; /* Pointer to dataset to modify */
- hsize_t dset_dims[H5S_MAX_RANK]; /* Current dataset dimensions */
- unsigned u; /* Local index variable */
- herr_t ret_value = SUCCEED; /* Return value */
+ H5VL_object_t *vol_obj = NULL; /* Dataset structure */
+ hid_t sid = H5I_INVALID_HID; /* Dataspace ID */
+ H5S_t *ds = NULL; /* Dataspace struct */
+ int ndims; /* Dataset/space rank */
+ hsize_t dset_dims[H5S_MAX_RANK]; /* Current dataset dimensions */
+ int i; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE2("e", "i*h", dset_id, size);
/* Check args */
- if(NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset")
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(dset_id, H5I_DATASET)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid dataset identifier")
if(!size)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no size specified")
- /* Make certain that the dataset dimensions don't decrease */
- /* (Shrinking dimensions is possible with H5Dset_extent, but not H5Dextend) */
- if(H5S_get_simple_extent_dims(dset->shared->space, dset_dims, NULL) < 0)
+ /* Get the dataspace pointer for the dataset */
+ if(H5VL_dataset_get(vol_obj, H5VL_DATASET_GET_SPACE, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &sid) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to get dataspace")
+ if(H5I_INVALID_HID == sid)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "received an invalid dataspace from the dataset")
+ if(NULL == (ds = (H5S_t *)H5I_object_verify(sid, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "couldn't get dataspace structure from ID")
+
+ /* Get the dataset's current extent */
+ if(H5S_get_simple_extent_dims(ds, dset_dims, NULL) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get dataset dimensions")
- for(u = 0; u < dset->shared->ndims; u++)
- if(size[u] > dset_dims[u])
- dset_dims[u] = size[u];
+
+ /* Get the dataset dimensions */
+ ndims = H5S_GET_EXTENT_NDIMS(ds);
+
+ /* Make certain that the dataset dimensions don't decrease in any dimension.
+ *
+ * (Shrinking dimensions is possible with H5Dset_extent, but not H5Dextend)
+ *
+ * XXX (VOL_MERGE): I feel like we should fail here instead of just silently
+ * not doing what we're supposed to do.
+ */
+ for(i = 0; i < ndims; i++)
+ if(size[i] > dset_dims[i])
+ dset_dims[i] = size[i];
/* Set up collective metadata if appropriate */
if(H5CX_set_loc(dset_id) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set collective metadata read info")
/* Increase size */
- if(H5D__set_extent(dset, dset_dims) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to extend dataset")
+ if ((ret_value = H5VL_dataset_specific(vol_obj, H5VL_DATASET_SET_EXTENT, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, dset_dims)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to extend dataset")
done:
+ /* Close the dataspace */
+ if(sid != H5I_INVALID_HID && H5I_dec_app_ref(sid) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "can't close dataspace")
+
FUNC_LEAVE_API(ret_value)
} /* end H5Dextend() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5Dvlen_reclaim
+ *
+ * Purpose: Frees the buffers allocated for storing variable-length data
+ * in memory. Only frees the VL data in the selection defined in the
+ * dataspace. The dataset transfer property list is required to find the
+ * correct allocation/free methods for the VL data in the buffer.
+ *
+ * Return: Non-negative on success, negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, June 10, 1999
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Dvlen_reclaim(hid_t type_id, hid_t space_id, hid_t dxpl_id, void *buf)
+{
+ H5S_t *space; /* Dataspace for iteration */
+ herr_t ret_value; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE4("e", "iii*x", type_id, space_id, dxpl_id, buf);
+
+ /* Check args */
+ if(H5I_DATATYPE != H5I_get_type(type_id) || buf == NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid argument")
+ if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid dataspace")
+ if(!(H5S_has_extent(space)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dataspace does not have extent set")
+
+ /* Get the default dataset transfer property list if the user didn't provide one */
+ if(H5P_DEFAULT == dxpl_id)
+ dxpl_id = H5P_DATASET_XFER_DEFAULT;
+ else
+ if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms")
+
+ /* Set DXPL for operation */
+ H5CX_set_dxpl(dxpl_id);
+
+ /* Call internal routine */
+ ret_value = H5T_reclaim(type_id, space, buf);
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Dvlen_reclaim() */
+
#endif /* H5_NO_DEPRECATED_SYMBOLS */
diff --git a/src/H5Dearray.c b/src/H5Dearray.c
index a20145a..b23ac46 100644
--- a/src/H5Dearray.c
+++ b/src/H5Dearray.c
@@ -37,6 +37,7 @@
#include "H5EAprivate.h" /* Extensible arrays */
#include "H5FLprivate.h" /* Free Lists */
#include "H5MFprivate.h" /* File space management */
+#include "H5MMprivate.h" /* Memory management */
#include "H5VMprivate.h" /* Vector functions */
@@ -437,7 +438,7 @@ H5D__earray_debug(FILE *stream, int indent, int fwidth, hsize_t idx,
HDassert(elmt);
/* Print element */
- sprintf(temp_str, "Element #%llu:", (unsigned long long)idx);
+ HDsprintf(temp_str, "Element #%llu:", (unsigned long long)idx);
HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth, temp_str,
*(const haddr_t *)elmt);
@@ -596,7 +597,7 @@ H5D__earray_filt_debug(FILE *stream, int indent, int fwidth, hsize_t idx,
HDassert(elmt);
/* Print element */
- sprintf(temp_str, "Element #%llu:", (unsigned long long)idx);
+ HDsprintf(temp_str, "Element #%llu:", (unsigned long long)idx);
HDfprintf(stream, "%*s%-*s {%a, %u, %0x}\n", indent, "", fwidth, temp_str,
elmt->addr, elmt->nbytes, elmt->filter_mask);
@@ -1197,11 +1198,11 @@ H5D__earray_idx_resize(H5O_layout_chunk_t *layout)
hsize_t swizzled_max_chunks[H5O_LAYOUT_NDIMS]; /* Swizzled form of max # of chunks in each dimension */
/* Get the swizzled chunk dimensions */
- HDmemcpy(layout->u.earray.swizzled_dim, layout->dim, (layout->ndims - 1) * sizeof(layout->dim[0]));
+ H5MM_memcpy(layout->u.earray.swizzled_dim, layout->dim, (layout->ndims - 1) * sizeof(layout->dim[0]));
H5VM_swizzle_coords(uint32_t, layout->u.earray.swizzled_dim, layout->u.earray.unlim_dim);
/* Get the swizzled number of chunks in each dimension */
- HDmemcpy(swizzled_chunks, layout->chunks, (layout->ndims - 1) * sizeof(swizzled_chunks[0]));
+ H5MM_memcpy(swizzled_chunks, layout->chunks, (layout->ndims - 1) * sizeof(swizzled_chunks[0]));
H5VM_swizzle_coords(hsize_t, swizzled_chunks, layout->u.earray.unlim_dim);
/* Get the swizzled "down" sizes for each dimension */
@@ -1209,7 +1210,7 @@ H5D__earray_idx_resize(H5O_layout_chunk_t *layout)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't compute swizzled 'down' chunk size value")
/* Get the swizzled max number of chunks in each dimension */
- HDmemcpy(swizzled_max_chunks, layout->max_chunks, (layout->ndims - 1) * sizeof(swizzled_max_chunks[0]));
+ H5MM_memcpy(swizzled_max_chunks, layout->max_chunks, (layout->ndims - 1) * sizeof(swizzled_max_chunks[0]));
H5VM_swizzle_coords(hsize_t, swizzled_max_chunks, layout->u.earray.unlim_dim);
/* Get the swizzled max "down" sizes for each dimension */
diff --git a/src/H5Defl.c b/src/H5Defl.c
index b2f9b29..91caa61 100644
--- a/src/H5Defl.c
+++ b/src/H5Defl.c
@@ -91,6 +91,7 @@ const H5D_layout_ops_t H5D_LOPS_EFL[1] = {{
H5D__efl_construct,
NULL,
H5D__efl_is_space_alloc,
+ NULL,
H5D__efl_io_init,
H5D__contig_read,
H5D__contig_write,
@@ -226,7 +227,7 @@ H5D__efl_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t H5_ATTR_UNU
{
FUNC_ENTER_STATIC_NOERR
- HDmemcpy(&io_info->store->efl, &(io_info->dset->shared->dcpl_cache.efl), sizeof(H5O_efl_t));
+ H5MM_memcpy(&io_info->store->efl, &(io_info->dset->shared->dcpl_cache.efl), sizeof(H5O_efl_t));
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5D__efl_io_init() */
@@ -476,7 +477,6 @@ H5D__efl_readvv(const H5D_io_info_t *io_info,
HDassert(io_info->u.rbuf);
HDassert(io_info->dset);
HDassert(io_info->dset->shared);
- HDassert(io_info->dset->shared->extfile_prefix);
HDassert(dset_curr_seq);
HDassert(dset_len_arr);
HDassert(dset_off_arr);
@@ -560,7 +560,6 @@ H5D__efl_writevv(const H5D_io_info_t *io_info,
HDassert(io_info->u.wbuf);
HDassert(io_info->dset);
HDassert(io_info->dset->shared);
- HDassert(io_info->dset->shared->extfile_prefix);
HDassert(dset_curr_seq);
HDassert(dset_len_arr);
HDassert(dset_off_arr);
diff --git a/src/H5Dfarray.c b/src/H5Dfarray.c
index 372ae26..2d85e3b 100644
--- a/src/H5Dfarray.c
+++ b/src/H5Dfarray.c
@@ -434,7 +434,7 @@ H5D__farray_debug(FILE *stream, int indent, int fwidth, hsize_t idx,
HDassert(elmt);
/* Print element */
- sprintf(temp_str, "Element #%llu:", (unsigned long long)idx);
+ HDsprintf(temp_str, "Element #%llu:", (unsigned long long)idx);
HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth, temp_str,
*(const haddr_t *)elmt);
@@ -699,7 +699,7 @@ H5D__farray_filt_debug(FILE *stream, int indent, int fwidth, hsize_t idx,
HDassert(elmt);
/* Print element */
- sprintf(temp_str, "Element #%llu:", (unsigned long long)idx);
+ HDsprintf(temp_str, "Element #%llu:", (unsigned long long)idx);
HDfprintf(stream, "%*s%-*s {%a, %u, %0x}\n", indent, "", fwidth, temp_str,
elmt->addr, elmt->nbytes, elmt->filter_mask);
diff --git a/src/H5Dfill.c b/src/H5Dfill.c
index 619f699..3ccee90 100644
--- a/src/H5Dfill.c
+++ b/src/H5Dfill.c
@@ -38,6 +38,7 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5FLprivate.h" /* Free Lists */
#include "H5Iprivate.h" /* IDs */
+#include "H5MMprivate.h" /* Memory management */
#include "H5VMprivate.h" /* Vector and array functions */
#include "H5WBprivate.h" /* Wrapped Buffers */
@@ -275,12 +276,12 @@ H5D__fill(const void *fill, const H5T_t *fill_type, void *buf,
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "can't allocate memory selection iterator")
/* Create a selection iterator for scattering the elements to memory buffer */
- if(H5S_select_iter_init(mem_iter, space, dst_type_size) < 0)
+ if(H5S_select_iter_init(mem_iter, space, dst_type_size, 0) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize memory selection information")
mem_iter_init = TRUE;
/* Scatter the data into memory */
- if(H5D__scatter_mem(tmp_buf, space, mem_iter, (size_t)nelmts, buf/*out*/) < 0)
+ if(H5D__scatter_mem(tmp_buf, mem_iter, (size_t)nelmts, buf/*out*/) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "scatter failed")
} /* end if */
else {
@@ -300,7 +301,7 @@ H5D__fill(const void *fill, const H5T_t *fill_type, void *buf,
HGOTO_ERROR(H5E_DATASET, H5E_NOSPACE, FAIL, "can't get actual buffer")
/* Copy the user's data into the buffer for conversion */
- HDmemcpy(elem_ptr, fill, src_type_size);
+ H5MM_memcpy(elem_ptr, fill, src_type_size);
/* If there's no VL type of data, do conversion first then fill the data into
* the memory buffer. */
@@ -577,7 +578,7 @@ H5D__fill_refill_vl(H5D_fill_buf_info_t *fb_info, size_t nelmts)
HDassert(fb_info->fill_buf);
/* Make a copy of the (disk-based) fill value into the buffer */
- HDmemcpy(fb_info->fill_buf, fb_info->fill->buf, fb_info->file_elmt_size);
+ H5MM_memcpy(fb_info->fill_buf, fb_info->fill->buf, fb_info->file_elmt_size);
/* Reset first element of background buffer, if necessary */
if(H5T_path_bkg(fb_info->fill_to_mem_tpath))
@@ -603,7 +604,7 @@ H5D__fill_refill_vl(H5D_fill_buf_info_t *fb_info, size_t nelmts)
if(!buf)
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "memory allocation failed for temporary fill buffer")
- HDmemcpy(buf, fb_info->fill_buf, fb_info->fill_buf_size);
+ H5MM_memcpy(buf, fb_info->fill_buf, fb_info->fill_buf_size);
/* Type convert the dataset buffer, to copy any VL components */
if(H5T_convert(fb_info->mem_to_dset_tpath, fb_info->mem_tid, fb_info->file_tid, nelmts, (size_t)0, (size_t)0, fb_info->fill_buf, fb_info->bkg_buf) < 0)
diff --git a/src/H5Dint.c b/src/H5Dint.c
index 9d15ca6..97ce042 100644
--- a/src/H5Dint.c
+++ b/src/H5Dint.c
@@ -21,15 +21,17 @@
/***********/
/* Headers */
/***********/
-#include "H5private.h" /* Generic Functions */
-#include "H5CXprivate.h" /* API Contexts */
-#include "H5Dpkg.h" /* Datasets */
-#include "H5Eprivate.h" /* Error handling */
-#include "H5FLprivate.h" /* Free Lists */
-#include "H5FOprivate.h" /* File objects */
-#include "H5Iprivate.h" /* IDs */
-#include "H5Lprivate.h" /* Links */
-#include "H5MMprivate.h" /* Memory management */
+#include "H5private.h" /* Generic Functions */
+#include "H5CXprivate.h" /* API Contexts */
+#include "H5Dpkg.h" /* Datasets */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fprivate.h" /* Files */
+#include "H5FLprivate.h" /* Free Lists */
+#include "H5FOprivate.h" /* File objects */
+#include "H5Iprivate.h" /* IDs */
+#include "H5Lprivate.h" /* Links */
+#include "H5MMprivate.h" /* Memory management */
+#include "H5VLprivate.h" /* Virtual Object Layer */
/****************/
@@ -52,12 +54,15 @@ static herr_t H5D__init_type(H5F_t *file, const H5D_t *dset, hid_t type_id, cons
static herr_t H5D__cache_dataspace_info(const H5D_t *dset);
static herr_t H5D__init_space(H5F_t *file, const H5D_t *dset, const H5S_t *space);
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, hid_t dapl_id, const char *prefix_type, char **file_prefix);
+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__append_flush_setup(H5D_t *dset, hid_t dapl_id);
-static herr_t H5D__close_cb(H5D_t *dset);
+static herr_t H5D__close_cb(H5VL_object_t *dset_vol_obj);
+static herr_t H5D__use_minimized_dset_headers(H5F_t *file, H5D_t *dset, hbool_t *minimize);
+static herr_t H5D__prepare_minimized_oh(H5F_t *file, H5D_t *dset, H5O_loc_t *oloc);
+static size_t H5D__calculate_minimum_header_size(H5F_t *file, H5D_t *dset, H5O_t *ohdr);
/*********************/
@@ -107,6 +112,10 @@ static const H5I_class_t H5I_DATASET_CLS[1] = {{
/* Flag indicating "top" of interface has been initialized */
static hbool_t H5D_top_package_initialize_s = FALSE;
+/* Prefixes of VDS and external file from the environment variables
+ * HDF5_EXTFILE_PREFIX and HDF5_VDS_PREFIX */
+static const char *H5D_prefix_ext_env = NULL;
+static const char *H5D_prefix_vds_env = NULL;
/*-------------------------------------------------------------------------
@@ -183,6 +192,10 @@ H5D__init_package(void)
/* Mark "top" of interface as initialized, too */
H5D_top_package_initialize_s = TRUE;
+ /* Retrieve the prefixes of VDS and external file from the environment variable */
+ H5D_prefix_vds_env = HDgetenv("HDF5_VDS_PREFIX");
+ H5D_prefix_ext_env = HDgetenv("HDF5_EXTFILE_PREFIX");
+
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__init_package() */
@@ -289,23 +302,29 @@ H5D_term_package(void)
*-------------------------------------------------------------------------
*/
static herr_t
-H5D__close_cb(H5D_t *dset)
+H5D__close_cb(H5VL_object_t *dset_vol_obj)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC
/* Sanity check */
- HDassert(dset);
- HDassert(dset->oloc.file);
- HDassert(dset->shared);
- HDassert(dset->shared->fo_count > 0);
+ HDassert(dset_vol_obj);
/* Close the dataset */
- if(H5D_close(dset) < 0)
+ if(H5VL_dataset_close(dset_vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to close dataset");
done:
+ /* XXX: (MSC) Weird thing for datasets and filters:
+ * Always decrement the ref count on the VOL for datasets, since
+ * the ID is removed even if the close fails.
+ */
+
+ /* Free the VOL object */
+ if(H5VL_free_object(dset_vol_obj) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTDEC, FAIL, "unable to free VOL object");
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__close_cb() */
@@ -459,7 +478,7 @@ H5D__new(hid_t dcpl_id, hbool_t creating, hbool_t vl_type)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* Copy the default dataset information */
- HDmemcpy(new_dset, &H5D_def_dset, sizeof(H5D_shared_t));
+ H5MM_memcpy(new_dset, &H5D_def_dset, sizeof(H5D_shared_t));
/* If we are using the default dataset creation property list, during creation
* don't bother to copy it, just increment the reference count
@@ -528,7 +547,7 @@ H5D__init_type(H5F_t *file, const H5D_t *dset, hid_t type_id, const H5T_t *type)
/* To use at least v18 format versions or not */
use_at_least_v18 = (H5F_LOW_BOUND(file) >= H5F_LIBVER_V18);
- /* Copy the datatype if it's a custom datatype or if it'll change when it's location is changed */
+ /* Copy the datatype if it's a custom datatype or if it'll change when its location is changed */
if(!immutable || relocatable || use_at_least_v18) {
/* Copy datatype for dataset */
if((dset->shared->type = H5T_copy(type, H5T_COPY_ALL)) == NULL)
@@ -551,7 +570,7 @@ H5D__init_type(H5F_t *file, const H5D_t *dset, hid_t type_id, const H5T_t *type)
/* Get a datatype ID for the dataset's datatype */
if((dset->shared->type_id = H5I_register(H5I_DATATYPE, dset->shared->type, FALSE)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register type")
- }
+ } /* end if */
/* Not a custom datatype, just use it directly */
else {
if(H5I_inc_ref(type_id, FALSE) < 0)
@@ -560,7 +579,7 @@ H5D__init_type(H5F_t *file, const H5D_t *dset, hid_t type_id, const H5T_t *type)
/* Use existing datatype */
dset->shared->type_id = type_id;
dset->shared->type = (H5T_t *)type; /* (Cast away const OK - QAK) */
- }
+ } /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -651,6 +670,208 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5D__use_minimized_dset_headers
+ *
+ * Purpose: Compartmentalize check for file- or dcpl-set values indicating
+ * to create a "minimized" dataset object header.
+ * Upon success, write resulting value to out pointer `minimize`.
+ *
+ * Return: Success: SUCCEED (0) (non-negative value)
+ * Failure: FAIL (-1) (negative value)
+ *
+ * Programmer: Jacob Smith
+ * 16 August 2018
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D__use_minimized_dset_headers(H5F_t *file, H5D_t *dset, hbool_t *minimize)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT;
+
+ HDassert(file);
+ HDassert(dset);
+ HDassert(minimize);
+
+ /* Get the dataset object header minimize flag for this call */
+ if(H5CX_get_dset_min_ohdr_flag(minimize) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get dataset object header minimize flag from API context")
+
+ if(FALSE == *minimize)
+ *minimize = H5F_get_min_dset_ohdr(file);
+
+done:
+ if(FAIL == ret_value)
+ *minimize = FALSE;
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* H5D__use_minimized_dset_headers */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D__calculate_minimium_header_size
+ *
+ * Purpose: Calculate the size required for the minimized object header.
+ *
+ * Return: Success: Positive value > 0
+ * Failure: 0
+ *
+ * Programmer: Jacob Smith
+ * 16 August 2018
+ *-------------------------------------------------------------------------
+ */
+static size_t
+H5D__calculate_minimum_header_size(H5F_t *file, H5D_t *dset, H5O_t *ohdr)
+{
+ H5T_t *type = NULL;
+ H5O_fill_t *fill_prop = NULL;
+ hbool_t use_at_least_v18 = FALSE;
+ const char continuation[1] = ""; /* requred for work-around */
+ size_t get_value = 0;
+ size_t ret_value = 0;
+
+ FUNC_ENTER_NOAPI_NOINIT;
+
+ HDassert(file);
+ HDassert(dset);
+ HDassert(ohdr);
+
+ type = dset->shared->type;
+ fill_prop = &(dset->shared->dcpl_cache.fill);
+ use_at_least_v18 = (H5F_LOW_BOUND(file) >= H5F_LIBVER_V18);
+
+ /* Datatype message size */
+ get_value = H5O_msg_size_oh(file, ohdr, H5O_DTYPE_ID, type, 0);
+ if (get_value == 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, 0, "Can't get size of datatype message")
+ ret_value += get_value;
+
+ /* Shared Dataspace message size */
+ get_value = H5O_msg_size_oh(file, ohdr, H5O_SDSPACE_ID, dset->shared->space, 0);
+ if (get_value == 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, 0, "can't get size of dataspace message")
+ ret_value += get_value;
+
+ /* "Layout" message size */
+ get_value = H5O_msg_size_oh(file, ohdr, H5O_LAYOUT_ID, &dset->shared->layout, 0);
+ if (get_value == 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, 0, "can't get size of layout message")
+ ret_value += get_value;
+
+ /* Fill Value message size */
+ get_value = H5O_msg_size_oh(file, ohdr, H5O_FILL_NEW_ID, fill_prop, 0);
+ if (get_value == 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, 0, "can't get size of fill value message")
+ ret_value += get_value;
+
+ /* "Continuation" message size */
+ /* message pointer "continuation" is unused by raw get function, however,
+ * a null pointer would be intercepted by an assert in H5O_msg_size_oh().
+ */
+ get_value = H5O_msg_size_oh(file, ohdr, H5O_CONT_ID, continuation, 0);
+ if (get_value == 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, 0, "can't get size of continuation message")
+ ret_value += get_value;
+
+ /* Fill Value (backwards compatability) message size */
+ if(fill_prop->buf && !use_at_least_v18) {
+ H5O_fill_t old_fill_prop; /* Copy for writing "old" fill value */
+
+ /* Shallow copy the fill value property */
+ /* guards against shared component modification */
+ H5MM_memcpy(&old_fill_prop, fill_prop, sizeof(old_fill_prop));
+
+ if (H5O_msg_reset_share(H5O_FILL_ID, &old_fill_prop) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, 0, "can't reset the copied fill property")
+
+ get_value = H5O_msg_size_oh(file, ohdr, H5O_FILL_ID, &old_fill_prop, 0);
+ if (get_value == 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, 0, "can't get size of fill value (backwards compat) message")
+ ret_value += get_value;
+ }
+
+ /* Filter/Pipeline message size */
+ if(H5D_CHUNKED == dset->shared->layout.type) {
+ H5O_pline_t *pline = &dset->shared->dcpl_cache.pline;
+ if(pline->nused > 0) {
+ get_value = H5O_msg_size_oh(file, ohdr, H5O_PLINE_ID, pline, 0);
+ if (get_value == 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, 0, "can't get size of filter message")
+ ret_value += get_value;
+ }
+ }
+
+ /* External File Link message size */
+ if(dset->shared->dcpl_cache.efl.nused > 0) {
+ get_value = H5O_msg_size_oh(file, ohdr, H5O_EFL_ID, &dset->shared->dcpl_cache.efl, 0);
+ if (get_value == 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, 0, "can't get size of external file link message")
+ ret_value += get_value;
+ }
+
+ /* Modification Time message size */
+ if(H5O_HDR_STORE_TIMES & H5O_OH_GET_FLAGS(ohdr)) {
+ HDassert(H5O_OH_GET_VERSION(ohdr) >= 1); /* 1 :: H5O_VERSION_1 (H5Opkg.h) */
+
+ if(H5O_OH_GET_VERSION(ohdr) == 1) {
+ /* v1 object headers store modification time as a message */
+ time_t mtime;
+ get_value = H5O_msg_size_oh(file, ohdr, H5O_MTIME_NEW_ID, &mtime, 0);
+ if (get_value == 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, 0, "can't get size of modification time message")
+ ret_value += get_value;
+ }
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* H5D__calculate_minimum_header_size */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D__prepare_minimized_oh
+ *
+ * Purpose: Create an object header (H5O_t) allocated with the smallest
+ * possible size.
+ *
+ * Return: Success: SUCCEED (0) (non-negative value)
+ * Failure: FAIL (-1) (negative value)
+ *
+ * Programmer: Jacob Smith
+ * 16 August 2018
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D__prepare_minimized_oh(H5F_t *file, H5D_t *dset, H5O_loc_t *oloc)
+{
+ H5O_t *oh = NULL;
+ size_t ohdr_size = 0;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT;
+
+ HDassert(file);
+ HDassert(dset);
+ HDassert(oloc);
+
+ oh = H5O__create_ohdr(file, dset->shared->dcpl_id);
+ if(NULL == oh)
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "can't instantiate object header")
+
+ ohdr_size = H5D__calculate_minimum_header_size(file, dset, oh);
+ if (ohdr_size == 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "computed header size is invalid")
+
+ /* Special allocation of space for compact datsets is handled by the call here. */
+ if(H5O__apply_ohdr(file, oh, dset->shared->dcpl_id, ohdr_size, (size_t)1, oloc) == FAIL)
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "can't apply object header to file")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* H5D__prepare_minimized_oh */
+
+
+/*-------------------------------------------------------------------------
* Function: H5D__update_oh_info
*
* Purpose: Create and fill object header for dataset
@@ -662,17 +883,18 @@ done:
static herr_t
H5D__update_oh_info(H5F_t *file, H5D_t *dset, hid_t dapl_id)
{
- H5O_t *oh = NULL; /* Pointer to dataset's object header */
- size_t ohdr_size = H5D_MINHDR_SIZE; /* Size of dataset's object header */
- H5O_loc_t *oloc = NULL; /* Dataset's object location */
- H5O_layout_t *layout; /* Dataset's layout information */
- H5T_t *type; /* Dataset's datatype */
- H5O_fill_t *fill_prop; /* Pointer to dataset's fill value information */
- H5D_fill_value_t fill_status; /* Fill value status */
- hbool_t fill_changed = FALSE; /* Flag indicating the fill value was changed */
- hbool_t layout_init = FALSE; /* Flag to indicate that chunk information was initialized */
- hbool_t use_at_least_v18; /* Flag indicating to use at least v18 format versions */
- herr_t ret_value = SUCCEED; /* Return value */
+ H5O_t *oh = NULL; /* Pointer to dataset's object header */
+ size_t ohdr_size = H5D_MINHDR_SIZE; /* Size of dataset's object header */
+ H5O_loc_t *oloc = NULL; /* Dataset's object location */
+ H5O_layout_t *layout; /* Dataset's layout information */
+ H5T_t *type; /* Dataset's datatype */
+ H5O_fill_t *fill_prop; /* Pointer to dataset's fill value information */
+ H5D_fill_value_t fill_status; /* Fill value status */
+ hbool_t fill_changed = FALSE; /* Flag indicating the fill value was changed */
+ hbool_t layout_init = FALSE; /* Flag to indicate that chunk information was initialized */
+ hbool_t use_at_least_v18; /* Flag indicating to use at least v18 format versions */
+ hbool_t minimize_header = FALSE;
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC
@@ -740,13 +962,24 @@ H5D__update_oh_info(H5F_t *file, H5D_t *dset, hid_t dapl_id)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set fill value info")
} /* end if */
- /* Add the dataset's raw data size to the size of the header, if the raw data will be stored as compact */
- if(layout->type == H5D_COMPACT)
- ohdr_size += layout->storage.u.compact.size;
+ if(H5D__use_minimized_dset_headers(file, dset, &minimize_header) == FAIL)
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTGET, FAIL, "can't get minimize settings")
+
+ if(TRUE == minimize_header) {
+ if(H5D__prepare_minimized_oh(file, dset, oloc) == FAIL)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't create minimized dataset object header")
+ } else {
+ /* Add the dataset's raw data size to the size of the header, if the
+ * raw data will be stored as compact
+ */
+ if(H5D_COMPACT == layout->type)
+ ohdr_size += layout->storage.u.compact.size;
+
+ /* Create an object header for the dataset */
+ if(H5O_create(file, ohdr_size, (size_t)1, dset->shared->dcpl_id, oloc/*out*/) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create dataset object header")
+ } /* If use minimum/standard object header space */
- /* Create an object header for the dataset */
- if(H5O_create(file, ohdr_size, (size_t)1, dset->shared->dcpl_id, oloc/*out*/) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create dataset object header")
HDassert(file == dset->oloc.file);
/* Pin the object header */
@@ -772,7 +1005,7 @@ H5D__update_oh_info(H5F_t *file, H5D_t *dset, hid_t dapl_id)
/* Shallow copy the fill value property */
/* (we only want to make certain that the shared component isn't modified) */
- HDmemcpy(&old_fill_prop, fill_prop, sizeof(old_fill_prop));
+ H5MM_memcpy(&old_fill_prop, fill_prop, sizeof(old_fill_prop));
/* Reset shared component info */
H5O_msg_reset_share(H5O_FILL_ID, &old_fill_prop);
@@ -855,15 +1088,13 @@ done:
*--------------------------------------------------------------------------
*/
static herr_t
-H5D__build_file_prefix(const H5D_t *dset, hid_t dapl_id, const char *prefix_type,
- char **file_prefix /*out*/)
+H5D__build_file_prefix(const H5D_t *dset, H5F_prefix_open_t prefix_type, char **file_prefix /*out*/)
{
- char *prefix = NULL; /* prefix used to look for the file */
+ const char *prefix = NULL; /* prefix used to look for the file */
char *filepath = NULL; /* absolute path of directory the HDF5 file is in */
size_t filepath_len; /* length of file path */
size_t prefix_len; /* length of prefix */
size_t file_prefix_len; /* length of expanded prefix */
- H5P_genplist_t *plist = NULL; /* Property list pointer */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC
@@ -877,20 +1108,22 @@ H5D__build_file_prefix(const H5D_t *dset, hid_t dapl_id, const char *prefix_type
/* XXX: Future thread-safety note - getenv is not required
* to be reentrant.
*/
- if(HDstrcmp(prefix_type, H5D_ACS_VDS_PREFIX_NAME) == 0)
- prefix = HDgetenv("HDF5_VDS_PREFIX");
- else if(HDstrcmp(prefix_type, H5D_ACS_EFILE_PREFIX_NAME) == 0)
- prefix = HDgetenv("HDF5_EXTFILE_PREFIX");
- else
- HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "prefix name is not sensible")
-
- if(prefix == NULL || *prefix == '\0') {
- /* Set prefix to value of prefix_type property */
- if(NULL == (plist = H5P_object_verify(dapl_id, H5P_DATASET_ACCESS)))
- HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
- if(H5P_peek(plist, prefix_type, &prefix) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get file prefix")
+ if(H5F_PREFIX_VDS == prefix_type) {
+ prefix = H5D_prefix_vds_env;
+
+ if(prefix == NULL || *prefix == '\0')
+ if(H5CX_get_vds_prefix(&prefix) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get the prefix for vds file")
} /* end if */
+ else if(H5F_PREFIX_EFILE == prefix_type) {
+ prefix = H5D_prefix_ext_env;
+
+ if(prefix == NULL || *prefix == '\0')
+ if(H5CX_get_ext_file_prefix(&prefix) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get the prefix for the external file")
+ } /* end else-if */
+ else
+ HGOTO_ERROR(H5E_DATASET, H5E_BADTYPE, FAIL, "prefix name is not sensible")
/* Prefix has to be checked for NULL / empty string again because the
* code above might have updated it.
@@ -899,11 +1132,10 @@ H5D__build_file_prefix(const H5D_t *dset, hid_t dapl_id, const char *prefix_type
/* filename is interpreted as relative to the current directory,
* does not need to be expanded
*/
- if(NULL == (*file_prefix = (char *)H5MM_strdup("")))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ *file_prefix = NULL;
} /* end if */
else {
- if (HDstrncmp(prefix, "${ORIGIN}", HDstrlen("${ORIGIN}")) == 0) {
+ if(HDstrncmp(prefix, "${ORIGIN}", HDstrlen("${ORIGIN}")) == 0) {
/* Replace ${ORIGIN} at beginning of prefix by directory of HDF5 file */
filepath_len = HDstrlen(filepath);
prefix_len = HDstrlen(prefix);
@@ -943,7 +1175,8 @@ H5D_t *
H5D__create(H5F_t *file, hid_t type_id, const H5S_t *space, hid_t dcpl_id,
hid_t dapl_id)
{
- const H5T_t *type; /* Datatype for dataset */
+ H5T_t *type = NULL; /* Datatype for dataset (VOL pointer) */
+ H5T_t *dt = NULL; /* Datatype for dataset (non-VOL pointer) */
H5D_t *new_dset = NULL;
H5P_genplist_t *dc_plist = NULL; /* New Property list */
hbool_t has_vl_type = FALSE; /* Flag to indicate a VL-type for dataset */
@@ -964,9 +1197,12 @@ H5D__create(H5F_t *file, hid_t type_id, const H5S_t *space, hid_t dcpl_id,
HDassert(H5I_GENPROP_LST == H5I_get_type(dcpl_id));
/* Get the dataset's datatype */
- if(NULL == (type = (const H5T_t *)H5I_object(type_id)))
+ if(NULL == (dt = (H5T_t *)H5I_object(type_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a datatype")
+ /* If this is a named datatype, get the pointer via the VOL plugin */
+ type = H5T_get_actual_type(dt);
+
/* Check if the datatype is "sensible" for use in a dataset */
if(H5T_is_sensible(type) != TRUE)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "datatype is not sensible")
@@ -1095,11 +1331,11 @@ H5D__create(H5F_t *file, hid_t type_id, const H5S_t *space, hid_t dcpl_id,
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to set up flush append property")
/* Set the external file prefix */
- if(H5D__build_file_prefix(new_dset, dapl_id, H5D_ACS_EFILE_PREFIX_NAME, &new_dset->shared->extfile_prefix) < 0)
+ if(H5D__build_file_prefix(new_dset, H5F_PREFIX_EFILE, &new_dset->shared->extfile_prefix) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to initialize external file prefix")
/* Set the VDS file prefix */
- if(H5D__build_file_prefix(new_dset, dapl_id, H5D_ACS_VDS_PREFIX_NAME, &new_dset->shared->vds_prefix) < 0)
+ if(H5D__build_file_prefix(new_dset, H5F_PREFIX_VDS, &new_dset->shared->vds_prefix) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to initialize VDS prefix")
/* Add the dataset to the list of opened objects in the file */
@@ -1254,11 +1490,11 @@ H5D_open(const H5G_loc_t *loc, hid_t dapl_id)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, NULL, "can't copy path")
/* Get the external file prefix */
- if(H5D__build_file_prefix(dataset, dapl_id, H5D_ACS_EFILE_PREFIX_NAME, &extfile_prefix) < 0)
+ if(H5D__build_file_prefix(dataset, H5F_PREFIX_EFILE, &extfile_prefix) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to initialize external file prefix")
/* Get the VDS prefix */
- if(H5D__build_file_prefix(dataset, dapl_id, H5D_ACS_VDS_PREFIX_NAME, &vds_prefix) < 0)
+ if(H5D__build_file_prefix(dataset, H5F_PREFIX_VDS, &vds_prefix) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to initialize VDS prefix")
/* Check if dataset was already open */
@@ -1302,8 +1538,13 @@ H5D_open(const H5G_loc_t *loc, hid_t dapl_id)
/* Check whether the external file prefix of the already open dataset
* matches the new external file prefix
*/
- if(HDstrcmp(extfile_prefix, dataset->shared->extfile_prefix) != 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, NULL, "new external file prefix does not match external file prefix of already open dataset")
+ if(extfile_prefix && dataset->shared->extfile_prefix) {
+ if(HDstrcmp(extfile_prefix, dataset->shared->extfile_prefix) != 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, NULL, "new external file prefix does not match external file prefix of already open dataset")
+ } else {
+ if(extfile_prefix || dataset->shared->extfile_prefix)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, NULL, "new external file prefix does not match external file prefix of already open dataset")
+ }
/* Check if the object has been opened through the top file yet */
if(H5FO_top_count(dataset->oloc.file, dataset->oloc.addr) == 0) {
@@ -1411,7 +1652,7 @@ H5D__append_flush_setup(H5D_t *dset, hid_t dapl_id)
dset->shared->append_flush.ndims = info.ndims;
dset->shared->append_flush.func = info.func;
dset->shared->append_flush.udata = info.udata;
- HDmemcpy(dset->shared->append_flush.boundary, info.boundary, sizeof(info.boundary));
+ H5MM_memcpy(dset->shared->append_flush.boundary, info.boundary, sizeof(info.boundary));
} /* end if */
} /* end if */
} /* end if */
@@ -1812,11 +2053,13 @@ H5D_mult_refresh_close(hid_t dset_id)
FUNC_ENTER_NOAPI(FAIL)
- if(NULL == (dataset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
+ if(NULL == (dataset = (H5D_t *)H5VL_object_verify(dset_id, H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset")
/* check args */
- HDassert(dataset && dataset->oloc.file && dataset->shared);
+ HDassert(dataset);
+ HDassert(dataset->oloc.file);
+ HDassert(dataset->shared);
HDassert(dataset->shared->fo_count > 0);
if(dataset->shared->fo_count > 1) {
@@ -1949,40 +2192,16 @@ H5D_oloc(H5D_t *dataset)
*-------------------------------------------------------------------------
*/
H5G_name_t *
-H5D_nameof(H5D_t *dataset)
+H5D_nameof(const H5D_t *dataset)
{
/* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
FUNC_ENTER_NOAPI_NOINIT_NOERR
- FUNC_LEAVE_NOAPI(dataset ? &(dataset->path) : (H5G_name_t *)NULL)
+ FUNC_LEAVE_NOAPI(dataset ? &(dataset->path) : NULL)
} /* end H5D_nameof() */
/*-------------------------------------------------------------------------
- * Function: H5D_typeof
- *
- * Purpose: Returns a pointer to the dataset's datatype. The datatype
- * is not copied.
- *
- * Return: Success: Ptr to the dataset's datatype, uncopied.
- * Failure: NULL
- *-------------------------------------------------------------------------
- */
-H5T_t *
-H5D_typeof(const H5D_t *dset)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOERR
-
- HDassert(dset);
- HDassert(dset->shared);
- HDassert(dset->shared->type);
-
- FUNC_LEAVE_NOAPI(dset->shared->type)
-} /* end H5D_typeof() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5D__alloc_storage
*
* Purpose: Allocate storage for the raw data of a dataset.
@@ -2323,50 +2542,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5D_vlen_reclaim
- *
- * Purpose: Frees the buffers allocated for storing variable-length data
- * in memory. Only frees the VL data in the selection defined in the
- * dataspace.
- *
- * Return: Non-negative on success, negative on failure
- *-------------------------------------------------------------------------
- */
-herr_t
-H5D_vlen_reclaim(hid_t type_id, H5S_t *space, void *buf)
-{
- H5T_t *type; /* Datatype */
- H5S_sel_iter_op_t dset_op; /* Operator for iteration */
- H5T_vlen_alloc_info_t vl_alloc_info; /* VL allocation info */
- herr_t ret_value = FAIL; /* Return value */
-
- FUNC_ENTER_NOAPI(FAIL)
-
- /* Check args */
- HDassert(H5I_DATATYPE == H5I_get_type(type_id));
- HDassert(space);
- HDassert(buf);
-
- if(NULL == (type = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an valid base datatype")
-
- /* Get the allocation info */
- if(H5CX_get_vlen_alloc_info(&vl_alloc_info) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to retrieve VL allocation info")
-
- /* Call H5S_select_iterate with args, etc. */
- dset_op.op_type = H5S_SEL_ITER_OP_APP;
- dset_op.u.app_op.op = H5T_vlen_reclaim;
- dset_op.u.app_op.type_id = type_id;
-
- ret_value = H5S_select_iterate(buf, type, space, &dset_op, &vl_alloc_info);
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_vlen_reclaim() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5D__vlen_get_buf_size_alloc
*
* Purpose: This routine makes certain there is enough space in the temporary
@@ -2422,8 +2597,8 @@ H5D__vlen_get_buf_size(void H5_ATTR_UNUSED *elem, hid_t type_id,
unsigned H5_ATTR_UNUSED ndim, const hsize_t *point, void *op_data)
{
H5D_vlen_bufsize_t *vlen_bufsize = (H5D_vlen_bufsize_t *)op_data;
+ H5VL_object_t *vol_obj = vlen_bufsize->dset_vol_obj;
H5T_t *dt; /* Datatype for operation */
- H5S_t *mspace; /* Memory dataspace for operation */
H5S_t *fspace; /* File dataspace for operation */
herr_t ret_value = SUCCEED; /* Return value */
@@ -2440,10 +2615,6 @@ H5D__vlen_get_buf_size(void H5_ATTR_UNUSED *elem, hid_t type_id,
if(NULL == (vlen_bufsize->fl_tbuf = H5FL_BLK_REALLOC(vlen_fl_buf, vlen_bufsize->fl_tbuf, H5T_get_size(dt))))
HGOTO_ERROR(H5E_DATASET, H5E_NOSPACE, FAIL, "can't resize tbuf")
- /* Get the memory dataspace from the ID */
- if(NULL == (mspace = (H5S_t *)H5I_object_verify(vlen_bufsize->mspace_id, H5I_DATASPACE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
-
/* Select point to read in */
if(NULL == (fspace = (H5S_t *)H5I_object_verify(vlen_bufsize->fspace_id, H5I_DATASPACE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
@@ -2451,7 +2622,7 @@ H5D__vlen_get_buf_size(void H5_ATTR_UNUSED *elem, hid_t type_id,
HGOTO_ERROR(H5E_DATASET, H5E_CANTCREATE, FAIL, "can't select point")
/* Read in the point (with the custom VL memory allocator) */
- if(H5D__read(vlen_bufsize->dset, type_id, mspace, fspace, vlen_bufsize->fl_tbuf) < 0)
+ if(H5VL_dataset_read(vol_obj, type_id, vlen_bufsize->mspace_id, vlen_bufsize->fspace_id, H5P_DATASET_XFER_DEFAULT, vlen_bufsize->fl_tbuf, H5_REQUEST_NULL) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read point")
done:
@@ -2549,7 +2720,7 @@ H5D__set_extent(H5D_t *dset, const hsize_t *size)
/* Keep the current dataspace dimensions for later */
HDcompile_assert(sizeof(curr_dims) == sizeof(dset->shared->curr_dims));
- HDmemcpy(curr_dims, dset->shared->curr_dims, H5S_MAX_RANK * sizeof(curr_dims[0]));
+ H5MM_memcpy(curr_dims, dset->shared->curr_dims, H5S_MAX_RANK * sizeof(curr_dims[0]));
/* Modify the size of the dataspace */
if((changed = H5S_set_extent(dset->shared->space, size)) < 0)
@@ -2643,7 +2814,7 @@ H5D__set_extent(H5D_t *dset, const hsize_t *size)
dset->shared->layout.storage.u.virt.list[u].virtual_space_status = H5O_VIRTUAL_STATUS_CORRECT;
/* Patch sub-source datasets */
- for(v = 0; v < dset->shared->layout.storage.u.virt.list[u].sub_dset_nalloc; v++)
+ for(v = 0; v < dset->shared->layout.storage.u.virt.list[u].sub_dset_nused; v++)
if(H5S_set_extent(dset->shared->layout.storage.u.virt.list[u].sub_dset[v].virtual_select, size) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to modify size of dataspace")
} /* end for */
@@ -2669,7 +2840,8 @@ H5D__set_extent(H5D_t *dset, const hsize_t *size)
*-------------------------------------------------------------------------
*/
if(H5D_CHUNKED == dset->shared->layout.type) {
- if(shrink && (*dset->shared->layout.ops->is_space_alloc)(&dset->shared->layout.storage))
+ if(shrink && ((*dset->shared->layout.ops->is_space_alloc)(&dset->shared->layout.storage)
+ || (dset->shared->layout.ops->is_data_cached && (*dset->shared->layout.ops->is_data_cached)(dset->shared))))
/* Remove excess chunks */
if(H5D__chunk_prune_by_extent(dset, curr_dims) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to remove chunks")
@@ -2716,7 +2888,7 @@ H5D__flush_sieve_buf(H5D_t *dataset)
HDassert(dataset->shared->layout.type != H5D_COMPACT); /* We should never have a sieve buffer for compact storage */
/* Write dirty data sieve buffer to file */
- if(H5F_block_write(dataset->oloc.file, H5FD_MEM_DRAW, dataset->shared->cache.contig.sieve_loc,
+ if(H5F_shared_block_write(H5F_SHARED(dataset->oloc.file), H5FD_MEM_DRAW, dataset->shared->cache.contig.sieve_loc,
dataset->shared->cache.contig.sieve_size, dataset->shared->cache.contig.sieve_buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed")
@@ -2833,7 +3005,7 @@ H5D__format_convert(H5D_t *dataset)
idx_info.storage = &dataset->shared->layout.storage.u.chunk;
/* Copy the current layout info to the new layout */
- HDmemcpy(newlayout, &dataset->shared->layout, sizeof(H5O_layout_t));
+ H5MM_memcpy(newlayout, &dataset->shared->layout, sizeof(H5O_layout_t));
/* Set up info for version 1 B-tree in the new layout */
newlayout->version = H5O_LAYOUT_VERSION_3;
@@ -2884,7 +3056,7 @@ H5D__format_convert(H5D_t *dataset)
HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "unable to release chunk index info")
/* Copy the new layout to the dataset's layout */
- HDmemcpy(&dataset->shared->layout, newlayout, sizeof(H5O_layout_t));
+ H5MM_memcpy(&dataset->shared->layout, newlayout, sizeof(H5O_layout_t));
break;
@@ -3048,7 +3220,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5D_flush_all(const H5F_t *f)
+H5D_flush_all(H5F_t *f)
{
herr_t ret_value = SUCCEED; /* Return value */
@@ -3058,7 +3230,7 @@ H5D_flush_all(const H5F_t *f)
HDassert(f);
/* Iterate over all the open datasets */
- if(H5I_iterate(H5I_DATASET, H5D__flush_all_cb, (void *)f, FALSE) < 0) /* Casting away const OK -QAK */
+ if(H5I_iterate(H5I_DATASET, H5D__flush_all_cb, f, FALSE) < 0) /* Casting away const OK -QAK */
HGOTO_ERROR(H5E_DATASET, H5E_BADITER, FAIL, "unable to flush cached dataset info")
done:
@@ -3384,8 +3556,18 @@ H5D__get_type(const H5D_t *dset)
if(H5T_lock(dt, FALSE) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to lock transient datatype")
- if((ret_value = H5I_register(H5I_DATATYPE, dt, TRUE)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register datatype")
+ /* Create an atom */
+ if(H5T_is_named(dt)) {
+ /* If this is a committed datatype, we need to recreate the
+ * two-level IDs, where the VOL object is a copy of the
+ * returned datatype.
+ */
+ if((ret_value = H5VL_wrap_register(H5I_DATATYPE, dt, TRUE)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register datatype")
+ } /* end if */
+ else
+ if((ret_value = H5I_register(H5I_DATATYPE, dt, TRUE)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register datatype")
done:
if(ret_value < 0)
diff --git a/src/H5Dio.c b/src/H5Dio.c
index 88a9e4b..79a856a 100644
--- a/src/H5Dio.c
+++ b/src/H5Dio.c
@@ -30,10 +30,7 @@
#include "H5MMprivate.h" /* Memory management */
#include "H5Sprivate.h" /* Dataspace */
-#ifdef H5_HAVE_PARALLEL
-/* Remove this if H5R_DATASET_REGION is no longer used in this file */
-#include "H5Rpublic.h"
-#endif /*H5_HAVE_PARALLEL*/
+#include "H5VLnative_private.h" /* Native VOL connector */
/****************/
@@ -163,26 +160,22 @@ 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*/)
{
- H5D_t *dset = NULL;
- const H5S_t *mem_space = NULL;
- const H5S_t *file_space = NULL;
+ H5VL_object_t *vol_obj = NULL;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE6("e", "iiiiix", dset_id, mem_type_id, mem_space_id, file_space_id,
dxpl_id, buf);
+ /* 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")
+
/* Get dataset pointer */
- if (NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
+ if (NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(dset_id, H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dset_id is not a dataset ID")
- if (NULL == dset->oloc.file)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dataset is not associated with a file")
-
- /* Get validated dataspace pointers */
- if (H5S_get_validated_dataspace(mem_space_id, &mem_space) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "could not get a validated dataspace from mem_space_id")
- if (H5S_get_validated_dataspace(file_space_id, &file_space) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "could not get a validated dataspace from file_space_id")
/* Get the default dataset transfer property list if the user didn't provide one */
if (H5P_DEFAULT == dxpl_id)
@@ -195,7 +188,7 @@ H5Dread(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id,
H5CX_set_dxpl(dxpl_id);
/* Read the data */
- if (H5D__read(dset, mem_type_id, mem_space, file_space, buf/*out*/) < 0)
+ if ((ret_value = H5VL_dataset_read(vol_obj, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf, H5_REQUEST_NULL)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read data")
done:
@@ -219,20 +212,15 @@ herr_t
H5Dread_chunk(hid_t dset_id, hid_t dxpl_id, const hsize_t *offset, uint32_t *filters,
void *buf)
{
- H5D_t *dset = NULL;
- hsize_t offset_copy[H5O_LAYOUT_NDIMS]; /* Internal copy of chunk offset */
+ H5VL_object_t *vol_obj = NULL;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE5("e", "ii*h*Iu*x", dset_id, dxpl_id, offset, filters, buf);
/* Check arguments */
- if (NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
+ if (NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(dset_id, H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dset_id is not a dataset ID")
- if (NULL == dset->oloc.file)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dataset is not associated with a file")
- if (H5D_CHUNKED != dset->shared->layout.type)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a chunked dataset")
if (!buf)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "buf cannot be NULL")
if (!offset)
@@ -250,14 +238,8 @@ H5Dread_chunk(hid_t dset_id, hid_t dxpl_id, const hsize_t *offset, uint32_t *fil
/* Set DXPL for operation */
H5CX_set_dxpl(dxpl_id);
- /* Copy the user's offset array so we can be sure it's terminated properly.
- * (we don't want to mess with the user's buffer).
- */
- if (H5D__get_offset_copy(dset, offset, offset_copy) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "failure to copy offset array")
-
/* Read the raw chunk */
- if (H5D__chunk_direct_read(dset, offset_copy, filters, buf) < 0)
+ if(H5VL_dataset_optional(vol_obj, dxpl_id, H5_REQUEST_NULL, H5VL_NATIVE_DATASET_CHUNK_READ, offset, filters, buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read unprocessed chunk data")
done:
@@ -298,28 +280,24 @@ done:
*/
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)
+ hid_t file_space_id, hid_t dxpl_id, const void *buf)
{
- H5D_t *dset = NULL;
- const H5S_t *mem_space = NULL;
- const H5S_t *file_space = NULL;
+ H5VL_object_t *vol_obj = NULL;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE6("e", "iiiii*x", dset_id, mem_type_id, mem_space_id, file_space_id,
dxpl_id, buf);
+ /* 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")
+
/* Get dataset pointer */
- if (NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
+ if (NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(dset_id, H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dset_id is not a dataset ID")
- if (NULL == dset->oloc.file)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dataset is not associated with a file")
-
- /* Get validated dataspace pointers */
- if (H5S_get_validated_dataspace(mem_space_id, &mem_space) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "could not get a validated dataspace from mem_space_id")
- if (H5S_get_validated_dataspace(file_space_id, &file_space) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "could not get a validated dataspace from file_space_id")
/* Get the default dataset transfer property list if the user didn't provide one */
if (H5P_DEFAULT == dxpl_id)
@@ -332,7 +310,7 @@ H5Dwrite(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id,
H5CX_set_dxpl(dxpl_id);
/* Write the data */
- if (H5D__write(dset, mem_type_id, mem_space, file_space, buf) < 0)
+ if ((ret_value = H5VL_dataset_write(vol_obj, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf, H5_REQUEST_NULL)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write data")
done:
@@ -356,8 +334,7 @@ herr_t
H5Dwrite_chunk(hid_t dset_id, hid_t dxpl_id, uint32_t filters, const hsize_t *offset,
size_t data_size, const void *buf)
{
- H5D_t *dset = NULL;
- hsize_t offset_copy[H5O_LAYOUT_NDIMS]; /* Internal copy of chunk offset */
+ H5VL_object_t *vol_obj = NULL;
uint32_t data_size_32; /* Chunk data size (limited to 32-bits currently) */
herr_t ret_value = SUCCEED; /* Return value */
@@ -365,12 +342,8 @@ H5Dwrite_chunk(hid_t dset_id, hid_t dxpl_id, uint32_t filters, const hsize_t *of
H5TRACE6("e", "iiIu*hz*x", dset_id, dxpl_id, filters, offset, data_size, buf);
/* Check arguments */
- if (NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
+ if (NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(dset_id, H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid dataset ID")
- if (NULL == dset->oloc.file)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dataset is not associated with a file")
- if (H5D_CHUNKED != dset->shared->layout.type)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a chunked dataset")
if (!buf)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "buf cannot be NULL")
if (!offset)
@@ -393,14 +366,8 @@ H5Dwrite_chunk(hid_t dset_id, hid_t dxpl_id, uint32_t filters, const hsize_t *of
/* Set DXPL for operation */
H5CX_set_dxpl(dxpl_id);
- /* Copy the user's offset array so we can be sure it's terminated properly.
- * (we don't want to mess with the user's buffer).
- */
- if (H5D__get_offset_copy(dset, offset, offset_copy) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "failure to copy offset array")
-
/* Write chunk */
- if (H5D__chunk_direct_write(dset, filters, offset_copy, data_size_32, buf) < 0)
+ if(H5VL_dataset_optional(vol_obj, dxpl_id, H5_REQUEST_NULL, H5VL_NATIVE_DATASET_CHUNK_WRITE, filters, offset, data_size_32, buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write unprocessed chunk data")
done:
@@ -506,33 +473,33 @@ H5D__read(H5D_t *dataset, hid_t mem_type_id, const H5S_t *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
+ * 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
+ * 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
+ * Note that in general, this requires us to touch up the memory buffer as
* well.
*/
- if(TRUE == H5S_select_shape_same(mem_space, file_space) &&
+ if(TRUE == H5S_SELECT_SHAPE_SAME(mem_space, file_space) &&
H5S_GET_EXTENT_NDIMS(mem_space) != H5S_GET_EXTENT_NDIMS(file_space)) {
- void *adj_buf = NULL; /* Pointer to the location in buf corresponding */
+ const void *adj_buf = NULL; /* Pointer to the location in buf corresponding */
/* to the beginning of the projected mem space. */
/* 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), buf, (const void **)&adj_buf, type_info.dst_type_size) < 0)
+ (unsigned)H5S_GET_EXTENT_NDIMS(file_space), buf, &adj_buf, type_info.dst_type_size) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to construct projected memory dataspace")
HDassert(projected_mem_space);
HDassert(adj_buf);
/* Switch to using projected memory dataspace & adjusted buffer */
mem_space = projected_mem_space;
- buf = adj_buf;
+ buf = (void *)adj_buf; /* Casting away 'const' OK -QAK */
} /* end if */
@@ -546,7 +513,8 @@ H5D__read(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space,
* 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_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 */
/* Retrieve dataset's fill-value properties */
@@ -578,6 +546,7 @@ H5D__read(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space,
/* 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
|| dataset->shared->layout.type == H5D_COMPACT);
@@ -685,22 +654,12 @@ H5D__write(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space,
/* 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 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_detect_class(type_info.mem_type, H5T_VLEN, FALSE) > 0)
- HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "Parallel IO does not support writing VL datatypes yet")
-
- /* If MPI based VFD is used, no VL datatype support yet. */
+ 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 */
- /* We should really use H5T_detect_class() here, but it will be difficult
- * to detect the type of the reference if it is nested... -QAK
- */
- if(H5T_get_class(type_info.mem_type, TRUE) == H5T_REFERENCE &&
- H5T_get_ref_type(type_info.mem_type) == H5R_DATASET_REGION)
- HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "Parallel IO does not support writing region reference datatypes 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 */
@@ -748,27 +707,27 @@ H5D__write(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space,
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
+ /* 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
+ * 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
+ * Note that in general, this requires us to touch up the memory buffer
* as well.
*/
- if(TRUE == H5S_select_shape_same(mem_space, file_space) &&
+ if(TRUE == H5S_SELECT_SHAPE_SAME(mem_space, file_space) &&
H5S_GET_EXTENT_NDIMS(mem_space) != H5S_GET_EXTENT_NDIMS(file_space)) {
- void *adj_buf = NULL; /* Pointer to the location in buf corresponding */
+ const void *adj_buf = NULL; /* Pointer to the location in buf corresponding */
/* to the beginning of the projected mem space. */
/* 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), buf, (const void **)&adj_buf, type_info.src_type_size) < 0)
+ (unsigned)H5S_GET_EXTENT_NDIMS(file_space), buf, &adj_buf, type_info.src_type_size) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to construct projected memory dataspace")
HDassert(projected_mem_space);
HDassert(adj_buf);
@@ -893,6 +852,7 @@ H5D__ioinfo_init(H5D_t *dset, const H5D_type_info_t *type_info,
/* Set up "normal" I/O fields */
io_info->dset = dset;
+ io_info->f_sh = H5F_SHARED(dset->oloc.file);
io_info->store = store;
/* Set I/O operations to initial values */
@@ -1069,16 +1029,13 @@ H5D__typeinfo_init(const H5D_t *dset, hid_t mem_type_id, hbool_t do_write,
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
+ /* 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. The
- * malloc() is usually less resource-intensive if we allocate/free the
- * same size over and over.
+ * buffer which is the exact size, we allocate the target size.
*/
if(NULL == (type_info->tconv_buf = (uint8_t *)tconv_buf)) {
/* Allocate temporary buffer */
- if(NULL == (type_info->tconv_buf = H5FL_BLK_MALLOC(type_conv, target_size)))
+ if(NULL == (type_info->tconv_buf = H5FL_BLK_CALLOC(type_conv, target_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion")
type_info->tconv_buf_allocated = TRUE;
} /* end if */
@@ -1181,15 +1138,19 @@ H5D__ioinfo_adjust(H5D_io_info_t *io_info, const H5D_t *dset,
hbool_t local_error_message_previously_written = FALSE;
hbool_t global_error_message_previously_written = FALSE;
size_t index;
- char local_no_collective_cause_string[256] = "";
- char global_no_collective_cause_string[256] = "";
+ size_t cause_strings_len;
+ char local_no_collective_cause_string[512] = "";
+ char global_no_collective_cause_string[512] = "";
const char *cause_strings[] = { "independent I/O was requested",
"datatype conversions were required",
"data transforms needed to be applied",
"optimized MPI types flag wasn't set",
"one of the dataspaces was neither simple nor scalar",
"dataset was not contiguous or chunked",
- "parallel writes to filtered datasets are disabled" };
+ "parallel writes to filtered datasets are disabled",
+ "an error occurred while checking if collective I/O was possible" };
+
+ cause_strings_len = sizeof(cause_strings) / sizeof(cause_strings[0]);
if(H5CX_get_mpio_local_no_coll_cause(&local_no_collective_cause) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to get local no collective cause value")
@@ -1198,7 +1159,7 @@ H5D__ioinfo_adjust(H5D_io_info_t *io_info, const H5D_t *dset,
/* Append each of the "reason for breaking collective I/O" error messages to the
* local and global no collective cause strings */
- for (cause = 1, index = 0; cause < H5D_MPIO_NO_COLLECTIVE_MAX_CAUSE; cause <<= 1, index++) {
+ for (cause = 1, index = 0; (cause < H5D_MPIO_NO_COLLECTIVE_MAX_CAUSE) && (index < cause_strings_len); cause <<= 1, index++) {
size_t cause_strlen = HDstrlen(cause_strings[index]);
if (cause & local_no_collective_cause) {
diff --git a/src/H5Dlayout.c b/src/H5Dlayout.c
index 494d2c8..b882578 100644
--- a/src/H5Dlayout.c
+++ b/src/H5Dlayout.c
@@ -50,6 +50,8 @@
const unsigned H5O_layout_ver_bounds[] = {
H5O_LAYOUT_VERSION_1, /* H5F_LIBVER_EARLIEST */
H5O_LAYOUT_VERSION_3, /* H5F_LIBVER_V18 */ /* H5O_LAYOUT_VERSION_DEFAULT */
+ H5O_LAYOUT_VERSION_4, /* H5F_LIBVER_V110 */
+ H5O_LAYOUT_VERSION_4, /* H5F_LIBVER_V112 */
H5O_LAYOUT_VERSION_LATEST /* H5F_LIBVER_LATEST */
};
@@ -64,7 +66,7 @@ const unsigned H5O_layout_ver_bounds[] = {
-
+
/*-------------------------------------------------------------------------
* Function: H5D__layout_set_io_ops
*
@@ -81,7 +83,7 @@ const unsigned H5O_layout_ver_bounds[] = {
herr_t
H5D__layout_set_io_ops(const H5D_t *dataset)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
@@ -151,7 +153,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__layout_set_io_ops() */
-
+
/*-------------------------------------------------------------------------
* Function: H5D__layout_meta_size
*
@@ -282,7 +284,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__layout_meta_size() */
-
+
/*-------------------------------------------------------------------------
* Function: H5D__layout_set_version
*
@@ -320,7 +322,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__layout_set_version() */
-
+
/*-------------------------------------------------------------------------
* Function: H5D__layout_set_latest_indexing
*
@@ -334,7 +336,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5D__layout_set_latest_indexing(H5O_layout_t *layout, const H5S_t *space,
+H5D__layout_set_latest_indexing(H5O_layout_t *layout, const H5S_t *space,
const H5D_dcpl_cache_t *dcpl_cache)
{
herr_t ret_value = SUCCEED; /* Return value */
@@ -360,9 +362,9 @@ H5D__layout_set_latest_indexing(H5O_layout_t *layout, const H5S_t *space,
if(ndims > 0) {
hsize_t max_dims[H5O_LAYOUT_NDIMS]; /* Maximum dimension sizes */
hsize_t cur_dims[H5O_LAYOUT_NDIMS]; /* Current dimension sizes */
- unsigned unlim_count = 0; /* Count of unlimited max. dimensions */
+ unsigned unlim_count = 0; /* Count of unlimited max. dimensions */
hbool_t single = TRUE; /* Fulfill single chunk indexing */
- unsigned u; /* Local index variable */
+ unsigned u; /* Local index variable */
/* Query the dataspace's dimensions */
if(H5S_get_simple_extent_dims(space, cur_dims, max_dims) < 0)
@@ -416,7 +418,7 @@ H5D__layout_set_latest_indexing(H5O_layout_t *layout, const H5S_t *space,
layout->storage.u.chunk.idx_type = H5D_CHUNK_IDX_SINGLE;
layout->storage.u.chunk.ops = H5D_COPS_SINGLE;
} /* end if */
- else if(!dcpl_cache->pline.nused &&
+ else if(!dcpl_cache->pline.nused &&
dcpl_cache->fill.alloc_time == H5D_ALLOC_TIME_EARLY) {
/* Set the chunk index type to "none" Index */
@@ -444,7 +446,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__layout_set_latest_indexing() */
-
+
/*-------------------------------------------------------------------------
* Function: H5D__layout_oh_create
*
@@ -585,17 +587,17 @@ done:
FUNC_LEAVE_NOAPI_TAG(ret_value)
} /* end H5D__layout_oh_create() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5D__layout_oh_read
+ * Function: H5D__layout_oh_read
*
- * Purpose: Read layout/pline/efl information for dataset
+ * Purpose: Read layout/pline/efl information for dataset
*
- * Return: Success: SUCCEED
- * Failure: FAIL
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Programmer: Quincey Koziol
- * Monday, July 27, 2009
+ * Programmer: Quincey Koziol
+ * Monday, July 27, 2009
*
*-------------------------------------------------------------------------
*/
@@ -679,17 +681,17 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__layout_oh_read() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5D__layout_oh_write
+ * Function: H5D__layout_oh_write
*
- * Purpose: Write layout information for dataset
+ * Purpose: Write layout information for dataset
*
- * Return: Success: SUCCEED
- * Failure: FAIL
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Programmer: Quincey Koziol
- * Monday, July 27, 2009
+ * Programmer: Quincey Koziol
+ * Monday, July 27, 2009
*
*-------------------------------------------------------------------------
*/
diff --git a/src/H5Dmpio.c b/src/H5Dmpio.c
index 2c06800..0dbbe9f 100644
--- a/src/H5Dmpio.c
+++ b/src/H5Dmpio.c
@@ -37,7 +37,6 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5Fprivate.h" /* File access */
#include "H5FDprivate.h" /* File drivers */
-#include "H5FDmpi.h" /* MPI-based file drivers */
#include "H5Iprivate.h" /* IDs */
#include "H5MMprivate.h" /* Memory management */
#include "H5Oprivate.h" /* Object headers */
@@ -89,10 +88,20 @@
/******************/
/* Combine chunk address and chunk info into a struct for better performance. */
typedef struct H5D_chunk_addr_info_t {
- haddr_t chunk_addr;
- H5D_chunk_info_t chunk_info;
+ haddr_t chunk_addr;
+ H5D_chunk_info_t chunk_info;
} H5D_chunk_addr_info_t;
+/* Rank 0 Bcast values */
+typedef enum H5D_mpio_no_rank0_bcast_cause_t {
+ H5D_MPIO_RANK0_BCAST = 0x00,
+ H5D_MPIO_RANK0_NOT_H5S_ALL = 0x01,
+ H5D_MPIO_RANK0_NOT_CONTIGUOUS = 0x02,
+ H5D_MPIO_RANK0_NOT_FIXED_SIZE = 0x04,
+ H5D_MPIO_RANK0_GREATER_THAN_2GB = 0x08
+} H5D_mpio_no_rank0_bcast_cause_t;
+
+
/*
* Information about a single chunk when performing collective filtered I/O. All
* of the fields of one of these structs are initialized at the start of collective
@@ -281,8 +290,10 @@ 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)
{
H5FD_mpio_xfer_t io_xfer_mode; /* MPI I/O transfer mode */
- unsigned local_cause = 0; /* Local reason(s) for breaking collective mode */
- unsigned global_cause = 0; /* Global reason(s) for breaking collective mode */
+ 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 */
FUNC_ENTER_PACKAGE
@@ -296,36 +307,37 @@ H5D__mpio_opt_possible(const H5D_io_info_t *io_info, const H5S_t *file_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)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get MPI-I/O transfer mode")
+ /* Set error flag, but keep going */
+ local_cause[0] |= H5D_MPIO_ERROR_WHILE_CHECKING_COLLECTIVE_POSSIBLE;
if(io_xfer_mode == H5FD_MPIO_INDEPENDENT)
- local_cause |= H5D_MPIO_SET_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 |= H5D_MPIO_MPI_OPT_TYPES_ENV_VAR_DISABLED;
+ local_cause[0] |= H5D_MPIO_MPI_OPT_TYPES_ENV_VAR_DISABLED;
/* Don't allow collective operations if datatype conversions need to happen */
if(!type_info->is_conv_noop)
- local_cause |= H5D_MPIO_DATATYPE_CONVERSION;
+ local_cause[0] |= H5D_MPIO_DATATYPE_CONVERSION;
/* Don't allow collective operations if data transform operations should occur */
if(!type_info->is_xform_noop)
- local_cause |= H5D_MPIO_DATA_TRANSFORMS;
+ local_cause[0] |= H5D_MPIO_DATA_TRANSFORMS;
/* 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 |= H5D_MPIO_NOT_SIMPLE_OR_SCALAR_DATASPACES;
+ local_cause[0] |= H5D_MPIO_NOT_SIMPLE_OR_SCALAR_DATASPACES;
/* 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 |= H5D_MPIO_NOT_CONTIGUOUS_OR_CHUNKED_DATASET;
+ local_cause[0] |= H5D_MPIO_NOT_CONTIGUOUS_OR_CHUNKED_DATASET;
/* check if external-file storage is used */
if(io_info->dset->shared->dcpl_cache.efl.nused > 0)
- local_cause |= H5D_MPIO_NOT_CONTIGUOUS_OR_CHUNKED_DATASET;
+ 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
@@ -340,31 +352,84 @@ H5D__mpio_opt_possible(const H5D_io_info_t *io_info, const H5S_t *file_space,
* is less than 3. The functions needed (MPI_Mprobe and MPI_Imrecv) will
* not be available.
*/
- if (io_info->op_type == H5D_IO_OP_WRITE &&
- io_info->dset->shared->layout.type == H5D_CHUNKED &&
- io_info->dset->shared->dcpl_cache.pline.nused > 0)
- local_cause |= H5D_MPIO_PARALLEL_FILTERED_WRITES_DISABLED;
+ if(io_info->op_type == H5D_IO_OP_WRITE &&
+ io_info->dset->shared->layout.type == H5D_CHUNKED &&
+ io_info->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 contigous 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.
+ */
+ 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)))
+ local_cause[0] |= H5D_MPIO_ERROR_WHILE_CHECKING_COLLECTIVE_POSSIBLE;
+ else {
+ hssize_t snelmts; /* [Signed] # of elements in dataset's dataspace */
+
+ /* 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;
+
+ /* 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 */
+
/* Check for independent I/O */
- if(local_cause & H5D_MPIO_SET_INDEPENDENT)
- global_cause = local_cause;
+ if(local_cause[0] & H5D_MPIO_SET_INDEPENDENT)
+ global_cause[0] = local_cause[0];
else {
int mpi_code; /* MPI error code */
/* Form consensus opinion among all processes about whether to perform
* collective I/O
*/
- if(MPI_SUCCESS != (mpi_code = MPI_Allreduce(&local_cause, &global_cause, 1, MPI_UNSIGNED, MPI_BOR, io_info->comm)))
+ if(MPI_SUCCESS != (mpi_code = MPI_Allreduce(&local_cause, &global_cause, 2, MPI_UNSIGNED, MPI_BOR, io_info->comm)))
HMPI_GOTO_ERROR(FAIL, "MPI_Allreduce failed", mpi_code)
} /* end else */
/* Set the local & global values of no-collective-cause in the API context */
- H5CX_set_mpio_local_no_coll_cause(local_cause);
- H5CX_set_mpio_global_no_coll_cause(global_cause);
+ H5CX_set_mpio_local_no_coll_cause(local_cause[0]);
+ H5CX_set_mpio_global_no_coll_cause(global_cause[0]);
+
+ /* Set read-with-rank0-and-bcast flag if possible */
+ if(global_cause[0] == 0 && global_cause[1] == 0) {
+ H5CX_set_mpio_rank0_bcast(TRUE);
+#ifdef H5_HAVE_INSTRUMENTED_LIBRARY
+ H5CX_test_set_mpio_coll_rank0_bcast(TRUE);
+#endif /* H5_HAVE_INSTRUMENTED_LIBRARY */
+ } /* end if */
/* Set the return value, based on the global cause */
- ret_value = global_cause > 0 ? FALSE : TRUE;
+ ret_value = global_cause[0] > 0 ? FALSE : TRUE;
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -392,7 +457,7 @@ H5D__mpio_select_read(const H5D_io_info_t *io_info, const H5D_type_info_t H5_ATT
FUNC_ENTER_PACKAGE
H5_CHECK_OVERFLOW(mpi_buf_count, hsize_t, size_t);
- if(H5F_block_read(io_info->dset->oloc.file, 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, store_contig->dset_addr, (size_t)mpi_buf_count, io_info->u.rbuf) < 0)
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "can't finish collective parallel read")
done:
@@ -422,7 +487,7 @@ H5D__mpio_select_write(const H5D_io_info_t *io_info, const H5D_type_info_t H5_AT
/*OKAY: CAST DISCARDS CONST QUALIFIER*/
H5_CHECK_OVERFLOW(mpi_buf_count, hsize_t, size_t);
- if(H5F_block_write(io_info->dset->oloc.file, 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, store_contig->dset_addr, (size_t)mpi_buf_count, io_info->u.wbuf) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "can't finish collective parallel write")
done:
@@ -735,6 +800,10 @@ H5D__chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_inf
HDassert(type_info);
HDassert(fm);
+ /* Disable collective metadata reads for chunked dataset I/O operations
+ * in order to prevent potential hangs */
+ H5CX_set_coll_metadata_read(FALSE);
+
/* Check the optional property list for the collective chunk IO optimization option */
if(H5CX_get_mpio_chunk_opt_mode(&chunk_opt_mode) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "couldn't get chunk optimization option")
@@ -1358,7 +1427,7 @@ H5D__link_chunk_filtered_collective_io(H5D_io_info_t *io_info, const H5D_type_in
for (i = 0, offset = 0; i < (size_t) mpi_rank; i++)
offset += num_chunks_selected_array[i];
- HDmemcpy(chunk_list, &collective_chunk_list[offset], num_chunks_selected_array[mpi_rank] * sizeof(H5D_filtered_collective_io_info_t));
+ H5MM_memcpy(chunk_list, &collective_chunk_list[offset], num_chunks_selected_array[mpi_rank] * sizeof(H5D_filtered_collective_io_info_t));
/* Create single MPI type encompassing each selection in the dataspace */
if (H5D__mpio_filtered_collective_write_type(chunk_list, chunk_list_num_entries,
@@ -1484,7 +1553,7 @@ if(H5DEBUG(D))
HGOTO_ERROR(H5E_DATASET, H5E_CANTRECV, FAIL, "unable to obtain MPIO mode")
/* Set up contiguous I/O info object */
- HDmemcpy(&ctg_io_info, io_info, sizeof(ctg_io_info));
+ 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;
@@ -1492,7 +1561,7 @@ if(H5DEBUG(D))
ctg_store.contig.dset_size = (hsize_t)io_info->dset->shared->layout.u.chunk.size;
/* Set up compact I/O info object */
- HDmemcpy(&cpt_io_info, io_info, sizeof(cpt_io_info));
+ 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;
@@ -1719,7 +1788,7 @@ H5D__multi_chunk_filtered_collective_io(H5D_io_info_t *io_info, const H5D_type_i
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "couldn't construct filtered I/O info list")
/* Set up contiguous I/O info object */
- HDmemcpy(&ctg_io_info, io_info, sizeof(ctg_io_info));
+ 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;
@@ -1824,7 +1893,7 @@ H5D__multi_chunk_filtered_collective_io(H5D_io_info_t *io_info, const H5D_type_i
/* Collect the new chunk info back to the local copy, since only the record in the
* collective array gets updated by the chunk re-allocation */
- HDmemcpy(&chunk_list[i].chunk_states.new_chunk, &collective_chunk_list[offset].chunk_states.new_chunk, sizeof(chunk_list[i].chunk_states.new_chunk));
+ H5MM_memcpy(&chunk_list[i].chunk_states.new_chunk, &collective_chunk_list[offset].chunk_states.new_chunk, sizeof(chunk_list[i].chunk_states.new_chunk));
H5_CHECKED_ASSIGN(mpi_type_count, int, chunk_list[i].chunk_states.new_chunk.length, hsize_t);
@@ -2248,7 +2317,7 @@ if(H5DEBUG(D))
/* 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)
+ HMPI_GOTO_ERROR(FAIL, "MPI_BCast failed", mpi_code)
} /* end if */
/* Start at first node in chunk skip list */
@@ -2448,8 +2517,8 @@ H5D__obtain_mpio_mode(H5D_io_info_t* io_info, H5D_chunk_map_t *fm,
/* merge buffer io_mode info and chunk addr into one */
- HDmemcpy(mergebuf, assign_io_mode, total_chunks);
- HDmemcpy(tempbuf, chunk_addr, sizeof(haddr_t) * total_chunks);
+ H5MM_memcpy(mergebuf, assign_io_mode, total_chunks);
+ H5MM_memcpy(tempbuf, chunk_addr, sizeof(haddr_t) * total_chunks);
H5MM_free(nproc_per_chunk);
} /* end if */
@@ -2458,8 +2527,8 @@ H5D__obtain_mpio_mode(H5D_io_info_t* io_info, H5D_chunk_map_t *fm,
if(MPI_SUCCESS != (mpi_code = MPI_Bcast(mergebuf, ((sizeof(haddr_t) + 1) * total_chunks), MPI_BYTE, root, comm)))
HMPI_GOTO_ERROR(FAIL, "MPI_BCast failed", mpi_code)
- HDmemcpy(assign_io_mode, mergebuf, total_chunks);
- HDmemcpy(chunk_addr, tempbuf, sizeof(haddr_t) * total_chunks);
+ H5MM_memcpy(assign_io_mode, mergebuf, total_chunks);
+ H5MM_memcpy(chunk_addr, tempbuf, sizeof(haddr_t) * total_chunks);
#ifdef H5_HAVE_INSTRUMENTED_LIBRARY
{
@@ -2561,7 +2630,7 @@ H5D__construct_filtered_io_info_list(const H5D_io_info_t *io_info, const H5D_typ
local_info_array[i].async_info.receive_buffer_array = NULL;
local_info_array[i].async_info.receive_requests_array = NULL;
- HDmemcpy(local_info_array[i].scaled, chunk_info->scaled, sizeof(chunk_info->scaled));
+ H5MM_memcpy(local_info_array[i].scaled, chunk_info->scaled, sizeof(chunk_info->scaled));
if ((select_npoints = H5S_GET_SELECT_NPOINTS(chunk_info->mspace)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCOUNT, FAIL, "dataspace is invalid")
@@ -2673,6 +2742,9 @@ H5D__chunk_redistribute_shared_chunks(const H5D_io_info_t *io_info, const H5D_ty
if ((mpi_size = H5F_mpi_get_size(io_info->dset->oloc.file)) < 0)
HGOTO_ERROR(H5E_IO, H5E_MPI, FAIL, "unable to obtain mpi size")
+ /* Set to latest format for encoding dataspace */
+ H5CX_set_libver_bounds(NULL);
+
if (*local_chunk_array_num_entries)
if (NULL == (send_requests = (MPI_Request *) H5MM_malloc(*local_chunk_array_num_entries * sizeof(MPI_Request))))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate send requests buffer")
@@ -2734,8 +2806,9 @@ H5D__chunk_redistribute_shared_chunks(const H5D_io_info_t *io_info, const H5D_ty
/* Sort the new list in order of previous owner so that each original owner of a chunk
* entry gets that entry back, with the possibly newly-modified "new_owner" field
*/
- HDqsort(shared_chunks_info_array, shared_chunks_info_array_num_entries,
- sizeof(H5D_filtered_collective_io_info_t), H5D__cmp_filtered_collective_io_info_entry_owner);
+ if(shared_chunks_info_array_num_entries > 1)
+ HDqsort(shared_chunks_info_array, shared_chunks_info_array_num_entries,
+ sizeof(H5D_filtered_collective_io_info_t), H5D__cmp_filtered_collective_io_info_entry_owner);
send_displacements[0] = 0;
for (i = 1; i < (size_t) mpi_size; i++)
@@ -2772,45 +2845,45 @@ H5D__chunk_redistribute_shared_chunks(const H5D_io_info_t *io_info, const H5D_ty
size_t mod_data_size;
/* Look up the chunk and get its file and memory dataspaces */
- if (NULL == (chunk_info = (H5D_chunk_info_t *) H5SL_search(fm->sel_chunks, &chunk_entry->index)))
+ if(NULL == (chunk_info = (H5D_chunk_info_t *) H5SL_search(fm->sel_chunks, &chunk_entry->index)))
HGOTO_ERROR(H5E_DATASPACE, H5E_NOTFOUND, FAIL, "can't locate chunk in skip list")
/* Determine size of serialized chunk file dataspace, plus the size of
* the data being written
*/
- if (H5S_encode(chunk_info->fspace, &mod_data_p, &mod_data_size) < 0)
+ if(H5S_encode(chunk_info->fspace, &mod_data_p, &mod_data_size) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTENCODE, FAIL, "unable to get encoded dataspace size")
- if ((iter_nelmts = H5S_GET_SELECT_NPOINTS(chunk_info->mspace)) < 0)
+ if((iter_nelmts = H5S_GET_SELECT_NPOINTS(chunk_info->mspace)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCOUNT, FAIL, "dataspace is invalid")
mod_data_size += (size_t) iter_nelmts * type_info->src_type_size;
- if (NULL == (mod_data[num_send_requests] = (unsigned char *) H5MM_malloc(mod_data_size)))
+ if(NULL == (mod_data[num_send_requests] = (unsigned char *) H5MM_malloc(mod_data_size)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate chunk modification send buffer")
/* Serialize the chunk's file dataspace into the buffer */
mod_data_p = mod_data[num_send_requests];
- if (H5S_encode(chunk_info->fspace, &mod_data_p, &mod_data_size) < 0)
+ if(H5S_encode(chunk_info->fspace, &mod_data_p, &mod_data_size) < 0)
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) < 0)
+ if(H5S_select_iter_init(mem_iter, chunk_info->mspace, type_info->src_type_size, 0) < 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(!H5D__gather_mem(io_info->u.wbuf, chunk_info->mspace, mem_iter, (size_t)iter_nelmts, mod_data_p))
+ if(0 == H5D__gather_mem(io_info->u.wbuf, mem_iter, (size_t)iter_nelmts, mod_data_p))
HGOTO_ERROR(H5E_IO, H5E_CANTGATHER, FAIL, "couldn't gather from write buffer")
/* Send modification data to new owner */
H5_CHECK_OVERFLOW(mod_data_size, size_t, int)
H5_CHECK_OVERFLOW(chunk_entry->index, hsize_t, int)
- if (MPI_SUCCESS != (mpi_code = MPI_Isend(mod_data[num_send_requests], (int) mod_data_size, MPI_BYTE,
+ if(MPI_SUCCESS != (mpi_code = MPI_Isend(mod_data[num_send_requests], (int) mod_data_size, MPI_BYTE,
chunk_entry->owners.new_owner, (int) chunk_entry->index, io_info->comm, &send_requests[num_send_requests])))
HMPI_GOTO_ERROR(FAIL, "MPI_Isend failed", mpi_code)
- if (mem_iter_init && H5S_SELECT_ITER_RELEASE(mem_iter) < 0)
+ if(mem_iter_init && H5S_SELECT_ITER_RELEASE(mem_iter) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "couldn't release memory selection iterator")
mem_iter_init = FALSE;
@@ -2979,11 +3052,11 @@ H5D__mpio_filtered_collective_write_type(H5D_filtered_collective_io_info_t *chun
} /* end if */
done:
- if (write_buf_array)
+ if(write_buf_array)
H5MM_free(write_buf_array);
- if (file_offset_array)
+ if(file_offset_array)
H5MM_free(file_offset_array);
- if (length_array)
+ if(length_array)
H5MM_free(length_array);
FUNC_LEAVE_NOAPI(ret_value)
@@ -3069,8 +3142,8 @@ H5D__filtered_collective_chunk_entry_io(H5D_filtered_collective_io_info_t *chunk
chunk_entry->chunk_states.new_chunk.length = chunk_entry->chunk_states.chunk_current.length;
/* Currently, these chunk reads are done independently and will likely
- * cause issues with collective metadata reads enabled. In the future,
- * this should be refactored to use collective chunk reads - JTH */
+ * cause issues with collective metadata reads enabled. In the future,
+ * this should be refactored to use collective chunk reads - JTH */
/* Get the original state of parallel I/O transfer mode */
if(H5CX_get_io_xfer_mode(&xfer_mode) < 0)
@@ -3080,7 +3153,7 @@ H5D__filtered_collective_chunk_entry_io(H5D_filtered_collective_io_info_t *chunk
if(H5CX_set_io_xfer_mode(H5FD_MPIO_INDEPENDENT) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set MPI-I/O transfer mode")
- if(H5F_block_read(io_info->dset->oloc.file, H5FD_MEM_DRAW, chunk_entry->chunk_states.chunk_current.offset,
+ if(H5F_shared_block_read(io_info->f_sh, H5FD_MEM_DRAW, chunk_entry->chunk_states.chunk_current.offset,
chunk_entry->chunk_states.new_chunk.length, chunk_entry->buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "unable to read raw data chunk")
@@ -3101,7 +3174,7 @@ H5D__filtered_collective_chunk_entry_io(H5D_filtered_collective_io_info_t *chunk
if (NULL == (mem_iter = (H5S_sel_iter_t *) H5MM_malloc(sizeof(H5S_sel_iter_t))))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate memory iterator")
- if (H5S_select_iter_init(mem_iter, chunk_info->mspace, type_info->src_type_size) < 0)
+ if(H5S_select_iter_init(mem_iter, chunk_info->mspace, type_info->src_type_size, 0) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize memory selection information")
mem_iter_init = TRUE;
@@ -3111,99 +3184,99 @@ H5D__filtered_collective_chunk_entry_io(H5D_filtered_collective_io_info_t *chunk
* from the current process, then apply any modifications from other processes. Finally,
* filter the newly-updated chunk.
*/
- switch (io_info->op_type) {
+ switch(io_info->op_type) {
case H5D_IO_OP_READ:
- if (NULL == (file_iter = (H5S_sel_iter_t *) H5MM_malloc(sizeof(H5S_sel_iter_t))))
+ if(NULL == (file_iter = (H5S_sel_iter_t *) H5MM_malloc(sizeof(H5S_sel_iter_t))))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate file iterator")
- if (H5S_select_iter_init(file_iter, chunk_info->fspace, type_info->src_type_size) < 0)
+ if(H5S_select_iter_init(file_iter, chunk_info->fspace, type_info->src_type_size, 0) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize memory selection information")
file_iter_init = TRUE;
- if ((iter_nelmts = H5S_GET_SELECT_NPOINTS(chunk_info->fspace)) < 0)
+ if((iter_nelmts = H5S_GET_SELECT_NPOINTS(chunk_info->fspace)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCOUNT, FAIL, "dataspace is invalid")
- if (NULL == (tmp_gath_buf = H5MM_malloc((hsize_t) iter_nelmts * type_info->src_type_size)))
+ if(NULL == (tmp_gath_buf = H5MM_malloc((hsize_t) iter_nelmts * type_info->src_type_size)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate temporary gather buffer")
- if (!H5D__gather_mem(chunk_entry->buf, chunk_info->fspace, file_iter, (size_t) iter_nelmts, tmp_gath_buf))
+ if(!H5D__gather_mem(chunk_entry->buf, file_iter, (size_t) iter_nelmts, tmp_gath_buf))
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "couldn't gather from chunk buffer")
- if ((iter_nelmts = H5S_GET_SELECT_NPOINTS(chunk_info->mspace)) < 0)
+ if((iter_nelmts = H5S_GET_SELECT_NPOINTS(chunk_info->mspace)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCOUNT, FAIL, "dataspace is invalid")
- if (H5D__scatter_mem(tmp_gath_buf, chunk_info->mspace, mem_iter, (size_t) iter_nelmts, io_info->u.rbuf) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "couldn't scatter to read buffer")
+ if(H5D__scatter_mem(tmp_gath_buf, mem_iter, (size_t) iter_nelmts, io_info->u.rbuf) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "couldn't scatter to read buffer")
break;
case H5D_IO_OP_WRITE:
- if ((iter_nelmts = H5S_GET_SELECT_NPOINTS(chunk_info->mspace)) < 0)
+ if((iter_nelmts = H5S_GET_SELECT_NPOINTS(chunk_info->mspace)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCOUNT, FAIL, "dataspace is invalid")
- if (NULL == (tmp_gath_buf = H5MM_malloc((hsize_t) iter_nelmts * type_info->src_type_size)))
+ if(NULL == (tmp_gath_buf = H5MM_malloc((hsize_t) iter_nelmts * type_info->src_type_size)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate temporary gather buffer")
/* Gather modification data from the application write buffer into a temporary buffer */
- if(!H5D__gather_mem(io_info->u.wbuf, chunk_info->mspace, mem_iter, (size_t) iter_nelmts, tmp_gath_buf))
+ if(0 == H5D__gather_mem(io_info->u.wbuf, mem_iter, (size_t) iter_nelmts, tmp_gath_buf))
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "couldn't gather from write buffer")
- if (H5S_SELECT_ITER_RELEASE(mem_iter) < 0)
+ if(H5S_SELECT_ITER_RELEASE(mem_iter) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "couldn't release selection iterator")
mem_iter_init = FALSE;
/* Initialize iterator for file selection */
- if (H5S_select_iter_init(mem_iter, chunk_info->fspace, type_info->dst_type_size) < 0)
+ if(H5S_select_iter_init(mem_iter, chunk_info->fspace, type_info->dst_type_size, 0) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize file selection information")
mem_iter_init = TRUE;
- if ((iter_nelmts = H5S_GET_SELECT_NPOINTS(chunk_info->fspace)) < 0)
+ if((iter_nelmts = H5S_GET_SELECT_NPOINTS(chunk_info->fspace)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCOUNT, FAIL, "dataspace is invalid")
/* Scatter the owner's modification data into the chunk data buffer according to
* the file space.
*/
- if(H5D__scatter_mem(tmp_gath_buf, chunk_info->fspace, mem_iter, (size_t) iter_nelmts, chunk_entry->buf) < 0)
+ if(H5D__scatter_mem(tmp_gath_buf, mem_iter, (size_t) iter_nelmts, chunk_entry->buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "couldn't scatter to chunk data buffer")
- if (H5S_SELECT_ITER_RELEASE(mem_iter) < 0)
+ if(H5S_SELECT_ITER_RELEASE(mem_iter) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "couldn't release selection iterator")
mem_iter_init = FALSE;
- if (MPI_SUCCESS != (mpi_code = MPI_Waitall(chunk_entry->async_info.num_receive_requests,
+ if(MPI_SUCCESS != (mpi_code = MPI_Waitall(chunk_entry->async_info.num_receive_requests,
chunk_entry->async_info.receive_requests_array, MPI_STATUSES_IGNORE)))
HMPI_GOTO_ERROR(FAIL, "MPI_Waitall failed", mpi_code)
/* For each asynchronous receive call previously posted, receive the chunk modification
* buffer from another rank and update the chunk data
*/
- for (i = 0; i < (size_t) chunk_entry->async_info.num_receive_requests; i++) {
+ for(i = 0; i < (size_t) chunk_entry->async_info.num_receive_requests; i++) {
const unsigned char *mod_data_p;
/* Decode the process' chunk file dataspace */
mod_data_p = chunk_entry->async_info.receive_buffer_array[i];
- if (NULL == (dataspace = H5S_decode(&mod_data_p)))
+ if(NULL == (dataspace = H5S_decode(&mod_data_p)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTDECODE, FAIL, "unable to decode dataspace")
- if (H5S_select_iter_init(mem_iter, dataspace, type_info->dst_type_size) < 0)
+ if(H5S_select_iter_init(mem_iter, dataspace, type_info->dst_type_size, 0) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize memory selection information")
mem_iter_init = TRUE;
- if ((iter_nelmts = H5S_GET_SELECT_NPOINTS(dataspace)) < 0)
+ if((iter_nelmts = H5S_GET_SELECT_NPOINTS(dataspace)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCOUNT, FAIL, "dataspace is invalid")
/* Update the chunk data with the received modification data */
- if(H5D__scatter_mem(mod_data_p, dataspace, mem_iter, (size_t) iter_nelmts, chunk_entry->buf) < 0)
+ if(H5D__scatter_mem(mod_data_p, mem_iter, (size_t) iter_nelmts, chunk_entry->buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "couldn't scatter to write buffer")
- if (H5S_SELECT_ITER_RELEASE(mem_iter) < 0)
+ if(H5S_SELECT_ITER_RELEASE(mem_iter) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "couldn't release selection iterator")
mem_iter_init = FALSE;
- if (dataspace) {
- if (H5S_close(dataspace) < 0)
+ if(dataspace) {
+ if(H5S_close(dataspace) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTFREE, FAIL, "can't close dataspace")
dataspace = NULL;
- }
+ } /* end if */
H5MM_free(chunk_entry->async_info.receive_buffer_array[i]);
} /* end for */
diff --git a/src/H5Dnone.c b/src/H5Dnone.c
index be421b6..9346220 100644
--- a/src/H5Dnone.c
+++ b/src/H5Dnone.c
@@ -242,9 +242,9 @@ H5D__none_idx_iterate(const H5D_chk_idx_info_t *idx_info,
unsigned u; /* Local index variable */
int curr_dim; /* Current rank */
hsize_t idx; /* Array index of chunk */
- int ret_value = -1; /* Return value */
+ int ret_value = H5_ITER_CONT; /* Return value */
- FUNC_ENTER_STATIC_NOERR
+ FUNC_ENTER_STATIC
/* Sanity checks */
HDassert(idx_info);
@@ -266,34 +266,35 @@ H5D__none_idx_iterate(const H5D_chk_idx_info_t *idx_info,
HDassert(ndims > 0);
/* Iterate over all the chunks in the dataset's dataspace */
- for(u = 0; u < idx_info->layout->nchunks; u++) {
- /* Calculate the index of this chunk */
- idx = H5VM_array_offset_pre(ndims, idx_info->layout->max_down_chunks, chunk_rec.scaled);
-
- /* Calculate the address of the chunk */
- chunk_rec.chunk_addr = idx_info->storage->idx_addr + idx * idx_info->layout->size;
-
- /* Make "generic chunk" callback */
- if((ret_value = (*chunk_cb)(&chunk_rec, chunk_udata)) < 0)
- HERROR(H5E_DATASET, H5E_CALLBACK, "failure in generic chunk iterator callback");
-
- /* Update coordinates of chunk in dataset */
- curr_dim = (int)(ndims - 1);
- while(curr_dim >= 0) {
- /* Increment coordinate in current dimension */
- chunk_rec.scaled[curr_dim]++;
-
- /* Check if we went off the end of the current dimension */
- if(chunk_rec.scaled[curr_dim] >= idx_info->layout->chunks[curr_dim]) {
- /* Reset coordinate & move to next faster dimension */
- chunk_rec.scaled[curr_dim] = 0;
- curr_dim--;
- } /* end if */
- else
- break;
- } /* end while */
+ for(u = 0; u < idx_info->layout->nchunks && ret_value == H5_ITER_CONT; u++) {
+ /* Calculate the index of this chunk */
+ idx = H5VM_array_offset_pre(ndims, idx_info->layout->max_down_chunks, chunk_rec.scaled);
+
+ /* Calculate the address of the chunk */
+ chunk_rec.chunk_addr = idx_info->storage->idx_addr + idx * idx_info->layout->size;
+
+ /* Make "generic chunk" callback */
+ if((ret_value = (*chunk_cb)(&chunk_rec, chunk_udata)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CALLBACK, H5_ITER_ERROR, "failure in generic chunk iterator callback")
+
+ /* Update coordinates of chunk in dataset */
+ curr_dim = (int)(ndims - 1);
+ while(curr_dim >= 0) {
+ /* Increment coordinate in current dimension */
+ chunk_rec.scaled[curr_dim]++;
+
+ /* Check if we went off the end of the current dimension */
+ if(chunk_rec.scaled[curr_dim] >= idx_info->layout->chunks[curr_dim]) {
+ /* Reset coordinate & move to next faster dimension */
+ chunk_rec.scaled[curr_dim] = 0;
+ curr_dim--;
+ } /* end if */
+ else
+ break;
+ } /* end while */
} /* end for */
+done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__none_idx_iterate() */
diff --git a/src/H5Doh.c b/src/H5Doh.c
index 38d0914..017bab7 100644
--- a/src/H5Doh.c
+++ b/src/H5Doh.c
@@ -29,6 +29,7 @@
#include "H5FLprivate.h" /* Free lists */
#include "H5Iprivate.h" /* IDs */
#include "H5Opkg.h" /* Object headers */
+#include "H5VLprivate.h" /* Virtual Object Layer */
/****************/
@@ -47,7 +48,7 @@
static void *H5O__dset_get_copy_file_udata(void);
static void H5O__dset_free_copy_file_udata(void *);
static htri_t H5O__dset_isa(const H5O_t *loc);
-static hid_t H5O__dset_open(const H5G_loc_t *obj_loc, hbool_t app_ref);
+static void *H5O__dset_open(const H5G_loc_t *obj_loc, H5I_type_t *opened_type);
static void *H5O__dset_create(H5F_t *f, void *_crt_info, H5G_loc_t *obj_loc);
static H5O_loc_t *H5O__dset_get_oloc(hid_t obj_id);
static herr_t H5O__dset_bh_info(const H5O_loc_t *loc, H5O_t *oh,
@@ -217,17 +218,19 @@ done:
*
*-------------------------------------------------------------------------
*/
-static hid_t
-H5O__dset_open(const H5G_loc_t *obj_loc, hbool_t app_ref)
+static void *
+H5O__dset_open(const H5G_loc_t *obj_loc, H5I_type_t *opened_type)
{
- H5D_t *dset = NULL; /* Dataset opened */
- hid_t dapl_id; /* dapl to use to open this dataset */
- hid_t ret_value = H5I_INVALID_HID; /* Return value */
+ H5D_t *dset = NULL; /* Dataset opened */
+ hid_t dapl_id; /* dapl to use to open this dataset */
+ void *ret_value = NULL; /* Return value */
FUNC_ENTER_STATIC
HDassert(obj_loc);
+ *opened_type = H5I_DATASET;
+
/* Get the LAPL (which is a superclass of DAPLs) from the API context, but
* if it's the default link access property list or a custom link access
* property list but not a dataset access property list, use the default
@@ -242,9 +245,9 @@ H5O__dset_open(const H5G_loc_t *obj_loc, hbool_t app_ref)
/* Check class of LAPL from API context */
if((is_lapl = H5P_isa_class(dapl_id, H5P_LINK_ACCESS)) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, H5I_INVALID_HID, "unable to get LAPL status")
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, NULL, "unable to get LAPL status")
if((is_dapl = H5P_isa_class(dapl_id, H5P_DATASET_ACCESS)) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, H5I_INVALID_HID, "unable to get DAPL status")
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, NULL, "unable to get DAPL status")
/* Switch to default DAPL if not an actual DAPL in the API context */
if(!is_dapl && is_lapl)
@@ -253,16 +256,14 @@ H5O__dset_open(const H5G_loc_t *obj_loc, hbool_t app_ref)
/* Open the dataset */
if(NULL == (dset = H5D_open(obj_loc, dapl_id)))
- HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open dataset")
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, NULL, "unable to open dataset")
- /* Register an ID for the dataset */
- if((ret_value = H5I_register(H5I_DATASET, dset, app_ref)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register dataset")
+ ret_value = (void *)dset;
done:
- if(H5I_INVALID_HID == ret_value)
+ if(NULL == ret_value)
if(dset && H5D_close(dset) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, H5I_INVALID_HID, "unable to release dataset")
+ HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, NULL, "unable to release dataset")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O__dset_open() */
@@ -339,7 +340,7 @@ H5O__dset_get_oloc(hid_t obj_id)
FUNC_ENTER_STATIC
/* Get the dataset */
- if(NULL == (dset = (H5D_t *)H5I_object(obj_id)))
+ if(NULL == (dset = (H5D_t *)H5VL_object(obj_id)))
HGOTO_ERROR(H5E_OHDR, H5E_BADATOM, NULL, "couldn't get object from ID")
/* Get the dataset's object header location */
diff --git a/src/H5Dpkg.h b/src/H5Dpkg.h
index 591fcb1..723acf9 100644
--- a/src/H5Dpkg.h
+++ b/src/H5Dpkg.h
@@ -47,11 +47,13 @@
/* [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
@@ -113,12 +115,14 @@ typedef struct H5D_type_info_t {
/* Forward declaration of structs used below */
struct H5D_io_info_t;
struct H5D_chunk_map_t;
+typedef struct H5D_shared_t H5D_shared_t;
/* Function pointers for I/O on particular types of dataset layouts */
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)(const struct H5D_io_info_t *io_info,
const H5D_type_info_t *type_info,
hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space,
@@ -144,6 +148,7 @@ typedef struct H5D_layout_ops_t {
H5D_layout_construct_func_t construct; /* Layout constructor for new datasets */
H5D_layout_init_func_t init; /* Layout initializer for dataset */
H5D_layout_is_space_alloc_func_t is_space_alloc; /* Query routine to determine if storage is allocated */
+ 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 */
@@ -204,6 +209,8 @@ typedef enum H5D_io_op_type_t {
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? */
+ 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 */
@@ -429,7 +436,7 @@ typedef struct H5D_rdcdc_t {
* created once for a given dataset. Thus, if a dataset is opened twice,
* there will be two IDs and two H5D_t structs, both sharing one H5D_shared_t.
*/
-typedef struct H5D_shared_t {
+struct H5D_shared_t {
size_t fo_count; /* Reference count */
hbool_t closing; /* Flag to indicate dataset is closing */
hid_t type_id; /* ID for dataset's datatype */
@@ -459,7 +466,7 @@ typedef struct H5D_shared_t {
H5D_append_flush_t append_flush; /* Append flush property information */
char *extfile_prefix; /* expanded external file prefix */
char *vds_prefix; /* expanded vds prefix */
-} H5D_shared_t;
+};
struct H5D_t {
H5O_loc_t oloc; /* Object header location */
@@ -510,7 +517,7 @@ typedef struct H5D_fill_buf_info_t {
/* Internal data structure for computing variable-length dataset's total size */
typedef struct {
- H5D_t *dset; /* Dataset for operation */
+ H5VL_object_t *dset_vol_obj; /* VOL object for the dataset */
hid_t fspace_id; /* File dataspace ID of the dataset we are working on */
hid_t mspace_id; /* Memory dataspace ID of the dataset we are working on */
void *fl_tbuf; /* Ptr to the temporary buffer we are using for fixed-length data */
@@ -562,6 +569,9 @@ H5_DLL herr_t H5D__get_space_status(const H5D_t *dset, H5D_space_status_t *alloc
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__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__get_num_chunks(const H5D_t *dset, const H5S_t *space, hsize_t *nchunks);
+H5_DLL herr_t H5D__get_chunk_info(const H5D_t *dset, const H5S_t *space, hsize_t chk_idx, hsize_t *coord, unsigned *filter_mask, haddr_t *offset, hsize_t *size);
+H5_DLL herr_t H5D__get_chunk_info_by_coord(const H5D_t *dset, const hsize_t *coord, unsigned *filter_mask, haddr_t *addr, hsize_t *size);
H5_DLL haddr_t H5D__get_offset(const H5D_t *dset);
H5_DLL void *H5D__vlen_get_buf_size_alloc(size_t size, void *info);
H5_DLL herr_t H5D__vlen_get_buf_size(void *elem, hid_t type_id, unsigned ndim, const hsize_t *point, void *op_data);
@@ -591,10 +601,10 @@ H5_DLL herr_t H5D__select_write(const H5D_io_info_t *io_info,
hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space);
/* Functions that perform scatter-gather serial I/O operations */
-H5_DLL herr_t H5D__scatter_mem(const void *_tscat_buf, const H5S_t *space,
- H5S_sel_iter_t *iter, size_t nelmts, void *_buf);
-H5_DLL size_t H5D__gather_mem(const void *_buf, const H5S_t *space,
- H5S_sel_iter_t *iter, size_t nelmts, void *_tgath_buf/*out*/);
+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, const H5S_t *file_space, const H5S_t *mem_space);
@@ -618,6 +628,7 @@ H5_DLL herr_t H5D__layout_oh_write(const H5D_t *dataset, H5O_t *oh, unsigned upd
/* Functions that operate on contiguous storage */
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, const H5S_t *file_space, const H5S_t *mem_space,
@@ -636,12 +647,13 @@ H5_DLL htri_t H5D__chunk_cacheable(const H5D_io_info_t *io_info, haddr_t caddr,
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, 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, hsize_t scaled[]);
+ H5F_block_t *new_chunk, hbool_t *need_insert, const hsize_t *scaled);
H5_DLL herr_t H5D__chunk_update_old_edge_chunks(H5D_t *dset, hsize_t old_dim[]);
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);
diff --git a/src/H5Dprivate.h b/src/H5Dprivate.h
index cbee0de..9a5277f 100644
--- a/src/H5Dprivate.h
+++ b/src/H5Dprivate.h
@@ -45,6 +45,7 @@
#define H5D_CRT_FILL_VALUE_NAME "fill_value" /* Fill value */
#define H5D_CRT_ALLOC_TIME_STATE_NAME "alloc_time_state" /* Space allocation time state */
#define H5D_CRT_EXT_FILE_LIST_NAME "efl" /* External file list */
+#define H5D_CRT_MIN_DSET_HDR_SIZE_NAME "dset_oh_minimize"/* Minimize object header */
/* ======== Dataset access property names ======== */
#define H5D_ACS_DATA_CACHE_NUM_SLOTS_NAME "rdcc_nslots" /* Size of raw data chunk cache(slots) */
@@ -94,7 +95,13 @@
/* Definitions for all collective chunk instrumentation properties */
#define H5D_XFER_COLL_CHUNK_SIZE sizeof(unsigned)
#define H5D_XFER_COLL_CHUNK_DEF 1
-#define H5D_XFER_COLL_CHUNK_FIX 0
+
+/* General collective I/O instrumentation properties */
+#define H5D_XFER_COLL_RANK0_BCAST_NAME "coll_rank0_bcast"
+
+/* Definitions for general collective I/O instrumentation properties */
+#define H5D_XFER_COLL_RANK0_BCAST_SIZE sizeof(hbool_t)
+#define H5D_XFER_COLL_RANK0_BCAST_DEF FALSE
#endif /* H5_HAVE_INSTRUMENTED_LIBRARY */
/* Default temporary buffer size */
@@ -158,15 +165,11 @@ H5_DLL herr_t H5D_close(H5D_t *dataset);
H5_DLL herr_t H5D_mult_refresh_close(hid_t dset_id);
H5_DLL herr_t H5D_mult_refresh_reopen(H5D_t *dataset);
H5_DLL H5O_loc_t *H5D_oloc(H5D_t *dataset);
-H5_DLL H5G_name_t *H5D_nameof(H5D_t *dataset);
-H5_DLL H5T_t *H5D_typeof(const H5D_t *dset);
-H5_DLL herr_t H5D_flush_all(const H5F_t *f);
+H5_DLL H5G_name_t *H5D_nameof(const H5D_t *dataset);
+H5_DLL herr_t H5D_flush_all(H5F_t *f);
H5_DLL hid_t H5D_get_create_plist(const H5D_t *dset);
H5_DLL hid_t H5D_get_access_plist(const H5D_t *dset);
-/* Functions that operate on vlen data */
-H5_DLL herr_t H5D_vlen_reclaim(hid_t type_id, H5S_t *space, void *buf);
-
/* Functions that operate on chunked storage */
H5_DLL herr_t H5D_chunk_idx_reset(H5O_storage_chunk_t *storage, hbool_t reset_addr);
diff --git a/src/H5Dpublic.h b/src/H5Dpublic.h
index a1ccda0..281da81 100644
--- a/src/H5Dpublic.h
+++ b/src/H5Dpublic.h
@@ -104,17 +104,6 @@ typedef enum H5D_vds_view_t {
/* Callback for H5Pset_append_flush() in a dataset access property list */
typedef herr_t (*H5D_append_cb_t)(hid_t dataset_id, hsize_t *cur_dims, void *op_data);
-/********************/
-/* Public Variables */
-/********************/
-
-/*********************/
-/* Public Prototypes */
-/*********************/
-#ifdef __cplusplus
-extern "C" {
-#endif
-
/* Define the operator function pointer for H5Diterate() */
typedef herr_t (*H5D_operator_t)(void *elem, hid_t type_id, unsigned ndim,
const hsize_t *point, void *operator_data);
@@ -128,6 +117,18 @@ typedef herr_t (*H5D_scatter_func_t)(const void **src_buf/*out*/,
typedef herr_t (*H5D_gather_func_t)(const void *dst_buf,
size_t dst_buf_bytes_used, void *op_data);
+
+/********************/
+/* Public Variables */
+/********************/
+
+/*********************/
+/* Public Prototypes */
+/*********************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
H5_DLL hid_t H5Dcreate2(hid_t loc_id, const char *name, hid_t type_id,
hid_t space_id, hid_t lcpl_id, hid_t dcpl_id, hid_t dapl_id);
H5_DLL hid_t H5Dcreate_anon(hid_t file_id, hid_t type_id, hid_t space_id,
@@ -141,6 +142,9 @@ H5_DLL hid_t H5Dget_create_plist(hid_t dset_id);
H5_DLL hid_t H5Dget_access_plist(hid_t dset_id);
H5_DLL hsize_t H5Dget_storage_size(hid_t dset_id);
H5_DLL herr_t H5Dget_chunk_storage_size(hid_t dset_id, const hsize_t *offset, hsize_t *chunk_bytes);
+H5_DLL herr_t H5Dget_num_chunks(hid_t dset_id, hid_t fspace_id, hsize_t *nchunks);
+H5_DLL herr_t H5Dget_chunk_info_by_coord(hid_t dset_id, const hsize_t *coord, unsigned *filter_mask, haddr_t *addr, hsize_t *size);
+H5_DLL herr_t H5Dget_chunk_info(hid_t dset_id, hid_t fspace_id, hsize_t chk_idx, hsize_t *coord, unsigned *filter_mask, haddr_t *addr, hsize_t *size);
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 plist_id, void *buf/*out*/);
@@ -152,7 +156,6 @@ H5_DLL herr_t H5Dread_chunk(hid_t dset_id, hid_t dxpl_id,
const hsize_t *offset, uint32_t *filters, void *buf);
H5_DLL herr_t H5Diterate(void *buf, hid_t type_id, hid_t space_id,
H5D_operator_t op, void *operator_data);
-H5_DLL herr_t H5Dvlen_reclaim(hid_t type_id, hid_t space_id, hid_t plist_id, void *buf);
H5_DLL herr_t H5Dvlen_get_buf_size(hid_t dataset_id, hid_t type_id, hid_t space_id, hsize_t *size);
H5_DLL herr_t H5Dfill(const void *fill, hid_t fill_type, void *buf,
hid_t buf_type, hid_t space);
@@ -199,6 +202,7 @@ H5_DLL hid_t H5Dcreate1(hid_t file_id, const char *name, hid_t type_id,
hid_t space_id, hid_t dcpl_id);
H5_DLL hid_t H5Dopen1(hid_t file_id, const char *name);
H5_DLL herr_t H5Dextend(hid_t dset_id, const hsize_t size[]);
+H5_DLL herr_t H5Dvlen_reclaim(hid_t type_id, hid_t space_id, hid_t plist_id, void *buf);
#endif /* H5_NO_DEPRECATED_SYMBOLS */
diff --git a/src/H5Dscatgath.c b/src/H5Dscatgath.c
index 266f5f5..cdf9da2 100644
--- a/src/H5Dscatgath.c
+++ b/src/H5Dscatgath.c
@@ -27,6 +27,7 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5FLprivate.h" /* Free Lists */
#include "H5Iprivate.h" /* IDs */
+#include "H5MMprivate.h" /* Memory management */
/****************/
@@ -43,13 +44,11 @@
/* Local Prototypes */
/********************/
static herr_t H5D__scatter_file(const H5D_io_info_t *io_info,
- const H5S_t *file_space, H5S_sel_iter_t *file_iter, size_t nelmts,
- const void *buf);
+ 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 H5S_t *file_space, H5S_sel_iter_t *file_iter, size_t nelmts,
- void *buf);
-static herr_t H5D__compound_opt_read(size_t nelmts, const H5S_t *mem_space,
- H5S_sel_iter_t *iter, const H5D_type_info_t *type_info, void *user_buf/*out*/);
+ 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);
@@ -90,9 +89,8 @@ H5FL_SEQ_EXTERN(hsize_t);
*-------------------------------------------------------------------------
*/
static herr_t
-H5D__scatter_file(const H5D_io_info_t *_io_info,
- const H5S_t *space, H5S_sel_iter_t *iter, size_t nelmts,
- const void *_buf)
+H5D__scatter_file(const H5D_io_info_t *_io_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 */
@@ -111,13 +109,12 @@ H5D__scatter_file(const H5D_io_info_t *_io_info,
/* Check args */
HDassert(_io_info);
- HDassert(space);
HDassert(iter);
HDassert(nelmts > 0);
HDassert(_buf);
/* Set up temporary I/O info object */
- HDmemcpy(&tmp_io_info, _io_info, sizeof(*_io_info));
+ 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;
@@ -138,7 +135,7 @@ H5D__scatter_file(const H5D_io_info_t *_io_info,
/* Loop until all elements are written */
while(nelmts > 0) {
/* Get list of sequences for selection to write */
- if(H5S_SELECT_GET_SEQ_LIST(space, H5S_GET_SEQ_LIST_SORTED, iter, vec_size, nelmts, &nseq, &nelem, off, len) < 0)
+ if(H5S_SELECT_ITER_GET_SEQ_LIST(iter, vec_size, nelmts, &nseq, &nelem, off, len) < 0)
HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed")
/* Reset the current sequence information */
@@ -191,9 +188,8 @@ done:
*-------------------------------------------------------------------------
*/
static size_t
-H5D__gather_file(const H5D_io_info_t *_io_info,
- const H5S_t *space, H5S_sel_iter_t *iter, size_t nelmts,
- void *_buf/*out*/)
+H5D__gather_file(const H5D_io_info_t *_io_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 */
@@ -214,13 +210,12 @@ H5D__gather_file(const H5D_io_info_t *_io_info,
HDassert(_io_info);
HDassert(_io_info->dset);
HDassert(_io_info->store);
- HDassert(space);
HDassert(iter);
HDassert(nelmts > 0);
HDassert(_buf);
/* Set up temporary I/O info object */
- HDmemcpy(&tmp_io_info, _io_info, sizeof(*_io_info));
+ 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;
@@ -241,7 +236,7 @@ H5D__gather_file(const H5D_io_info_t *_io_info,
/* Loop until all elements are read */
while(nelmts > 0) {
/* Get list of sequences for selection to read */
- if(H5S_SELECT_GET_SEQ_LIST(space, H5S_GET_SEQ_LIST_SORTED, iter, vec_size, nelmts, &nseq, &nelem, off, len) < 0)
+ if(H5S_SELECT_ITER_GET_SEQ_LIST(iter, vec_size, nelmts, &nseq, &nelem, off, len) < 0)
HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, 0, "sequence length generation failed")
/* Reset the current sequence information */
@@ -288,8 +283,8 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5D__scatter_mem (const void *_tscat_buf, const H5S_t *space,
- H5S_sel_iter_t *iter, size_t nelmts, void *_buf/*out*/)
+H5D__scatter_mem(const void *_tscat_buf, H5S_sel_iter_t *iter, size_t nelmts,
+ void *_buf/*out*/)
{
uint8_t *buf = (uint8_t *)_buf; /* Get local copies for address arithmetic */
const uint8_t *tscat_buf = (const uint8_t *)_tscat_buf;
@@ -307,7 +302,6 @@ H5D__scatter_mem (const void *_tscat_buf, const H5S_t *space,
/* Check args */
HDassert(tscat_buf);
- HDassert(space);
HDassert(iter);
HDassert(nelmts > 0);
HDassert(buf);
@@ -329,7 +323,7 @@ H5D__scatter_mem (const void *_tscat_buf, const H5S_t *space,
/* Loop until all elements are written */
while(nelmts > 0) {
/* Get list of sequences for selection to write */
- if(H5S_SELECT_GET_SEQ_LIST(space, 0, iter, vec_size, nelmts, &nseq, &nelem, off, len) < 0)
+ if(H5S_SELECT_ITER_GET_SEQ_LIST(iter, vec_size, nelmts, &nseq, &nelem, off, len) < 0)
HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, 0, "sequence length generation failed")
/* Loop, while sequences left to process */
@@ -337,7 +331,7 @@ H5D__scatter_mem (const void *_tscat_buf, const H5S_t *space,
/* Get the number of bytes in sequence */
curr_len = len[curr_seq];
- HDmemcpy(buf + off[curr_seq], tscat_buf, curr_len);
+ H5MM_memcpy(buf + off[curr_seq], tscat_buf, curr_len);
/* Advance offset in destination buffer */
tscat_buf += curr_len;
@@ -376,8 +370,8 @@ done:
*-------------------------------------------------------------------------
*/
size_t
-H5D__gather_mem(const void *_buf, const H5S_t *space,
- H5S_sel_iter_t *iter, size_t nelmts, void *_tgath_buf/*out*/)
+H5D__gather_mem(const void *_buf, H5S_sel_iter_t *iter, size_t nelmts,
+ void *_tgath_buf/*out*/)
{
const uint8_t *buf = (const uint8_t *)_buf; /* Get local copies for address arithmetic */
uint8_t *tgath_buf = (uint8_t *)_tgath_buf;
@@ -395,7 +389,6 @@ H5D__gather_mem(const void *_buf, const H5S_t *space,
/* Check args */
HDassert(buf);
- HDassert(space);
HDassert(iter);
HDassert(nelmts > 0);
HDassert(tgath_buf);
@@ -417,7 +410,7 @@ H5D__gather_mem(const void *_buf, const H5S_t *space,
/* Loop until all elements are written */
while(nelmts > 0) {
/* Get list of sequences for selection to write */
- if(H5S_SELECT_GET_SEQ_LIST(space, 0, iter, vec_size, nelmts, &nseq, &nelem, off, len) < 0)
+ if(H5S_SELECT_ITER_GET_SEQ_LIST(iter, vec_size, nelmts, &nseq, &nelem, off, len) < 0)
HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, 0, "sequence length generation failed")
/* Loop, while sequences left to process */
@@ -425,7 +418,7 @@ H5D__gather_mem(const void *_buf, const H5S_t *space,
/* Get the number of bytes in sequence */
curr_len = len[curr_seq];
- HDmemcpy(tgath_buf, buf + off[curr_seq], curr_len);
+ H5MM_memcpy(tgath_buf, buf + off[curr_seq], curr_len);
/* Advance offset in gather buffer */
tgath_buf += curr_len;
@@ -495,13 +488,13 @@ 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) < 0)
+ if(H5S_select_iter_init(file_iter, file_space, 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)
+ if(H5S_select_iter_init(mem_iter, mem_space, 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)
+ if(H5S_select_iter_init(bkg_iter, mem_space, 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 */
@@ -522,7 +515,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_space, file_iter, smine_nelmts, type_info->tconv_buf/*out*/);
+ n = H5D__gather_file(io_info, file_iter, smine_nelmts, type_info->tconv_buf/*out*/);
if(n != smine_nelmts)
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file gather failed")
@@ -531,12 +524,12 @@ H5D__scatgath_read(const H5D_io_info_t *io_info, const H5D_type_info_t *type_inf
* 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_space, mem_iter, type_info, buf /*out*/) < 0)
+ if(H5D__compound_opt_read(smine_nelmts, mem_iter, type_info, 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, mem_space, bkg_iter, smine_nelmts, type_info->bkg_buf/*out*/);
+ n = H5D__gather_mem(buf, bkg_iter, smine_nelmts, type_info->bkg_buf/*out*/);
if(n != smine_nelmts)
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "mem gather failed")
} /* end if */
@@ -562,7 +555,7 @@ H5D__scatgath_read(const H5D_io_info_t *io_info, const H5D_type_info_t *type_inf
}
/* Scatter the data into memory */
- if(H5D__scatter_mem(type_info->tconv_buf, mem_space, mem_iter, smine_nelmts, buf/*out*/) < 0)
+ if(H5D__scatter_mem(type_info->tconv_buf, mem_iter, smine_nelmts, buf/*out*/) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "scatter failed")
} /* end else */
} /* end for */
@@ -635,13 +628,13 @@ 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) < 0)
+ if(H5S_select_iter_init(file_iter, file_space, 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)
+ if(H5S_select_iter_init(mem_iter, mem_space, 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) < 0)
+ if(H5S_select_iter_init(bkg_iter, file_space, 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 */
@@ -658,7 +651,7 @@ H5D__scatgath_write(const H5D_io_info_t *io_info, const H5D_type_info_t *type_in
* buffer. Also gather data from the file into the background buffer
* if necessary.
*/
- n = H5D__gather_mem(buf, mem_space, mem_iter, smine_nelmts, type_info->tconv_buf/*out*/);
+ n = H5D__gather_mem(buf, mem_iter, smine_nelmts, type_info->tconv_buf/*out*/);
if(n != smine_nelmts)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "mem gather failed")
@@ -675,7 +668,7 @@ H5D__scatgath_write(const H5D_io_info_t *io_info, const H5D_type_info_t *type_in
} /* end if */
else {
if(H5T_BKG_YES == type_info->need_bkg) {
- n = H5D__gather_file(io_info, file_space, bkg_iter, smine_nelmts, type_info->bkg_buf/*out*/);
+ n = H5D__gather_file(io_info, bkg_iter, smine_nelmts, type_info->bkg_buf/*out*/);
if(n != smine_nelmts)
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file gather failed")
} /* end if */
@@ -705,7 +698,7 @@ H5D__scatgath_write(const H5D_io_info_t *io_info, const H5D_type_info_t *type_in
/*
* Scatter the data out to the file.
*/
- if(H5D__scatter_file(io_info, file_space, file_iter, smine_nelmts, type_info->tconv_buf) < 0)
+ if(H5D__scatter_file(io_info, file_iter, smine_nelmts, type_info->tconv_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "scatter failed")
} /* end for */
@@ -761,7 +754,7 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5D__compound_opt_read(size_t nelmts, const H5S_t *space, H5S_sel_iter_t *iter,
+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 *ubuf = (uint8_t *)user_buf; /* Cast for pointer arithmetic */
@@ -777,7 +770,6 @@ H5D__compound_opt_read(size_t nelmts, const H5S_t *space, H5S_sel_iter_t *iter,
/* Check args */
HDassert(nelmts > 0);
- HDassert(space);
HDassert(iter);
HDassert(type_info);
HDassert(type_info->cmpd_subset);
@@ -814,7 +806,7 @@ H5D__compound_opt_read(size_t nelmts, const H5S_t *space, H5S_sel_iter_t *iter,
size_t elmtno; /* Element counter */
/* Get list of sequences for selection to write */
- if(H5S_SELECT_GET_SEQ_LIST(space, 0, iter, vec_size, nelmts, &nseq, &elmtno, off, len) < 0)
+ if(H5S_SELECT_ITER_GET_SEQ_LIST(iter, vec_size, nelmts, &nseq, &elmtno, off, len) < 0)
HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, 0, "sequence length generation failed")
/* Loop, while sequences left to process */
@@ -981,7 +973,7 @@ H5Dscatter(H5D_scatter_func_t op, void *op_data, hid_t type_id,
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "can't allocate selection iterator")
/* Initialize selection iterator */
- if(H5S_select_iter_init(iter, dst_space, type_size) < 0)
+ if(H5S_select_iter_init(iter, dst_space, type_size, 0) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize selection iterator information")
iter_init = TRUE;
@@ -1005,7 +997,7 @@ H5Dscatter(H5D_scatter_func_t op, void *op_data, hid_t type_id,
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "callback returned more elements than in selection")
/* Scatter data */
- if(H5D__scatter_mem(src_buf, dst_space, iter, nelmts_scatter, dst_buf) < 0)
+ if(H5D__scatter_mem(src_buf, iter, nelmts_scatter, dst_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "scatter failed")
nelmts -= (hssize_t)nelmts_scatter;
@@ -1091,14 +1083,14 @@ H5Dgather(hid_t src_space_id, const void *src_buf, hid_t type_id,
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "can't allocate selection iterator")
/* Initialize selection iterator */
- if(H5S_select_iter_init(iter, src_space, type_size) < 0)
+ if(H5S_select_iter_init(iter, src_space, type_size, 0) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize selection iterator information")
iter_init = TRUE;
/* Loop until all data has been scattered */
while(nelmts > 0) {
/* Gather data */
- if(0 == (nelmts_gathered = H5D__gather_mem(src_buf, src_space, iter, MIN(dst_buf_nelmts, (size_t)nelmts), dst_buf)))
+ if(0 == (nelmts_gathered = H5D__gather_mem(src_buf, iter, MIN(dst_buf_nelmts, (size_t)nelmts), dst_buf)))
HGOTO_ERROR(H5E_IO, H5E_CANTCOPY, FAIL, "gather failed")
HDassert(nelmts_gathered == MIN(dst_buf_nelmts, (size_t)nelmts));
diff --git a/src/H5Dselect.c b/src/H5Dselect.c
index 0ec3423..a843d93 100644
--- a/src/H5Dselect.c
+++ b/src/H5Dselect.c
@@ -175,12 +175,12 @@ H5D__select_io(const H5D_io_info_t *io_info, size_t elmt_size,
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) < 0)
+ if(H5S_select_iter_init(file_iter, 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)
+ if(H5S_select_iter_init(mem_iter, 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 */
@@ -193,7 +193,7 @@ H5D__select_io(const H5D_io_info_t *io_info, size_t elmt_size,
/* Check if more file sequences are needed */
if(curr_file_seq >= file_nseq) {
/* Get sequences for file selection */
- if(H5S_SELECT_GET_SEQ_LIST(file_space, H5S_GET_SEQ_LIST_SORTED, file_iter, vec_size, nelmts, &file_nseq, &file_nelem, file_off, file_len) < 0)
+ if(H5S_SELECT_ITER_GET_SEQ_LIST(file_iter, vec_size, nelmts, &file_nseq, &file_nelem, file_off, file_len) < 0)
HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed")
/* Start at the beginning of the sequences again */
@@ -203,7 +203,7 @@ H5D__select_io(const H5D_io_info_t *io_info, size_t elmt_size,
/* Check if more memory sequences are needed */
if(curr_mem_seq >= mem_nseq) {
/* Get sequences for memory selection */
- if(H5S_SELECT_GET_SEQ_LIST(mem_space, 0, mem_iter, vec_size, nelmts, &mem_nseq, &mem_nelem, mem_off, mem_len) < 0)
+ if(H5S_SELECT_ITER_GET_SEQ_LIST(mem_iter, vec_size, nelmts, &mem_nseq, &mem_nelem, mem_off, mem_len) < 0)
HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed")
/* Start at the beginning of the sequences again */
@@ -227,6 +227,8 @@ H5D__select_io(const H5D_io_info_t *io_info, size_t elmt_size,
/* Decrement number of elements left to process */
HDassert(((size_t)tmp_file_len % elmt_size) == 0);
+ if(elmt_size == 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "Resulted in division by zero")
nelmts -= ((size_t)tmp_file_len / elmt_size);
} /* end while */
} /* end else */
diff --git a/src/H5Dtest.c b/src/H5Dtest.c
index ac1d05a..916ec72 100644
--- a/src/H5Dtest.c
+++ b/src/H5Dtest.c
@@ -32,6 +32,7 @@
#include "H5Dpkg.h" /* Datasets */
#include "H5Eprivate.h" /* Error handling */
#include "H5Iprivate.h" /* IDs */
+#include "H5VLprivate.h" /* Virtual Object Layer */
/****************/
@@ -88,7 +89,7 @@ H5D__layout_version_test(hid_t did, unsigned *version)
FUNC_ENTER_PACKAGE
/* Check args */
- if(NULL == (dset = (H5D_t *)H5I_object_verify(did, H5I_DATASET)))
+ if(NULL == (dset = (H5D_t *)H5VL_object_verify(did, H5I_DATASET)))
HGOTO_ERROR(H5E_DATASET, H5E_BADTYPE, FAIL, "not a dataset")
if(version)
@@ -127,7 +128,7 @@ H5D__layout_contig_size_test(hid_t did, hsize_t *size)
FUNC_ENTER_PACKAGE
/* Check args */
- if(NULL == (dset = (H5D_t *)H5I_object_verify(did, H5I_DATASET)))
+ if(NULL == (dset = (H5D_t *)H5VL_object_verify(did, H5I_DATASET)))
HGOTO_ERROR(H5E_DATASET, H5E_BADTYPE, FAIL, "not a dataset")
if(size) {
@@ -168,7 +169,7 @@ H5D__layout_compact_dirty_test(hid_t did, hbool_t *dirty)
FUNC_ENTER_PACKAGE
/* Check args */
- if(NULL == (dset = (H5D_t *)H5I_object_verify(did, H5I_DATASET)))
+ if(NULL == (dset = (H5D_t *)H5VL_object_verify(did, H5I_DATASET)))
HGOTO_ERROR(H5E_DATASET, H5E_BADTYPE, FAIL, "not a dataset")
if(dirty) {
@@ -211,7 +212,7 @@ H5D__layout_type_test(hid_t did, H5D_layout_t *layout_type)
HDassert(layout_type);
/* Check args */
- if(NULL == (dset = (H5D_t *)H5I_object_verify(did, H5I_DATASET)))
+ if(NULL == (dset = (H5D_t *)H5VL_object_verify(did, H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset")
if(layout_type)
@@ -250,7 +251,7 @@ H5D__layout_idx_type_test(hid_t did, H5D_chunk_index_t *idx_type)
FUNC_ENTER_PACKAGE
/* Check args */
- if(NULL == (dset = (H5D_t *)H5I_object_verify(did, H5I_DATASET)))
+ if(NULL == (dset = (H5D_t *)H5VL_object_verify(did, H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset")
if(dset->shared->layout.type != H5D_CHUNKED)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dataset is not chunked")
@@ -291,7 +292,7 @@ H5D__current_cache_size_test(hid_t did, size_t *nbytes_used, int *nused)
FUNC_ENTER_PACKAGE
/* Check args */
- if(NULL == (dset = (H5D_t *)H5I_object_verify(did, H5I_DATASET)))
+ if(NULL == (dset = (H5D_t *)H5VL_object_verify(did, H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset")
if(nbytes_used) {
diff --git a/src/H5Dvirtual.c b/src/H5Dvirtual.c
index 8867492..53640e7 100644
--- a/src/H5Dvirtual.c
+++ b/src/H5Dvirtual.c
@@ -35,6 +35,13 @@
* until the virtual dataset is closed.
*/
+/*
+ * Note: H5S_select_project_intersection has been updated to no longer require
+ * that the source and source intersect spaces have the same extent. This file
+ * should therefore be updated to remove code that ensures this condition, which
+ * should improve both maintainability and performance.
+ */
+
/****************/
/* Module Setup */
/****************/
@@ -58,7 +65,7 @@
#include "H5Oprivate.h" /* Object headers */
#include "H5Pprivate.h" /* Property Lists */
#include "H5Sprivate.h" /* Dataspaces */
-
+#include "H5VLprivate.h" /* Virtual Object Layer */
/****************/
/* Local Macros */
@@ -78,6 +85,7 @@
/********************/
/* 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, const H5S_t *file_space, const H5S_t *mem_space,
H5D_chunk_map_t *fm);
@@ -121,6 +129,7 @@ const H5D_layout_ops_t H5D_LOPS_VIRTUAL[1] = {{
NULL,
H5D__virtual_init,
H5D__virtual_is_space_alloc,
+ H5D__virtual_is_data_cached,
NULL,
H5D__virtual_read,
H5D__virtual_write,
@@ -428,6 +437,10 @@ H5D__virtual_store_layout(H5F_t *f, H5O_layout_t *layout)
/* Create block if # of used entries > 0 */
if(layout->storage.u.virt.list_nused > 0) {
+
+ /* Set the low/high bounds according to 'f' for the API context */
+ H5CX_set_libver_bounds(f);
+
/* Allocate array for caching results of strlen */
if(NULL == (str_size = (size_t *)H5MM_malloc(2 * layout->storage.u.virt.list_nused * sizeof(size_t))))
HGOTO_ERROR(H5E_OHDR, H5E_RESOURCE, FAIL, "unable to allocate string length array")
@@ -491,11 +504,11 @@ H5D__virtual_store_layout(H5F_t *f, H5O_layout_t *layout)
/* Encode each entry */
for(i = 0; i < layout->storage.u.virt.list_nused; i++) {
/* Source file name */
- HDmemcpy((char *)heap_block_p, layout->storage.u.virt.list[i].source_file_name, str_size[2 * i]);
+ H5MM_memcpy((char *)heap_block_p, layout->storage.u.virt.list[i].source_file_name, str_size[2 * i]);
heap_block_p += str_size[2 * i];
/* Source dataset name */
- HDmemcpy((char *)heap_block_p, layout->storage.u.virt.list[i].source_dset_name, str_size[(2 * i) + 1]);
+ H5MM_memcpy((char *)heap_block_p, layout->storage.u.virt.list[i].source_dset_name, str_size[(2 * i) + 1]);
heap_block_p += str_size[(2 * i) + 1];
/* Source selection */
@@ -1107,7 +1120,7 @@ H5D__virtual_str_append(const char *src, size_t src_len, char **p, char **buf,
/* Copy string to *p. Note that since src in not NULL terminated, we must
* use memcpy */
- (void)HDmemcpy(*p, src, src_len);
+ (void)H5MM_memcpy(*p, src, src_len);
/* Advance *p */
*p += src_len;
@@ -2207,6 +2220,54 @@ H5D__virtual_is_space_alloc(const H5O_storage_t H5_ATTR_UNUSED *storage)
/*-------------------------------------------------------------------------
+ * Function: H5D__virtual_is_data_cached
+ *
+ * Purpose: Query if raw data is cached for dataset
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * Wednessday, March 6, 2016
+ *
+ *-------------------------------------------------------------------------
+ */
+static hbool_t
+H5D__virtual_is_data_cached(const H5D_shared_t *shared_dset)
+{
+ const H5O_storage_virtual_t *storage; /* Convenience pointer */
+ size_t i, j; /* Local index variables */
+ hbool_t ret_value = FALSE; /* Return value */
+
+ FUNC_ENTER_PACKAGE_NOERR
+
+ /* Sanity checks */
+ HDassert(shared_dset);
+ storage = &shared_dset->layout.storage.u.virt;
+
+ /* Iterate over mappings */
+ for(i = 0; i < storage->list_nused; i++)
+ /* Check for "printf" source dataset resolution */
+ 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++)
+ /* Check for cahced data in source dset */
+ if(storage->list[i].sub_dset[j].dset
+ && storage->list[i].sub_dset[j].dset->shared->layout.ops->is_data_cached
+ && storage->list[i].sub_dset[j].dset->shared->layout.ops->is_data_cached(storage->list[i].sub_dset[j].dset->shared))
+ HGOTO_DONE(TRUE);
+ } /* end if */
+ else
+ if(storage->list[i].source_dset.dset
+ && storage->list[i].source_dset.dset->shared->layout.ops->is_data_cached
+ && storage->list[i].source_dset.dset->shared->layout.ops->is_data_cached(storage->list[i].source_dset.dset->shared))
+ HGOTO_DONE(TRUE);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D__virtual_is_data_cached() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5D__virtual_pre_io
*
* Purpose: Project all virtual mappings onto mem_space, with the
@@ -2961,8 +3022,9 @@ done:
static herr_t
H5D__virtual_refresh_source_dset(H5D_t **dset)
{
- hid_t temp_id; /* Temporary dataset identifier */
- herr_t ret_value = SUCCEED; /* Return value */
+ hid_t temp_id = H5I_INVALID_HID; /* Temporary dataset identifier */
+ H5VL_object_t *vol_obj = NULL; /* VOL object stored with the ID */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC
@@ -2970,20 +3032,26 @@ H5D__virtual_refresh_source_dset(H5D_t **dset)
HDassert(dset && *dset);
/* Get a temporary identifier for this source dataset */
- if((temp_id = H5I_register(H5I_DATASET, *dset, FALSE)) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "can't register source dataset ID")
+ if((temp_id = H5VL_wrap_register(H5I_DATASET, *dset, FALSE)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "can't register (temporary) source dataset ID")
/* Refresh source dataset */
if(H5D__refresh(temp_id, *dset) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTFLUSH, FAIL, "unable to refresh source dataset")
/* Discard the identifier & replace the dataset */
- if(NULL == (*dset = (H5D_t *)H5I_remove(temp_id)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_remove(temp_id)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTREMOVE, FAIL, "can't unregister source dataset ID")
+ if(NULL == (*dset = (H5D_t *)H5VL_object_unwrap(vol_obj)))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve library object from VOL object")
+ vol_obj->data = NULL;
done:
+ if(vol_obj && H5VL_free_object(vol_obj) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTDEC, FAIL, "unable to free VOL object")
+
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D__virtual_refresh_source_dsets() */
+} /* end H5D__virtual_refresh_source_dset() */
/*-------------------------------------------------------------------------
diff --git a/src/H5E.c b/src/H5E.c
index 170133e..07eaf18 100644
--- a/src/H5E.c
+++ b/src/H5E.c
@@ -866,7 +866,7 @@ H5Eget_msg(hid_t msg_id, H5E_type_t *type, char *msg_str, size_t size)
H5E_msg_t *msg; /* Pointer to error message */
ssize_t ret_value = -1; /* Return value */
- FUNC_ENTER_API((-1))
+ FUNC_ENTER_API_NOCLEAR((-1))
H5TRACE4("Zs", "i*Et*sz", msg_id, type, msg_str, size);
/* Get the message object */
@@ -1386,7 +1386,7 @@ H5Epush2(hid_t err_stack, const char *file, const char *func, unsigned line,
*/
/* Format the description */
- va_start(ap, fmt);
+ HDva_start(ap, fmt);
va_started = TRUE;
#ifdef H5_HAVE_VASPRINTF
@@ -1402,8 +1402,8 @@ H5Epush2(hid_t err_stack, const char *file, const char *func, unsigned line,
/* If the description doesn't fit into the initial buffer size, allocate more space and try again */
while((desc_len = HDvsnprintf(tmp, (size_t)tmp_len, fmt, ap)) > (tmp_len - 1)) {
/* shutdown & restart the va_list */
- va_end(ap);
- va_start(ap, fmt);
+ HDva_end(ap);
+ HDva_start(ap, fmt);
/* Release the previous description, it's too small */
H5MM_xfree(tmp);
@@ -1421,7 +1421,7 @@ H5Epush2(hid_t err_stack, const char *file, const char *func, unsigned line,
done:
if(va_started)
- va_end(ap);
+ HDva_end(ap);
#ifdef H5_HAVE_VASPRINTF
/* Memory was allocated with HDvasprintf so it needs to be freed
* with HDfree
@@ -1484,7 +1484,7 @@ done:
*
* Purpose: Prints the error stack in some default way. This is just a
* convenience function for H5Ewalk() with a function that
- * prints error messages. Users are encouraged to write there
+ * prints error messages. Users are encouraged to write their
* own more specific error handlers.
*
* Return: SUCCEED/FAIL
@@ -1566,8 +1566,8 @@ H5Ewalk2(hid_t err_stack, H5E_direction_t direction, H5E_walk2_t stack_func, voi
/* Walk the error stack */
op.vers = 2;
op.u.func2 = stack_func;
- if(H5E__walk(estack, direction, &op, client_data) < 0)
- HGOTO_ERROR(H5E_ERROR, H5E_CANTLIST, FAIL, "can't walk error stack")
+ if((ret_value = H5E__walk(estack, direction, &op, client_data)) < 0)
+ HERROR(H5E_ERROR, H5E_CANTLIST, "can't walk error stack");
done:
FUNC_LEAVE_API(ret_value)
diff --git a/src/H5EA.c b/src/H5EA.c
index 9ceb144..96eee12 100644
--- a/src/H5EA.c
+++ b/src/H5EA.c
@@ -46,6 +46,7 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5EApkg.h" /* Extensible Arrays */
#include "H5FLprivate.h" /* Free Lists */
+#include "H5MMprivate.h" /* Memory management */
#include "H5VMprivate.h" /* Vector functions */
@@ -693,7 +694,7 @@ H5EA_set(const H5EA_t *ea, hsize_t idx, const void *elmt))
HDassert(thing_unprot_func);
/* Set element in thing's element buffer */
- HDmemcpy(thing_elmt_buf + (hdr->cparam.cls->nat_elmt_size * thing_elmt_idx), elmt, hdr->cparam.cls->nat_elmt_size);
+ H5MM_memcpy(thing_elmt_buf + (hdr->cparam.cls->nat_elmt_size * thing_elmt_idx), elmt, hdr->cparam.cls->nat_elmt_size);
thing_cache_flags |= H5AC__DIRTIED_FLAG;
/* Update max. element set in array, if appropriate */
@@ -765,7 +766,7 @@ H5EA_get(const H5EA_t *ea, hsize_t idx, void *elmt))
} /* end if */
else
/* Get element from thing's element buffer */
- HDmemcpy(elmt, thing_elmt_buf + (hdr->cparam.cls->nat_elmt_size * thing_elmt_idx), hdr->cparam.cls->nat_elmt_size);
+ H5MM_memcpy(elmt, thing_elmt_buf + (hdr->cparam.cls->nat_elmt_size * thing_elmt_idx), hdr->cparam.cls->nat_elmt_size);
} /* end else */
CATCH
@@ -986,19 +987,25 @@ END_FUNC(PRIV) /* end H5EA_delete() */
* Purpose: Iterate over the elements of an extensible array
* (copied and modified from FA_iterate() in H5FA.c)
*
- * Return: SUCCEED/FAIL
+ * Return: H5_ITER_CONT/H5_ITER_ERROR
*
* Programmer: Vailin Choi; Feb 2015
*
+ * Modification:
+ * Prototype changed (HDFFV-10661)
+ * - herr_t to int
+ * - SUCCEED/FAIL to H5_ITER_CONT/H5_ITER_ERROR
+ * June 6, 2019 -BMR
*-------------------------------------------------------------------------
*/
BEGIN_FUNC(PRIV, ERR,
-herr_t, SUCCEED, FAIL,
+int, H5_ITER_CONT, H5_ITER_ERROR,
H5EA_iterate(H5EA_t *ea, H5EA_operator_t op, void *udata))
/* Local variables */
uint8_t *elmt = NULL;
hsize_t u;
+ int cb_ret = H5_ITER_CONT; /* Return value from callback */
/*
* Check arguments.
@@ -1012,9 +1019,7 @@ H5EA_iterate(H5EA_t *ea, H5EA_operator_t op, void *udata))
H5E_THROW(H5E_CANTALLOC, "memory allocation failed for extensible array element")
/* Iterate over all elements in array */
- for(u = 0; u < ea->hdr->stats.stored.max_idx_set; u++) {
- int cb_ret; /* Return value from callback */
-
+ for(u = 0; u < ea->hdr->stats.stored.max_idx_set && cb_ret == H5_ITER_CONT; u++) {
/* Get array element */
if(H5EA_get(ea, u, elmt) < 0)
H5E_THROW(H5E_CANTGET, "unable to delete fixed array")
diff --git a/src/H5EAcache.c b/src/H5EAcache.c
index d81d1b3..5b61522 100644
--- a/src/H5EAcache.c
+++ b/src/H5EAcache.c
@@ -41,6 +41,7 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5EApkg.h" /* Extensible Arrays */
#include "H5MFprivate.h" /* File memory management */
+#include "H5MMprivate.h" /* Memory management */
#include "H5VMprivate.h" /* Vectors and arrays */
#include "H5WBprivate.h" /* Wrapped Buffers */
@@ -484,7 +485,7 @@ H5EA__cache_hdr_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_UNUSED le
HDassert(hdr);
/* Magic number */
- HDmemcpy(image, H5EA_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ H5MM_memcpy(image, H5EA_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
image += H5_SIZEOF_MAGIC;
/* Version # */
@@ -872,7 +873,7 @@ H5EA__cache_iblock_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_UNUSED
/* Get temporary pointer to serialized info */
/* Magic number */
- HDmemcpy(image, H5EA_IBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ H5MM_memcpy(image, H5EA_IBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
image += H5_SIZEOF_MAGIC;
/* Version # */
@@ -1184,7 +1185,7 @@ H5EA__cache_sblock_deserialize(const void *_image, size_t len,
size_t tot_page_init_size = sblock->ndblks * sblock->dblk_page_init_size; /* Compute total size of 'page init' buffer */
/* Retrieve the 'page init' bitmasks */
- HDmemcpy(sblock->page_init, image, tot_page_init_size);
+ H5MM_memcpy(sblock->page_init, image, tot_page_init_size);
image += tot_page_init_size;
} /* end if */
@@ -1281,7 +1282,7 @@ H5EA__cache_sblock_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_UNUSED
HDassert(sblock->hdr);
/* Magic number */
- HDmemcpy(image, H5EA_SBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ H5MM_memcpy(image, H5EA_SBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
image += H5_SIZEOF_MAGIC;
/* Version # */
@@ -1303,7 +1304,7 @@ H5EA__cache_sblock_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_UNUSED
size_t tot_page_init_size = sblock->ndblks * sblock->dblk_page_init_size; /* Compute total size of 'page init' buffer */
/* Store the 'page init' bitmasks */
- HDmemcpy(image, sblock->page_init, tot_page_init_size);
+ H5MM_memcpy(image, sblock->page_init, tot_page_init_size);
image += tot_page_init_size;
} /* end if */
@@ -1695,7 +1696,7 @@ H5EA__cache_dblock_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_UNUSED
HDassert(dblock->hdr);
/* Magic number */
- HDmemcpy(image, H5EA_DBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ H5MM_memcpy(image, H5EA_DBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
image += H5_SIZEOF_MAGIC;
/* Version # */
diff --git a/src/H5EAdbg.c b/src/H5EAdbg.c
index 1a2b973..3d6c2ed 100644
--- a/src/H5EAdbg.c
+++ b/src/H5EAdbg.c
@@ -264,7 +264,7 @@ H5EA__iblock_debug(H5F_t *f, haddr_t H5_ATTR_UNUSED addr, FILE *stream, int inde
HDfprintf(stream, "%*sData Block Addresses in Index Block:\n", indent, "");
for(u = 0; u < iblock->ndblk_addrs; u++) {
/* Print address */
- sprintf(temp_str, "Address #%u:", u);
+ HDsprintf(temp_str, "Address #%u:", u);
HDfprintf(stream, "%*s%-*s %a\n", (indent + 3), "", MAX(0, (fwidth - 3)),
temp_str,
iblock->dblk_addrs[u]);
@@ -280,7 +280,7 @@ H5EA__iblock_debug(H5F_t *f, haddr_t H5_ATTR_UNUSED addr, FILE *stream, int inde
HDfprintf(stream, "%*sSuper Block Addresses in Index Block:\n", indent, "");
for(u = 0; u < iblock->nsblk_addrs; u++) {
/* Print address */
- sprintf(temp_str, "Address #%u:", u);
+ HDsprintf(temp_str, "Address #%u:", u);
HDfprintf(stream, "%*s%-*s %a\n", (indent + 3), "", MAX(0, (fwidth - 3)),
temp_str,
iblock->sblk_addrs[u]);
@@ -371,7 +371,7 @@ H5EA__sblock_debug(H5F_t *f, haddr_t addr, FILE *stream, int indent,
HDfprintf(stream, "%*sData Block Addresses in Super Block:\n", indent, "");
for(u = 0; u < sblock->ndblks; u++) {
/* Print address */
- sprintf(temp_str, "Address #%u:", u);
+ HDsprintf(temp_str, "Address #%u:", u);
HDfprintf(stream, "%*s%-*s %a\n", (indent + 3), "", MAX(0, (fwidth - 3)),
temp_str,
sblock->dblk_addrs[u]);
diff --git a/src/H5EAhdr.c b/src/H5EAhdr.c
index 62a23b8..ec40298 100644
--- a/src/H5EAhdr.c
+++ b/src/H5EAhdr.c
@@ -41,6 +41,7 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5EApkg.h" /* Extensible Arrays */
#include "H5MFprivate.h" /* File memory management */
+#include "H5MMprivate.h" /* Memory management */
#include "H5VMprivate.h" /* Vectors and arrays */
@@ -62,6 +63,9 @@
/* Local Typedefs */
/******************/
+/* Alias for pointer to factory, for use when allocating sequences of them */
+typedef H5FL_fac_head_t *H5FL_fac_head_ptr_t;
+
/********************/
/* Package Typedefs */
@@ -82,9 +86,6 @@
/* Library Private Variables */
/*****************************/
-/* Alias for pointer to factory, for use when allocating sequences of them */
-typedef H5FL_fac_head_t *H5FL_fac_head_ptr_t;
-
/*******************/
/* Local Variables */
@@ -407,7 +408,7 @@ H5EA__hdr_create(H5F_t *f, const H5EA_create_t *cparam, void *ctx_udata))
hdr->idx_blk_addr = HADDR_UNDEF;
/* Set the creation parameters for the array */
- HDmemcpy(&hdr->cparam, cparam, sizeof(hdr->cparam));
+ H5MM_memcpy(&hdr->cparam, cparam, sizeof(hdr->cparam));
/* Finish initializing extensible array header */
if(H5EA__hdr_init(hdr, ctx_udata) < 0)
diff --git a/src/H5EAstat.c b/src/H5EAstat.c
index 72c4d14..509d3f8 100644
--- a/src/H5EAstat.c
+++ b/src/H5EAstat.c
@@ -40,6 +40,7 @@
#include "H5private.h" /* Generic Functions */
#include "H5Eprivate.h" /* Error handling */
#include "H5EApkg.h" /* Extensible Arrays */
+#include "H5MMprivate.h" /* Memory management */
/****************/
@@ -108,7 +109,7 @@ HDfprintf(stderr, "%s: Called\n", FUNC);
HDassert(stats);
/* Copy extensible array statistics */
- HDmemcpy(stats, &ea->hdr->stats, sizeof(ea->hdr->stats));
+ H5MM_memcpy(stats, &ea->hdr->stats, sizeof(ea->hdr->stats));
END_FUNC(PRIV) /* end H5EA_get_stats() */
diff --git a/src/H5EAtest.c b/src/H5EAtest.c
index 7c02e16..814e64f 100644
--- a/src/H5EAtest.c
+++ b/src/H5EAtest.c
@@ -336,7 +336,7 @@ H5EA__test_debug(FILE *stream, int indent, int fwidth, hsize_t idx,
HDassert(elmt);
/* Print element */
- sprintf(temp_str, "Element #%llu:", (unsigned long long)idx);
+ HDsprintf(temp_str, "Element #%llu:", (unsigned long long)idx);
HDfprintf(stream, "%*s%-*s %llu\n", indent, "", fwidth, temp_str,
(unsigned long long)*(const uint64_t *)elmt);
diff --git a/src/H5HFpublic.h b/src/H5ESpublic.h
index 82cfc21..e3b1b56 100644
--- a/src/H5HFpublic.h
+++ b/src/H5ESpublic.h
@@ -1,9 +1,8 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* 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 *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the COPYING file, which can be found at the root of the source code *
* distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
@@ -11,22 +10,11 @@
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-/*-------------------------------------------------------------------------
- *
- * Created: H5HFpublic.h
- * Feb 24 2006
- * Quincey Koziol <koziol@ncsa.uiuc.edu>
- *
- * Purpose: Public declarations for the fractal heap package.
- *
- *-------------------------------------------------------------------------
- */
-
-#ifndef _H5HFpublic_H
-#define _H5HFpublic_H
+#ifndef _H5ESpublic_H
+#define _H5ESpublic_H
/* Public headers needed by this file */
-#include "H5public.h"
+#include "H5public.h" /* Generic Functions */
/*****************/
/* Public Macros */
@@ -36,9 +24,22 @@
/* Public Typedefs */
/*******************/
-/**********************************/
-/* Public API Function Prototypes */
-/**********************************/
+/* Asynchronous operation status */
+typedef enum H5ES_status_t {
+ H5ES_STATUS_IN_PROGRESS, /* Operation has not yet completed */
+ H5ES_STATUS_SUCCEED, /* Operation has completed, successfully */
+ H5ES_STATUS_FAIL, /* Operation has completed, but failed */
+ H5ES_STATUS_CANCELED /* Operation has not completed and was canceled */
+} H5ES_status_t;
+
+
+/********************/
+/* Public Variables */
+/********************/
+
+/*********************/
+/* Public Prototypes */
+/*********************/
#ifdef __cplusplus
extern "C" {
@@ -48,5 +49,5 @@ extern "C" {
}
#endif
-#endif /* _H5HFpublic_H */
+#endif /* _H5ESpublic_H */
diff --git a/src/H5Eint.c b/src/H5Eint.c
index 540c9b1..e76db82 100644
--- a/src/H5Eint.c
+++ b/src/H5Eint.c
@@ -422,7 +422,7 @@ done:
* Purpose: Private function to print the error stack in some default
* way. This is just a convenience function for H5Ewalk() and
* H5Ewalk2() with a function that prints error messages.
- * Users are encouraged to write there own more specific error
+ * Users are encouraged to write their own more specific error
* handlers.
*
* Return: SUCCEED/FAIL
@@ -511,10 +511,9 @@ H5E__walk(const H5E_t *estack, H5E_direction_t direction, const H5E_walk_op_t *o
void *client_data)
{
int i; /* Local index variable */
- herr_t status; /* Status from callback function */
- herr_t ret_value = SUCCEED; /* Return value */
+ herr_t ret_value = H5_ITER_CONT; /* Return value */
- FUNC_ENTER_PACKAGE
+ FUNC_ENTER_PACKAGE_NOERR
/* Sanity check */
HDassert(estack);
@@ -530,9 +529,9 @@ H5E__walk(const H5E_t *estack, H5E_direction_t direction, const H5E_walk_op_t *o
if(op->u.func1) {
H5E_error1_t old_err;
- status = SUCCEED;
+ ret_value = SUCCEED;
if(H5E_WALK_UPWARD == direction) {
- for(i = 0; i < (int)estack->nused && status >= 0; i++) {
+ for(i = 0; i < (int)estack->nused && ret_value == H5_ITER_CONT; i++) {
/* Point to each error record on the stack and pass it to callback function.*/
old_err.maj_num = estack->slot[i].maj_num;
old_err.min_num = estack->slot[i].min_num;
@@ -541,12 +540,12 @@ H5E__walk(const H5E_t *estack, H5E_direction_t direction, const H5E_walk_op_t *o
old_err.desc = estack->slot[i].desc;
old_err.line = estack->slot[i].line;
- status = (op->u.func1)(i, &old_err, client_data);
+ ret_value = (op->u.func1)(i, &old_err, client_data);
} /* end for */
} /* end if */
else {
H5_CHECK_OVERFLOW(estack->nused - 1, size_t, int);
- for(i = (int)(estack->nused - 1); i >= 0 && status >= 0; i--) {
+ for(i = (int)(estack->nused - 1); i >= 0 && ret_value == H5_ITER_CONT; i--) {
/* Point to each error record on the stack and pass it to callback function.*/
old_err.maj_num = estack->slot[i].maj_num;
old_err.min_num = estack->slot[i].min_num;
@@ -555,12 +554,12 @@ H5E__walk(const H5E_t *estack, H5E_direction_t direction, const H5E_walk_op_t *o
old_err.desc = estack->slot[i].desc;
old_err.line = estack->slot[i].line;
- status = (op->u.func1)((int)(estack->nused - (size_t)(i + 1)), &old_err, client_data);
+ ret_value = (op->u.func1)((int)(estack->nused - (size_t)(i + 1)), &old_err, client_data);
} /* end for */
} /* end else */
- if(status < 0)
- HGOTO_ERROR(H5E_ERROR, H5E_CANTLIST, FAIL, "can't walk error stack")
+ if(ret_value < 0)
+ HERROR(H5E_ERROR, H5E_CANTLIST, "can't walk error stack");
} /* end if */
#else /* H5_NO_DEPRECATED_SYMBOLS */
HDassert(0 && "version 1 error stack walk without deprecated symbols!");
@@ -569,23 +568,22 @@ H5E__walk(const H5E_t *estack, H5E_direction_t direction, const H5E_walk_op_t *o
else {
HDassert(op->vers == 2);
if(op->u.func2) {
- status = SUCCEED;
+ ret_value = SUCCEED;
if(H5E_WALK_UPWARD == direction) {
- for(i = 0; i < (int)estack->nused && status >= 0; i++)
- status = (op->u.func2)((unsigned)i, estack->slot + i, client_data);
+ for(i = 0; i < (int)estack->nused && ret_value == H5_ITER_CONT; i++)
+ ret_value = (op->u.func2)((unsigned)i, estack->slot + i, client_data);
} /* end if */
else {
H5_CHECK_OVERFLOW(estack->nused - 1, size_t, int);
- for(i = (int)(estack->nused - 1); i >= 0 && status >= 0; i--)
- status = (op->u.func2)((unsigned)(estack->nused - (size_t)(i + 1)), estack->slot + i, client_data);
+ for(i = (int)(estack->nused - 1); i >= 0 && ret_value == H5_ITER_CONT; i--)
+ ret_value = (op->u.func2)((unsigned)(estack->nused - (size_t)(i + 1)), estack->slot + i, client_data);
} /* end else */
- if(status < 0)
- HGOTO_ERROR(H5E_ERROR, H5E_CANTLIST, FAIL, "can't walk error stack")
+ if(ret_value < 0)
+ HERROR(H5E_ERROR, H5E_CANTLIST, "can't walk error stack");
} /* end if */
} /* end else */
-done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5E__walk() */
@@ -706,7 +704,7 @@ H5E_printf_stack(H5E_t *estack, const char *file, const char *func, unsigned lin
*/
/* Start the variable-argument parsing */
- va_start(ap, fmt);
+ HDva_start(ap, fmt);
va_started = TRUE;
#ifdef H5_HAVE_VASPRINTF
@@ -722,8 +720,8 @@ H5E_printf_stack(H5E_t *estack, const char *file, const char *func, unsigned lin
/* If the description doesn't fit into the initial buffer size, allocate more space and try again */
while((desc_len = HDvsnprintf(tmp, (size_t)tmp_len, fmt, ap)) > (tmp_len - 1)) {
/* shutdown & restart the va_list */
- va_end(ap);
- va_start(ap, fmt);
+ HDva_end(ap);
+ HDva_start(ap, fmt);
/* Release the previous description, it's too small */
H5MM_xfree(tmp);
@@ -741,7 +739,7 @@ H5E_printf_stack(H5E_t *estack, const char *file, const char *func, unsigned lin
done:
if(va_started)
- va_end(ap);
+ HDva_end(ap);
#ifdef H5_HAVE_VASPRINTF
/* Memory was allocated with HDvasprintf so it needs to be freed
* with HDfree
@@ -885,11 +883,11 @@ H5E__clear_entries(H5E_t *estack, size_t nentries)
/* Release strings */
if(error->func_name)
- H5MM_xfree((void *)error->func_name); /* Casting away const OK - QAK */
+ error->func_name = (const char *) H5MM_xfree((void *)error->func_name); /* Casting away const OK - QAK */
if(error->file_name)
- H5MM_xfree((void *)error->file_name); /* Casting away const OK - QAK */
+ error->file_name = (const char *) H5MM_xfree((void *)error->file_name); /* Casting away const OK - QAK */
if(error->desc)
- H5MM_xfree((void *)error->desc); /* Casting away const OK - QAK */
+ error->desc = (const char *) H5MM_xfree((void *)error->desc); /* Casting away const OK - QAK */
} /* end for */
/* Decrement number of errors on stack */
diff --git a/src/H5F.c b/src/H5F.c
index 3d9a257..144ffbe 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -29,22 +29,40 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5Fpkg.h" /* File access */
#include "H5FDprivate.h" /* File drivers */
+#include "H5FLprivate.h" /* Free lists */
#include "H5Gprivate.h" /* Groups */
#include "H5Iprivate.h" /* IDs */
#include "H5MFprivate.h" /* File memory management */
#include "H5MMprivate.h" /* Memory management */
#include "H5Pprivate.h" /* Property lists */
#include "H5Tprivate.h" /* Datatypes */
+#include "H5VLprivate.h" /* Virtual Object Layer */
+
+#include "H5VLnative_private.h" /* Native VOL connector */
/****************/
/* Local Macros */
/****************/
+
/******************/
/* Local Typedefs */
/******************/
+/* User data for traversal routine to get ID counts */
+typedef struct {
+ size_t obj_count; /* Number of objects counted so far */
+ unsigned types; /* Types of objects to be counted */
+} H5F_trav_obj_cnt_t;
+
+/* User data for traversal routine to get ID lists */
+typedef struct {
+ size_t max_objs; /* Maximum # of IDs to record */
+ hid_t *oid_list; /* Array of recorded IDs*/
+ size_t obj_count; /* Number of objects counted so far */
+} H5F_trav_obj_ids_t;
+
/********************/
/* Package Typedefs */
@@ -55,7 +73,13 @@
/* Local Prototypes */
/********************/
-static herr_t H5F__close_cb(H5F_t *f);
+static herr_t H5F__close_cb(H5VL_object_t *file_vol_obj);
+
+/* Callback for getting object counts in a file */
+static int H5F__get_all_count_cb(void H5_ATTR_UNUSED *obj_ptr, hid_t H5_ATTR_UNUSED obj_id, void *key);
+
+/* Callback for getting IDs for open objects in a file */
+static int H5F__get_all_ids_cb(void H5_ATTR_UNUSED *obj_ptr, hid_t obj_id, void *key);
/*********************/
@@ -75,6 +99,11 @@ hbool_t H5_PKG_INIT_VAR = FALSE;
/* Local Variables */
/*******************/
+/* Declare a free list to manage the H5VL_t struct */
+H5FL_EXTERN(H5VL_t);
+
+/* Declare a free list to manage the H5VL_object_t struct */
+H5FL_EXTERN(H5VL_object_t);
/* File ID class */
static const H5I_class_t H5I_FILE_CLS[1] = {{
@@ -176,43 +205,23 @@ H5F_term_package(void)
*-------------------------------------------------------------------------
*/
static herr_t
-H5F__close_cb(H5F_t *f)
+H5F__close_cb(H5VL_object_t *file_vol_obj)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC
/* Sanity check */
- HDassert(f);
- HDassert(f->file_id > 0); /* This routine should only be called when a file ID's ref count drops to zero */
+ HDassert(file_vol_obj);
- /* Perform checks for "semi" file close degree here, since closing the
- * file is not allowed if there are objects still open.
- */
- if(f->shared->fc_degree == H5F_CLOSE_SEMI) {
- unsigned nopen_files = 0; /* Number of open files in file/mount hierarchy */
- unsigned nopen_objs = 0; /* Number of open objects in file/mount hierarchy */
-
- /* Get the number of open objects and open files on this file/mount hierarchy */
- if(H5F__mount_count_ids(f, &nopen_files, &nopen_objs) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_MOUNT, FAIL, "problem checking mount hierarchy")
-
- /* If there are no other file IDs open on this file/mount hier., but
- * there are still open objects, issue an error and bail out now,
- * without decrementing the file ID's reference count and triggering
- * a "real" attempt at closing the file.
- */
- if(nopen_files == 1 && nopen_objs > 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file, there are objects still open")
- } /* end if */
-
- /* Reset the file ID for this file */
- f->file_id = -1;
-
- /* Attempt to close the file/mount hierarchy */
- if(H5F_try_close(f, NULL) < 0)
+ /* Close the file */
+ if(H5VL_file_close(file_vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "unable to close file")
+ /* Free the VOL object */
+ if(H5VL_free_object(file_vol_obj) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTDEC, FAIL, "unable to free VOL object")
+
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5F__close_cb() */
@@ -235,21 +244,18 @@ done:
hid_t
H5Fget_create_plist(hid_t file_id)
{
- H5F_t *file; /* File info */
- H5P_genplist_t *plist; /* Property list */
+ H5VL_object_t *vol_obj; /* File info */
hid_t ret_value = H5I_INVALID_HID; /* Return value */
FUNC_ENTER_API(H5I_INVALID_HID)
H5TRACE1("i", "i", file_id);
/* check args */
- if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(file_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid file identifier")
- if(NULL == (plist = (H5P_genplist_t *)H5I_object(file->shared->fcpl_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a property list")
/* Retrieve the file creation property list */
- if((ret_value = H5P_copy_plist(plist, TRUE)) < 0)
+ if(H5VL_file_get(vol_obj, H5VL_FILE_GET_FCPL, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &ret_value) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, H5I_INVALID_HID, "unable to retrieve file creation properties")
done:
@@ -278,18 +284,18 @@ done:
hid_t
H5Fget_access_plist(hid_t file_id)
{
- H5F_t *file; /* File info */
+ H5VL_object_t *vol_obj; /* File info */
hid_t ret_value = H5I_INVALID_HID; /* Return value */
FUNC_ENTER_API(H5I_INVALID_HID)
H5TRACE1("i", "i", file_id);
/* Check args */
- if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(file_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid file identifier")
/* Retrieve the file's access property list */
- if((ret_value = H5F_get_access_plist(file, TRUE)) < 0)
+ if(H5VL_file_get(vol_obj, H5VL_FILE_GET_FAPL, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &ret_value) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, H5I_INVALID_HID, "can't get file access property list")
done:
@@ -316,7 +322,7 @@ H5F__get_all_count_cb(void H5_ATTR_UNUSED *obj_ptr, hid_t H5_ATTR_UNUSED obj_id,
FUNC_ENTER_STATIC_NOERR
- *(udata->obj_count) = *(udata->obj_count) + 1;
+ udata->obj_count++;
FUNC_LEAVE_NOAPI(ret_value)
} /* H5F_get_all_count_cb */
@@ -351,52 +357,45 @@ H5Fget_obj_count(hid_t file_id, unsigned types)
* count the IDs in the file.
*/
if(file_id != (hid_t)H5F_OBJ_ALL) {
- H5F_t *f = NULL;
- size_t obj_count = 0;
+ H5VL_object_t *vol_obj;
/* Get the file object */
- if(NULL == (f = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "not a file id")
/* Get the count */
- if(H5F_get_obj_count(f, types, TRUE, &obj_count) < 0)
+ if(H5VL_file_get(vol_obj, H5VL_FILE_GET_OBJ_COUNT, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, types, &ret_value) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, (-1), "unable to get object count in file(s)")
-
- /* Set the return value */
- ret_value = (ssize_t)obj_count;
}
/* If we passed in the 'special' ID, get the count for everything open in the
* library, iterating over all open files and getting the object count for each.
- *
- * XXX: Consider making this a helper function in H5I.
*/
else {
H5F_trav_obj_cnt_t udata;
- udata.obj_count = &ret_value;
+ /* Set up callback context */
udata.types = types | H5F_OBJ_LOCAL;
+ udata.obj_count = 0;
- if(types & H5F_OBJ_FILE) {
+ if(types & H5F_OBJ_FILE)
if(H5I_iterate(H5I_FILE, H5F__get_all_count_cb, &udata, TRUE) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_BADITER, (-1), "iteration over file IDs failed");
- }
- if(types & H5F_OBJ_DATASET) {
+ HGOTO_ERROR(H5E_FILE, H5E_BADITER, (-1), "iteration over file IDs failed")
+ if(types & H5F_OBJ_DATASET)
if(H5I_iterate(H5I_DATASET, H5F__get_all_count_cb, &udata, TRUE) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_BADITER, (-1), "iteration over dataset IDs failed");
- }
- if(types & H5F_OBJ_GROUP) {
+ HGOTO_ERROR(H5E_FILE, H5E_BADITER, (-1), "iteration over dataset IDs failed")
+ if(types & H5F_OBJ_GROUP)
if(H5I_iterate(H5I_GROUP, H5F__get_all_count_cb, &udata, TRUE) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_BADITER, (-1), "iteration over group IDs failed");
- }
- if(types & H5F_OBJ_DATATYPE) {
+ HGOTO_ERROR(H5E_FILE, H5E_BADITER, (-1), "iteration over group IDs failed")
+ if(types & H5F_OBJ_DATATYPE)
if(H5I_iterate(H5I_DATATYPE, H5F__get_all_count_cb, &udata, TRUE) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_BADITER, (-1), "iteration over datatype IDs failed");
- }
- if(types & H5F_OBJ_ATTR) {
+ HGOTO_ERROR(H5E_FILE, H5E_BADITER, (-1), "iteration over datatype IDs failed")
+ if(types & H5F_OBJ_ATTR)
if(H5I_iterate(H5I_ATTR, H5F__get_all_count_cb, &udata, TRUE) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_BADITER, (-1), "iteration over attribute IDs failed");
- }
- }
+ HGOTO_ERROR(H5E_FILE, H5E_BADITER, (-1), "iteration over attribute IDs failed")
+
+ /* Set return value */
+ ret_value = (ssize_t)udata.obj_count;
+ } /* end else */
done:
FUNC_LEAVE_API(ret_value)
@@ -422,11 +421,12 @@ H5F__get_all_ids_cb(void H5_ATTR_UNUSED *obj_ptr, hid_t obj_id, void *key)
FUNC_ENTER_STATIC_NOERR
- if(*udata->obj_count >= udata->max_objs)
+ if(udata->obj_count >= udata->max_objs)
HGOTO_DONE(H5_ITER_STOP);
- udata->oid_list[*udata->obj_count] = obj_id;
- *(udata->obj_count) = *(udata->obj_count) + 1;
+ /* Add the ID to the array */
+ udata->oid_list[udata->obj_count] = obj_id;
+ udata->obj_count++;
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -441,6 +441,9 @@ done:
* NOTE: Type mismatch - You can ask for more objects than can be
* returned.
*
+ * NOTE: Currently, the IDs' ref counts are not incremented. Is this
+ * intentional and documented?
+ *
* Return: Success: The number of IDs in oid_list
*
* Failure: -1
@@ -466,24 +469,19 @@ H5Fget_obj_ids(hid_t file_id, unsigned types, size_t max_objs, hid_t *oid_list)
* get the IDs from the file.
*/
if(file_id != (hid_t)H5F_OBJ_ALL) {
- H5F_t *file = NULL;
- size_t obj_id_count = 0;
+ H5VL_object_t *vol_obj;
/* get the file object */
- if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "invalid file identifier")
/* Get the IDs */
- if(H5F_get_obj_ids(file, types, max_objs, oid_list, TRUE, &obj_id_count) < 0)
+ if(H5VL_file_get(vol_obj, H5VL_FILE_GET_OBJ_IDS, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, types, max_objs, oid_list, &ret_value) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, (-1), "unable to get object ids in file(s)")
-
- /* Set the return value */
- ret_value = (ssize_t)obj_id_count;
- }
+ } /* end if */
/* If we passed in the 'special' ID, get the count for everything open in the
* library, iterating over all open files and getting the object count for each.
*
- * XXX: Consider making this a helper function in H5I.
* XXX: Note that the RM states that passing in a negative value for max_objs
* gets you all the objects. This technically works, but is clearly wrong
* behavior since max_objs is an unsigned type.
@@ -491,31 +489,30 @@ H5Fget_obj_ids(hid_t file_id, unsigned types, size_t max_objs, hid_t *oid_list)
else {
H5F_trav_obj_ids_t udata;
+ /* Set up callback context */
udata.max_objs = max_objs;
udata.oid_list = oid_list;
- udata.obj_count = &ret_value;
+ udata.obj_count = 0;
- if(types & H5F_OBJ_FILE) {
+ if(types & H5F_OBJ_FILE)
if(H5I_iterate(H5I_FILE, H5F__get_all_ids_cb, &udata, TRUE) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_BADITER, (-1), "iteration over file IDs failed");
- }
- if(types & H5F_OBJ_DATASET) {
+ HGOTO_ERROR(H5E_FILE, H5E_BADITER, (-1), "iteration over file IDs failed")
+ if(types & H5F_OBJ_DATASET)
if(H5I_iterate(H5I_DATASET, H5F__get_all_ids_cb, &udata, TRUE) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_BADITER, (-1), "iteration over dataset IDs failed");
- }
- if(types & H5F_OBJ_GROUP) {
+ HGOTO_ERROR(H5E_FILE, H5E_BADITER, (-1), "iteration over dataset IDs failed")
+ if(types & H5F_OBJ_GROUP)
if(H5I_iterate(H5I_GROUP, H5F__get_all_ids_cb, &udata, TRUE) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_BADITER, (-1), "iteration over group IDs failed");
- }
- if(types & H5F_OBJ_DATATYPE) {
+ HGOTO_ERROR(H5E_FILE, H5E_BADITER, (-1), "iteration over group IDs failed")
+ if(types & H5F_OBJ_DATATYPE)
if(H5I_iterate(H5I_DATATYPE, H5F__get_all_ids_cb, &udata, TRUE) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_BADITER, (-1), "iteration over datatype IDs failed");
- }
- if(types & H5F_OBJ_ATTR) {
+ HGOTO_ERROR(H5E_FILE, H5E_BADITER, (-1), "iteration over datatype IDs failed")
+ if(types & H5F_OBJ_ATTR)
if(H5I_iterate(H5I_ATTR, H5F__get_all_ids_cb, &udata, TRUE) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_BADITER, (-1), "iteration over attribute IDs failed");
- }
- }
+ HGOTO_ERROR(H5E_FILE, H5E_BADITER, (-1), "iteration over attribute IDs failed")
+
+ /* Set return value */
+ ret_value = (ssize_t)udata.obj_count;
+ } /* end else */
done:
FUNC_LEAVE_API(ret_value)
@@ -535,7 +532,7 @@ done:
herr_t
H5Fget_vfd_handle(hid_t file_id, hid_t fapl_id, void **file_handle)
{
- H5F_t *file; /* File info */
+ H5VL_object_t *vol_obj; /* File info */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -546,11 +543,11 @@ H5Fget_vfd_handle(hid_t file_id, hid_t fapl_id, void **file_handle)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file handle pointer")
/* Get the file object */
- if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(file_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier")
/* Retrieve the VFD handle for the file */
- if(H5F_get_vfd_handle(file, fapl_id, file_handle) < 0)
+ if(H5VL_file_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_FILE_GET_VFD_HANDLE, file_handle, fapl_id) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get VFD handle")
done:
@@ -559,38 +556,41 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5Fis_hdf5
- *
- * Purpose: Check the file signature to detect an HDF5 file.
+ * Function: H5Fis_accessible
*
- * Bugs: This function is not robust: it only uses the default file
- * driver when attempting to open the file when in fact it
- * should use all known file drivers.
+ * Purpose: Check if the file can be opened with the given fapl.
*
- * Return: TRUE/FALSE/FAIL
+ * Return: Succeed: TRUE/FALSE
+ * Failure: FAIL (includes file does not exist)
*
*-------------------------------------------------------------------------
*/
htri_t
-H5Fis_hdf5(const char *name)
+H5Fis_accessible(const char *filename, hid_t fapl_id)
{
htri_t ret_value; /* Return value */
FUNC_ENTER_API(FAIL)
- H5TRACE1("t", "*s", name);
+ H5TRACE2("t", "*si", filename, fapl_id);
/* Check args */
- if(!name || !*name)
+ if(!filename || !*filename)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "no file name specified")
- /* call the private is_HDF5 function */
- /* (Should not trigger raw data I/O - QAK, 2018/01/03) */
- if((ret_value = H5F__is_hdf5(name)) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, FAIL, "unable open file")
+ /* Check the file access property list */
+ if(H5P_DEFAULT == fapl_id)
+ fapl_id = H5P_FILE_ACCESS_DEFAULT;
+ else
+ if(TRUE != H5P_isa_class(fapl_id, H5P_FILE_ACCESS))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not file access property list")
+
+ /* Check if file is accessible */
+ if(H5VL_file_specific(NULL, H5VL_FILE_IS_ACCESSIBLE, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, fapl_id, filename, &ret_value) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, FAIL, "unable to determine if file is accessible as HDF5")
done:
FUNC_LEAVE_API(ret_value)
-} /* end H5Fis_hdf5() */
+} /* end H5Fis_accessible() */
/*-------------------------------------------------------------------------
@@ -621,7 +621,9 @@ done:
hid_t
H5Fcreate(const char *filename, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
{
- H5F_t *new_file = NULL; /* file struct for new file */
+ H5F_t *new_file = NULL; /* File struct for new file */
+ H5P_genplist_t *plist; /* Property list pointer */
+ H5VL_connector_prop_t connector_prop; /* Property for VOL connector ID & info */
hid_t ret_value; /* return value */
FUNC_ENTER_API(H5I_INVALID_HID)
@@ -652,6 +654,18 @@ H5Fcreate(const char *filename, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
if(H5CX_set_apl(&fapl_id, H5P_CLS_FACC, H5I_INVALID_HID, TRUE) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info")
+ /* Get the VOL info from the fapl */
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a file access property list")
+ if(H5P_peek(plist, H5F_ACS_VOL_CONN_NAME, &connector_prop) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, H5I_INVALID_HID, "can't get VOL connector info")
+
+ /* Stash a copy of the "top-level" connector property, before any pass-through
+ * connectors modify or unwrap it.
+ */
+ if(H5CX_set_vol_connector_prop(&connector_prop) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set VOL connector info in API context")
+
/* Adjust bit flags by turning on the creation bit and making sure that
* the EXCL or TRUNC bit is set. All newly-created files are opened for
* reading and writing.
@@ -660,21 +674,15 @@ H5Fcreate(const char *filename, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
flags |= H5F_ACC_EXCL; /*default*/
flags |= H5F_ACC_RDWR | H5F_ACC_CREAT;
- /* Create a new file or truncate an existing file. */
- if(NULL == (new_file = H5F_open(filename, flags, fcpl_id, fapl_id)))
+ /* Create a new file or truncate an existing file through the VOL */
+ if(NULL == (new_file = (H5F_t *)H5VL_file_create(&connector_prop, filename, flags, fcpl_id, fapl_id, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)))
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, H5I_INVALID_HID, "unable to create file")
/* Get an atom for the file */
- if((ret_value = H5I_register(H5I_FILE, new_file, TRUE)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to atomize file")
-
- /* Keep this ID in file object structure */
- new_file->file_id = ret_value;
+ if((ret_value = H5VL_register_using_vol_id(H5I_FILE, new_file, connector_prop.connector_id, TRUE)) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to atomize file handle")
done:
- if(ret_value < 0 && new_file && H5F_try_close(new_file, NULL) < 0)
- HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, H5I_INVALID_HID, "problems closing file")
-
FUNC_LEAVE_API(ret_value)
} /* end H5Fcreate() */
@@ -701,8 +709,10 @@ done:
hid_t
H5Fopen(const char *filename, unsigned flags, hid_t fapl_id)
{
- H5F_t *new_file = NULL; /* file struct for new file */
- hid_t ret_value; /* return value */
+ H5F_t *new_file = NULL; /* File struct for new file */
+ H5P_genplist_t *plist; /* Property list pointer */
+ H5VL_connector_prop_t connector_prop; /* Property for VOL connector ID & info */
+ hid_t ret_value; /* return value */
FUNC_ENTER_API(H5I_INVALID_HID)
H5TRACE3("i", "*sIui", filename, flags, fapl_id);
@@ -714,6 +724,7 @@ H5Fopen(const char *filename, unsigned flags, hid_t fapl_id)
if((flags & ~H5F_ACC_PUBLIC_FLAGS) ||
(flags & H5F_ACC_TRUNC) || (flags & H5F_ACC_EXCL))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "invalid file open flags")
+ /* XXX (VOL MERGE): Might want to move SWMR flag checks to H5F_open() */
/* Asking for SWMR write access on a read-only file is invalid */
if((flags & H5F_ACC_SWMR_WRITE) && 0 == (flags & H5F_ACC_RDWR))
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, H5I_INVALID_HID, "SWMR write access on a file open for read-only access is not allowed")
@@ -725,21 +736,27 @@ H5Fopen(const char *filename, unsigned flags, hid_t fapl_id)
if(H5CX_set_apl(&fapl_id, H5P_CLS_FACC, H5I_INVALID_HID, TRUE) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info")
- /* Open the file */
- if(NULL == (new_file = H5F_open(filename, flags, H5P_FILE_CREATE_DEFAULT, fapl_id)))
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, H5I_INVALID_HID, "unable to open file")
+ /* Get the VOL info from the fapl */
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a file access property list")
+ if(H5P_peek(plist, H5F_ACS_VOL_CONN_NAME, &connector_prop) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, H5I_INVALID_HID, "can't get VOL connector info")
- /* Get an atom for the file */
- if((ret_value = H5I_register(H5I_FILE, new_file, TRUE)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to atomize file handle")
+ /* Stash a copy of the "top-level" connector property, before any pass-through
+ * connectors modify or unwrap it.
+ */
+ if(H5CX_set_vol_connector_prop(&connector_prop) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set VOL connector info in API context")
- /* Keep this ID in file object structure */
- new_file->file_id = ret_value;
+ /* Open the file through the VOL layer */
+ if(NULL == (new_file = (H5F_t *)H5VL_file_open(&connector_prop, filename, flags, fapl_id, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, H5I_INVALID_HID, "unable to open file")
-done:
- if(ret_value < 0 && new_file && H5F_try_close(new_file, NULL) < 0)
- HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, H5I_INVALID_HID, "problems closing file")
+ /* Get an ID for the file */
+ if((ret_value = H5VL_register_using_vol_id(H5I_FILE, new_file, connector_prop.connector_id, TRUE)) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to atomize file handle")
+done:
FUNC_LEAVE_API(ret_value)
} /* end H5Fopen() */
@@ -758,108 +775,26 @@ done:
herr_t
H5Fflush(hid_t object_id, H5F_scope_t scope)
{
- H5F_t *f = NULL; /* File to flush */
- H5O_loc_t *oloc = NULL; /* Object location for ID */
+ H5VL_object_t *vol_obj = NULL; /* Object info */
+ H5I_type_t obj_type; /* Type of object */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE2("e", "iFs", object_id, scope);
- switch(H5I_get_type(object_id)) {
- case H5I_FILE:
- if(NULL == (f = (H5F_t *)H5I_object(object_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier")
- break;
-
- case H5I_GROUP:
- {
- H5G_t *grp;
-
- if(NULL == (grp = (H5G_t *)H5I_object(object_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid group identifier")
- oloc = H5G_oloc(grp);
- }
- break;
-
- case H5I_DATATYPE:
- {
- H5T_t *type;
-
- if(NULL == (type = (H5T_t *)H5I_object(object_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid type identifier")
- oloc = H5T_oloc(type);
- }
- break;
-
- case H5I_DATASET:
- {
- H5D_t *dset;
-
- if(NULL == (dset = (H5D_t *)H5I_object(object_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid dataset identifier")
- oloc = H5D_oloc(dset);
- }
- break;
-
- case H5I_ATTR:
- {
- H5A_t *attr;
-
- if(NULL == (attr = (H5A_t *)H5I_object(object_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid attribute identifier")
- oloc = H5A_oloc(attr);
- }
- break;
-
- case H5I_UNINIT:
- case H5I_BADID:
- case H5I_DATASPACE:
- case H5I_REFERENCE:
- case H5I_VFL:
- case H5I_GENPROP_CLS:
- case H5I_GENPROP_LST:
- case H5I_ERROR_CLASS:
- case H5I_ERROR_MSG:
- case H5I_ERROR_STACK:
- case H5I_NTYPES:
- default:
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
- } /* end switch */
-
- if(!f) {
- if(!oloc)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "object is not assocated with a file")
- f = oloc->file;
- } /* end if */
- if(!f)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "object is not associated with a file")
+ /* Get the type of object we're flushing + sanity check */
+ obj_type = H5I_get_type(object_id);
+ if(H5I_FILE != obj_type && H5I_GROUP != obj_type && H5I_DATATYPE != obj_type &&
+ H5I_DATASET != obj_type && H5I_ATTR != obj_type)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
- /* Flush the file */
- /*
- * Nothing to do if the file is read only. This determination is
- * made at the shared open(2) flags level, implying that opening a
- * file twice, once for read-only and once for read-write, and then
- * calling H5Fflush() with the read-only handle, still causes data
- * to be flushed.
- */
- if(H5F_ACC_RDWR & H5F_INTENT(f)) {
- hid_t fapl_id = H5P_DEFAULT; /* FAPL to use */
-
- /* Verify access property list and set up collective metadata if appropriate */
- if(H5CX_set_apl(&fapl_id, H5P_CLS_FACC, object_id, TRUE) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set access property list info")
-
- /* Flush other files, depending on scope */
- if(H5F_SCOPE_GLOBAL == scope) {
- /* Call the flush routine for mounted file hierarchies */
- if(H5F_flush_mounts(f) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush mounted file hierarchy")
- } /* end if */
- else
- /* Call the flush routine, for this file */
- if(H5F__flush(f) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush file's cached information")
- } /* end if */
+ /* get the file object */
+ if(NULL == (vol_obj = H5VL_vol_object(object_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier")
+
+ /* Flush the object */
+ if(H5VL_file_specific(vol_obj, H5VL_FILE_FLUSH, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, (int)obj_type, (int)scope) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush file")
done:
FUNC_LEAVE_API(ret_value)
@@ -892,9 +827,11 @@ H5Fclose(hid_t file_id)
if(H5I_FILE != H5I_get_type(file_id))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file ID")
- /* Close the file */
- if(H5F__close(file_id) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "closing file ID failed")
+ /* Decrement reference count on atom. When it reaches zero the file will
+ * be closed.
+ */
+ if(H5I_dec_app_ref(file_id) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTCLOSEFILE, FAIL, "decrementing file ID failed")
done:
FUNC_LEAVE_API(ret_value)
@@ -902,6 +839,68 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5Fdelete
+ *
+ * Purpose: Deletes an HDF5 file.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Fdelete(const char *filename, hid_t fapl_id)
+{
+ H5P_genplist_t *plist; /* Property list pointer */
+ H5VL_connector_prop_t connector_prop; /* Property for VOL connector ID & info */
+ htri_t is_hdf5 = FAIL;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE2("e", "*si", filename, fapl_id);
+
+ /* Check args */
+ if(!filename || !*filename)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "no file name specified")
+
+ /* Check the file access property list */
+ if(H5P_DEFAULT == fapl_id)
+ fapl_id = H5P_FILE_ACCESS_DEFAULT;
+ else
+ if(TRUE != H5P_isa_class(fapl_id, H5P_FILE_ACCESS))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list")
+
+ /* Verify access property list and set up collective metadata if appropriate */
+ if(H5CX_set_apl(&fapl_id, H5P_CLS_FACC, H5I_INVALID_HID, TRUE) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info")
+
+ /* Get the VOL info from the fapl */
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object_verify(fapl_id, H5I_GENPROP_LST)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a property list")
+ if(H5P_peek(plist, H5F_ACS_VOL_CONN_NAME, &connector_prop) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, H5I_INVALID_HID, "can't get VOL connector info")
+
+ /* Stash a copy of the "top-level" connector property, before any pass-through
+ * connectors modify or unwrap it.
+ */
+ if(H5CX_set_vol_connector_prop(&connector_prop) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set VOL connector info in API context")
+
+ /* Make sure this is HDF5 storage for this VOL connector */
+ if(H5VL_file_specific(NULL, H5VL_FILE_IS_ACCESSIBLE, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, fapl_id, filename, &is_hdf5) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, FAIL, "unable to determine if file is accessible as HDF5")
+ if(!is_hdf5)
+ HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, FAIL, "not an HDF5 file")
+
+ /* Delete the file */
+ if(H5VL_file_specific(NULL, H5VL_FILE_DELETE, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, fapl_id, filename, &ret_value) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTDELETEFILE, FAIL, "unable to delete the file")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Fdelete() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5Freopen
*
* Purpose: Reopen a file. The new file handle which is returned points
@@ -919,33 +918,31 @@ done:
hid_t
H5Freopen(hid_t file_id)
{
- H5F_t *old_file = NULL;
- H5F_t *new_file = NULL;
+ H5VL_object_t *vol_obj = NULL;
+ H5F_t *file = NULL; /* File struct for new file */
hid_t ret_value = H5I_INVALID_HID; /* Return value */
FUNC_ENTER_API(H5I_INVALID_HID)
H5TRACE1("i", "i", file_id);
/* Get the file object */
- if(NULL == (old_file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a file")
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(file_id, H5I_FILE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid file identifier")
/* Reopen the file */
- if(NULL == (new_file = H5F__reopen(old_file)))
+ if(H5VL_file_specific(vol_obj, H5VL_FILE_REOPEN, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &file) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, H5I_INVALID_HID, "unable to reopen file via the VOL connector")
+
+ /* Make sure that worked */
+ if(NULL == file)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, H5I_INVALID_HID, "unable to reopen file")
/* Get an atom for the file */
- if((ret_value = H5I_register(H5I_FILE, new_file, TRUE)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to atomize file handle")
-
- /* Keep this ID in file object structure */
- new_file->file_id = ret_value;
+ if((ret_value = H5VL_register(H5I_FILE, file, vol_obj->connector, TRUE)) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to atomize file handle")
done:
- if(H5I_INVALID_HID == ret_value)
- if(new_file && H5F__dest(new_file, FALSE) < 0)
- HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, H5I_INVALID_HID, "can't close file")
-
+ /* XXX (VOL MERGE): If registration fails, file will not be closed */
FUNC_LEAVE_API(ret_value)
} /* end H5Freopen() */
@@ -970,30 +967,15 @@ H5Fget_intent(hid_t file_id, unsigned *intent_flags)
/* If no intent flags were passed in, exit quietly */
if(intent_flags) {
- H5F_t *file; /* Pointer to file structure */
+ H5VL_object_t *vol_obj; /* File info */
/* Get the internal file structure */
- if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file")
-
- /* HDF5 uses some flags internally that users don't know about.
- * Simplify things for them so that they only get either H5F_ACC_RDWR
- * or H5F_ACC_RDONLY.
- */
- if(H5F_INTENT(file) & H5F_ACC_RDWR) {
- *intent_flags = H5F_ACC_RDWR;
-
- /* Check for SWMR write access on the file */
- if(H5F_INTENT(file) & H5F_ACC_SWMR_WRITE)
- *intent_flags |= H5F_ACC_SWMR_WRITE;
- } /* end if */
- else {
- *intent_flags = H5F_ACC_RDONLY;
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(file_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier")
- /* Check for SWMR read access on the file */
- if(H5F_INTENT(file) & H5F_ACC_SWMR_READ)
- *intent_flags |= H5F_ACC_SWMR_READ;
- } /* end else */
+ /* Get the flags */
+ if((ret_value = H5VL_file_get(vol_obj, H5VL_FILE_GET_INTENT, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, intent_flags)) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get file's intent flags")
} /* end if */
done:
@@ -1002,6 +984,42 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5Fget_fileno
+ *
+ * Purpose: Public API to retrieve the file's 'file number' that uniquely
+ * identifies each open file.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Fget_fileno(hid_t file_id, unsigned long *fileno)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE2("e", "i*Ul", file_id, fileno);
+
+ /* If no fileno pointer was passed in, exit quietly */
+ if(fileno) {
+ H5VL_object_t *vol_obj; /* File info */
+
+ /* Get the internal file structure */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(file_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier")
+
+ /* Get the flags */
+ if((ret_value = H5VL_file_get(vol_obj, H5VL_FILE_GET_FILENO, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, fileno)) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get file's 'file number'")
+ } /* end if */
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Fget_fileno() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5Fget_freespace
*
* Purpose: Retrieves the amount of free space in the file.
@@ -1015,23 +1033,20 @@ done:
hssize_t
H5Fget_freespace(hid_t file_id)
{
- H5F_t *file; /* File object for file ID */
- hsize_t tot_space; /* Amount of free space in the file */
+ H5VL_object_t *vol_obj = NULL;
hssize_t ret_value; /* Return value */
FUNC_ENTER_API((-1))
H5TRACE1("Hs", "i", file_id);
/* Get the file object */
- if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(file_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "invalid file identifier")
/* Get the amount of free space in the file */
- if(H5MF_get_freespace(file, &tot_space, NULL) < 0)
+ if(H5VL_file_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_FILE_GET_FREE_SPACE, &ret_value) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, (-1), "unable to get file free space")
- ret_value = (hssize_t)tot_space;
-
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Fget_freespace() */
@@ -1051,9 +1066,7 @@ done:
herr_t
H5Fget_filesize(hid_t file_id, hsize_t *size)
{
- H5F_t *file; /* File object for file ID */
- haddr_t max_eof_eoa; /* Maximum of the EOA & EOF */
- haddr_t base_addr; /* Base address for the file */
+ H5VL_object_t *vol_obj; /* File info */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -1062,18 +1075,12 @@ H5Fget_filesize(hid_t file_id, hsize_t *size)
/* Check args */
if(!size)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "size parameter cannot be NULL")
- if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID")
- /* Get the actual file size */
- if(H5F__get_max_eof_eoa(file, &max_eof_eoa) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "file can't get max eof/eoa ")
-
- base_addr = H5FD_get_base_addr(file->shared->lf);
-
- /* Convert relative base address for file to absolute address */
- if(size)
- *size = (hsize_t)(max_eof_eoa + base_addr);
+ /* Get the file size */
+ if(H5VL_file_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_FILE_GET_SIZE, size) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get file size")
done:
FUNC_LEAVE_API(ret_value)
@@ -1122,19 +1129,18 @@ done:
ssize_t
H5Fget_file_image(hid_t file_id, void *buf_ptr, size_t buf_len)
{
- H5F_t *file; /* File object for file ID */
- ssize_t ret_value; /* Return value */
+ H5VL_object_t *vol_obj; /* File object for file ID */
+ ssize_t ret_value; /* Return value */
FUNC_ENTER_API((-1))
H5TRACE3("Zs", "i*xz", file_id, buf_ptr, buf_len);
/* Check args */
- if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, (-1), "not a file ID")
/* Get the file image */
- /* (Should not trigger raw data I/O - QAK, 2018/01/03) */
- if((ret_value = H5F__get_file_image(file, buf_ptr, buf_len)) < 0)
+ if(H5VL_file_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_FILE_GET_FILE_IMAGE, buf_ptr, &ret_value, buf_len) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, (-1), "unable to get file image")
done:
@@ -1159,20 +1165,22 @@ done:
herr_t
H5Fget_mdc_config(hid_t file_id, H5AC_cache_config_t *config_ptr)
{
- H5F_t *file; /* File object for file ID */
+ H5VL_object_t *vol_obj = NULL;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE2("e", "i*x", file_id, config_ptr);
/* Check args */
- if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID")
if((NULL == config_ptr) || (config_ptr->version != H5AC__CURR_CACHE_CONFIG_VERSION))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Bad config_ptr")
+ /* Get the file object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(file_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier")
+
/* Get the metadata cache configuration */
- if(H5AC_get_cache_auto_resize_config(file->shared->cache, config_ptr) < 0)
+ if(H5VL_file_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_FILE_GET_MDC_CONF, config_ptr) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get metadata cache configuration")
done:
@@ -1194,18 +1202,18 @@ done:
herr_t
H5Fset_mdc_config(hid_t file_id, H5AC_cache_config_t *config_ptr)
{
- H5F_t *file; /* File object for file ID */
+ H5VL_object_t *vol_obj = NULL;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE2("e", "i*x", file_id, config_ptr);
/* Get the file object */
- if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(file_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier")
/* Set the metadata cache configuration */
- if(H5AC_set_cache_auto_resize_config(file->shared->cache, config_ptr) < 0)
+ if(H5VL_file_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_FILE_SET_MDC_CONFIG, config_ptr) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to set metadata cache configuration")
done:
@@ -1228,21 +1236,20 @@ done:
herr_t
H5Fget_mdc_hit_rate(hid_t file_id, double *hit_rate_ptr)
{
- H5F_t *file; /* File object for file ID */
+ H5VL_object_t *vol_obj;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE2("e", "i*d", file_id, hit_rate_ptr);
/* Check args */
- if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID")
-
if(NULL == hit_rate_ptr)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL hit rate pointer")
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(file_id, H5I_FILE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID")
/* Get the current hit rate */
- if(H5AC_get_cache_hit_rate(file->shared->cache, hit_rate_ptr) < 0)
+ if(H5VL_file_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_FILE_GET_MDC_HR, hit_rate_ptr) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get MDC hit rate")
done:
@@ -1267,8 +1274,7 @@ herr_t
H5Fget_mdc_size(hid_t file_id, size_t *max_size_ptr, size_t *min_clean_size_ptr,
size_t *cur_size_ptr, int *cur_num_entries_ptr)
{
- H5F_t *file; /* File object for file ID */
- uint32_t cur_num_entries;
+ H5VL_object_t *vol_obj;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -1276,17 +1282,13 @@ H5Fget_mdc_size(hid_t file_id, size_t *max_size_ptr, size_t *min_clean_size_ptr,
cur_size_ptr, cur_num_entries_ptr);
/* Check args */
- if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID")
/* Get the size data */
- if(H5AC_get_cache_size(file->shared->cache, max_size_ptr,
- min_clean_size_ptr, cur_size_ptr, &cur_num_entries) < 0)
+ if(H5VL_file_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_FILE_GET_MDC_SIZE, max_size_ptr, min_clean_size_ptr, cur_size_ptr, cur_num_entries_ptr) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get MDC size")
- if(cur_num_entries_ptr != NULL)
- *cur_num_entries_ptr = (int)cur_num_entries;
-
done:
FUNC_LEAVE_API(ret_value)
} /* H5Fget_mdc_size() */
@@ -1311,18 +1313,18 @@ done:
herr_t
H5Freset_mdc_hit_rate_stats(hid_t file_id)
{
- H5F_t *file; /* File object for file ID */
+ H5VL_object_t *vol_obj = NULL;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE1("e", "i", file_id);
/* Get the file object */
- if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(file_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier")
/* Reset the hit rate statistic */
- if(H5AC_reset_cache_hit_rate_stats(file->shared->cache) < 0)
+ if(H5VL_file_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_FILE_RESET_MDC_HIT_RATE) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't reset cache hit rate")
done:
@@ -1354,40 +1356,25 @@ done:
ssize_t
H5Fget_name(hid_t obj_id, char *name/*out*/, size_t size)
{
- H5F_t *f; /* Top file in mount hierarchy */
- size_t len;
- ssize_t ret_value = -1;
+ H5VL_object_t *vol_obj = NULL;
+ H5I_type_t type;
+ ssize_t ret_value = -1; /* Return value */
FUNC_ENTER_API((-1))
H5TRACE3("Zs", "ixz", obj_id, name, size);
- /* For file IDs, get the file object directly */
- /* (This prevents the H5G_loc() call from returning the file pointer for
- * the top file in a mount hierarchy)
- */
- if(H5I_get_type(obj_id) == H5I_FILE ) {
- if(NULL == (f = (H5F_t *)H5I_object(obj_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "not a file")
- } /* end if */
- else {
- H5G_loc_t loc; /* Object location */
-
- /* Get symbol table entry */
- if(H5G_loc(obj_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, (-1), "not a valid object ID")
- f = loc.oloc->file;
- } /* end else */
-
- len = HDstrlen(H5F_OPEN_NAME(f));
+ /* Check the type */
+ type = H5I_get_type(obj_id);
+ if(H5I_FILE != type && H5I_GROUP != type && H5I_DATATYPE != type && H5I_DATASET != type && H5I_ATTR != type)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "not a file or file object")
- if(name) {
- HDstrncpy(name, H5F_OPEN_NAME(f), MIN(len + 1,size));
- if(len >= size)
- name[size-1]='\0';
- } /* end if */
+ /* Get the file object */
+ if(NULL == (vol_obj = H5VL_vol_object(obj_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "invalid file identifier")
- /* Set return value */
- ret_value = (ssize_t)len;
+ /* Get the filename via the VOL */
+ if(H5VL_file_get(vol_obj, H5VL_FILE_GET_NAME, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, (int)type, size, name, &ret_value) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, (-1), "unable to get file name")
done:
FUNC_LEAVE_API(ret_value)
@@ -1410,7 +1397,7 @@ done:
herr_t
H5Fget_info2(hid_t obj_id, H5F_info2_t *finfo)
{
- H5F_t *f; /* Top file in mount hierarchy */
+ H5VL_object_t *vol_obj = NULL;
H5I_type_t type;
herr_t ret_value = SUCCEED; /* Return value */
@@ -1427,25 +1414,11 @@ H5Fget_info2(hid_t obj_id, H5F_info2_t *finfo)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
/* Get the file object */
- if(type == H5I_FILE ) {
- /* For file IDs, get the file object directly */
- /* (This prevents the H5G_loc() call from returning the file pointer for
- * the top file in a mount hierarchy)
- */
- if(NULL == (f = (H5F_t *)H5I_object(obj_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier")
- } /* end if */
- else {
- H5G_loc_t loc; /* Object location */
-
- /* Get symbol table entry */
- if(H5G_loc(obj_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object identifier")
- f = loc.oloc->file;
- } /* end else */
+ if(NULL == (vol_obj = H5VL_vol_object(obj_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier")
/* Get the file information */
- if(H5F__get_info(f, finfo) < 0)
+ if(H5VL_file_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_FILE_GET_INFO, (int)type, finfo) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to retrieve file info")
done:
@@ -1466,22 +1439,22 @@ done:
herr_t
H5Fget_metadata_read_retry_info(hid_t file_id, H5F_retry_info_t *info)
{
- H5F_t *file; /* File object for file ID */
+ H5VL_object_t *vol_obj = NULL; /* File object for file ID */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE2("e", "i*x", file_id, info);
/* Check args */
- if (!info)
+ if(!info)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no info struct")
/* Get the file pointer */
- if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID")
/* Get the retry info */
- if(H5F_get_metadata_read_retry_info(file, info) < 0)
+ if(H5VL_file_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_FILE_GET_METADATA_READ_RETRY_INFO, info) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't get metadata read retry info")
done:
@@ -1507,20 +1480,20 @@ ssize_t
H5Fget_free_sections(hid_t file_id, H5F_mem_t type, size_t nsects,
H5F_sect_info_t *sect_info/*out*/)
{
- H5F_t *file;
+ H5VL_object_t *vol_obj = NULL;
ssize_t ret_value = -1; /* Return value */
FUNC_ENTER_API((-1))
H5TRACE4("Zs", "iFmzx", file_id, type, nsects, sect_info);
/* Check args */
- if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "invalid file identifier")
if(sect_info && nsects == 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, (-1), "nsects must be > 0")
/* Get the free-space section information in the file */
- if((ret_value = H5MF_get_free_sections(file, type, nsects, sect_info)) < 0)
+ if(H5VL_file_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_FILE_GET_FREE_SECTIONS, sect_info, &ret_value, (int)type, nsects) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, (-1), "unable to get file free sections")
done:
@@ -1542,21 +1515,19 @@ done:
herr_t
H5Fclear_elink_file_cache(hid_t file_id)
{
- H5F_t *file; /* File */
+ H5VL_object_t *vol_obj; /* File */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE1("e", "i", file_id);
/* Check args */
- if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID")
- /* See if there's an EFC */
- if(file->shared->efc)
- /* Release the EFC */
- if(H5F__efc_release(file->shared->efc) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't release external file cache")
+ /* Release the EFC */
+ if(H5VL_file_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_FILE_CLEAR_ELINK_CACHE) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't release external file cache")
done:
FUNC_LEAVE_API(ret_value)
@@ -1600,22 +1571,22 @@ done:
herr_t
H5Fstart_swmr_write(hid_t file_id)
{
- H5F_t *file = NULL; /* File info */
+ H5VL_object_t *vol_obj = NULL; /* File info */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE1("e", "i", file_id);
/* Check args */
- if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "hid_t identifier is not a file ID")
/* Set up collective metadata if appropriate */
if(H5CX_set_loc(file_id) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set collective metadata read info")
- /* start SWMR writing */
- if(H5F__start_swmr_write(file) < 0)
+ /* Start SWMR writing */
+ if(H5VL_file_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_FILE_START_SWMR_WRITE) < 0)
HGOTO_ERROR(H5E_FILE, H5E_SYSTEM, FAIL, "unable to start SWMR writing")
done:
@@ -1636,19 +1607,19 @@ done:
herr_t
H5Fstart_mdc_logging(hid_t file_id)
{
- H5F_t *file; /* File info */
- herr_t ret_value = SUCCEED; /* Return value */
+ H5VL_object_t *vol_obj; /* File info */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE1("e", "i", file_id);
/* Sanity check */
- if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "hid_t identifier is not a file ID")
/* Call mdc logging function */
- if(H5C_start_logging(file->shared->cache) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_LOGFAIL, FAIL, "unable to start mdc logging")
+ if(H5VL_file_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_FILE_START_MDC_LOGGING) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_LOGGING, FAIL, "unable to start mdc logging")
done:
FUNC_LEAVE_API(ret_value)
@@ -1669,19 +1640,19 @@ done:
herr_t
H5Fstop_mdc_logging(hid_t file_id)
{
- H5F_t *file; /* File info */
- herr_t ret_value = SUCCEED; /* Return value */
+ H5VL_object_t *vol_obj; /* File info */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE1("e", "i", file_id);
/* Sanity check */
- if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "hid_t identifier is not a file ID")
/* Call mdc logging function */
- if(H5C_stop_logging(file->shared->cache) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_LOGFAIL, FAIL, "unable to stop mdc logging")
+ if(H5VL_file_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_FILE_STOP_MDC_LOGGING) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_LOGGING, FAIL, "unable to stop mdc logging")
done:
FUNC_LEAVE_API(ret_value)
@@ -1703,19 +1674,19 @@ herr_t
H5Fget_mdc_logging_status(hid_t file_id, hbool_t *is_enabled,
hbool_t *is_currently_logging)
{
- H5F_t *file; /* File info */
- herr_t ret_value = SUCCEED; /* Return value */
+ H5VL_object_t *vol_obj; /* File info */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE3("e", "i*b*b", file_id, is_enabled, is_currently_logging);
/* Sanity check */
- if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "hid_t identifier is not a file ID")
/* Call mdc logging function */
- if(H5C_get_logging_status(file->shared->cache, is_enabled, is_currently_logging) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_LOGFAIL, FAIL, "unable to get logging status")
+ if(H5VL_file_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_FILE_GET_MDC_LOGGING_STATUS, is_enabled, is_currently_logging) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_LOGGING, FAIL, "unable to get logging status")
done:
FUNC_LEAVE_API(ret_value)
@@ -1737,23 +1708,23 @@ done:
herr_t
H5Fset_libver_bounds(hid_t file_id, H5F_libver_t low, H5F_libver_t high)
{
- H5F_t *f; /* File */
+ H5VL_object_t *vol_obj; /* File as VOL object */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE3("e", "iFvFv", file_id, low, high);
/* Check args */
- if(NULL == (f = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "not a file ID")
/* Set up collective metadata if appropriate */
if(H5CX_set_loc(file_id) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set collective metadata read info")
- /* Call internal set_libver_bounds function */
- if(H5F__set_libver_bounds(f, low, high) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "cannot set low/high bounds")
+ /* Set the library's version bounds */
+ if(H5VL_file_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_FILE_SET_LIBVER_BOUNDS, low, high) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set library version bounds")
done:
FUNC_LEAVE_API(ret_value)
@@ -1774,26 +1745,22 @@ done:
herr_t
H5Fformat_convert(hid_t file_id)
{
- H5F_t *f = NULL; /* File */
+ H5VL_object_t *vol_obj = NULL; /* File */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE1("e", "i", file_id);
/* Check args */
- if(H5I_FILE != H5I_get_type(file_id))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "file_id parameter is not a valid file identifier")
- /* Get file object */
- if(NULL == (f = (H5F_t *)H5I_object(file_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier")
-
/* Set up collective metadata if appropriate */
if(H5CX_set_loc(file_id) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set collective metadata read info")
/* Convert the format */
- if(H5F__format_convert(f) < 0)
+ if(H5VL_file_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_FILE_FORMAT_CONVERT) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTCONVERT, FAIL, "can't convert file format")
done:
@@ -1813,20 +1780,18 @@ done:
herr_t
H5Freset_page_buffering_stats(hid_t file_id)
{
- H5F_t *file; /* File to reset stats on */
+ H5VL_object_t *vol_obj; /* File to reset stats on */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE1("e", "i", file_id);
/* Check args */
- if(NULL == (file = (H5F_t *)H5I_object(file_id)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier")
- if(NULL == file->shared->pb_ptr)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "page buffering not enabled on file")
/* Reset the statistics */
- if(H5PB_reset_stats(file->shared->pb_ptr) < 0)
+ if(H5VL_file_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_FILE_RESET_PAGE_BUFFERING_STATS) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't reset stats for page buffering")
done:
@@ -1847,23 +1812,21 @@ herr_t
H5Fget_page_buffering_stats(hid_t file_id, unsigned accesses[2], unsigned hits[2],
unsigned misses[2], unsigned evictions[2], unsigned bypasses[2])
{
- H5F_t *file; /* File object */
- herr_t ret_value = SUCCEED; /* Return value */
+ H5VL_object_t *vol_obj; /* File object */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE6("e", "i*Iu*Iu*Iu*Iu*Iu", file_id, accesses, hits, misses, evictions,
bypasses);
/* Check args */
- if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID")
- if(NULL == file->shared->pb_ptr)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "page buffering not enabled on file")
if(NULL == accesses || NULL == hits || NULL == misses || NULL == evictions || NULL == bypasses)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL input parameters for stats")
/* Get the statistics */
- if(H5PB_get_stats(file->shared->pb_ptr, accesses, hits, misses, evictions, bypasses) < 0)
+ if(H5VL_file_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_FILE_GET_PAGE_BUFFERING_STATS, accesses, hits, misses, evictions, bypasses) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't retrieve stats for page buffering")
done:
@@ -1887,21 +1850,19 @@ done:
herr_t
H5Fget_mdc_image_info(hid_t file_id, haddr_t *image_addr, hsize_t *image_len)
{
- H5F_t *file; /* File object for file ID */
+ H5VL_object_t *vol_obj; /* File info */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE3("e", "i*a*h", file_id, image_addr, image_len);
/* Check args */
- if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID")
- if(NULL == image_addr || NULL == image_len)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL image addr or image len")
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(file_id, H5I_FILE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "hid_t identifier is not a file ID")
/* Go get the address and size of the cache image */
- if(H5AC_get_mdc_image_info(file->shared->cache, image_addr, image_len) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTGET, FAIL, "can't retrieve cache image info")
+ if(H5VL_file_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_FILE_GET_MDC_IMAGE_INFO, image_addr, image_len) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't retrieve cache image info")
done:
FUNC_LEAVE_API(ret_value)
@@ -1921,29 +1882,23 @@ done:
herr_t
H5Fget_eoa(hid_t file_id, haddr_t *eoa)
{
- H5F_t *file; /* File object for file ID */
- haddr_t rel_eoa; /* Relative address of EOA */
+ H5VL_object_t *vol_obj; /* File info */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE2("e", "i*a", file_id, eoa);
/* Check args */
- if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "hid_t identifier is not a file ID")
- /* This public routine will work only for drivers with this feature enabled.*/
- /* We might introduce a new feature flag in the future */
- if(!H5F_HAS_FEATURE(file, H5FD_FEAT_SUPPORTS_SWMR_IO))
- HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "must use a SWMR-compatible VFD for this public routine")
-
- /* The real work */
- if(HADDR_UNDEF == (rel_eoa = H5FD_get_eoa(file->shared->lf, H5FD_MEM_DEFAULT)))
- HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "get_eoa request failed")
+ /* Only do work if valid pointer to fill in */
+ if(eoa) {
+ /* Retrieve the EOA for the file */
+ if(H5VL_file_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_FILE_GET_EOA, eoa) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get EOA")
+ } /* end if */
- /* (Note compensating for base address subtraction in internal routine) */
- if(eoa)
- *eoa = rel_eoa + H5FD_get_base_addr(file->shared->lf);
done:
FUNC_LEAVE_API(ret_value)
} /* H5Fget_eoa() */
@@ -1960,34 +1915,109 @@ done:
herr_t
H5Fincrement_filesize(hid_t file_id, hsize_t increment)
{
- H5F_t *file; /* File object for file ID */
- haddr_t max_eof_eoa; /* Maximum of the relative EOA & EOF */
- herr_t ret_value = SUCCEED; /* Return value */
+ H5VL_object_t *vol_obj; /* File info */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE2("e", "ih", file_id, increment);
/* Check args */
- if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "hid_t identifier is not a file ID")
- /* This public routine will work only for drivers with this feature enabled.*/
- /* We might introduce a new feature flag in the future */
- if(!H5F_HAS_FEATURE(file, H5FD_FEAT_SUPPORTS_SWMR_IO))
- HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "must use a SWMR-compatible VFD for this public routine")
+ /* Increment the file size */
+ if(H5VL_file_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_FILE_INCR_FILESIZE, increment) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to increment file size")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* H5Fincrement_filesize() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Fget_dset_no_attrs_hint
+ *
+ * Purpose:
+ *
+ * Get the file-level setting to create minimized dataset object headers.
+ * Result is stored at pointer `minimize`.
+ *
+ * Return:
+ *
+ * Success: SUCCEED (0) (non-negative value)
+ * Failure: FAIL (-1) (negative value)
+ *
+ * Programmer:
+ *
+ * Jacob Smith
+ * 15 August 2018
+ *
+ * Changes: None.
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Fget_dset_no_attrs_hint(hid_t file_id, hbool_t *minimize)
+{
+ H5VL_object_t *vol_obj = NULL;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE2("e", "i*b", file_id, minimize);
+
+ if(NULL == minimize)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "out pointer 'minimize' cannot be NULL")
- /* Get the maximum of EOA and EOF */
- if(H5F__get_max_eof_eoa(file, &max_eof_eoa) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "file can't get max eof/eoa ")
+ vol_obj = (H5VL_object_t *)H5I_object_verify(file_id, H5I_FILE);
+ if(NULL == vol_obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier")
- /* Set EOA to the maximum value + increment */
- /* H5FD_set_eoa() will add base_addr to max_eof_eoa */
- if(H5FD_set_eoa(file->shared->lf, H5FD_MEM_DEFAULT, max_eof_eoa + increment) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "driver set_eoa request failed")
+ if(H5VL_file_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_FILE_GET_MIN_DSET_OHDR_FLAG, minimize) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to set file's dataset header minimization flag")
done:
FUNC_LEAVE_API(ret_value)
-} /* H5Fincrement_filesize() */
+} /* H5Fget_dset_no_attrs_hint */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Fset_dset_no_attrs_hint
+ *
+ * Purpose:
+ *
+ * Set the file-level setting to create minimized dataset object headers.
+ *
+ * Return:
+ *
+ * Success: SUCCEED (0) (non-negative value)
+ * Failure: FAIL (-1) (negative value)
+ *
+ * Programmer:
+ *
+ * Jacob Smith
+ * 15 August 2018
+ *
+ * Changes: None.
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Fset_dset_no_attrs_hint(hid_t file_id, hbool_t minimize)
+{
+ H5VL_object_t *vol_obj = NULL;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE2("e", "ib", file_id, minimize);
+
+ vol_obj = (H5VL_object_t *)H5I_object_verify(file_id, H5I_FILE);
+ if(NULL == vol_obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier")
+
+ if(H5VL_file_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_FILE_SET_MIN_DSET_OHDR_FLAG, minimize) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to set file's dataset header minimization flag")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* H5Fset_dset_no_attrs_hint */
/*-------------------------------------------------------------------------
@@ -2008,7 +2038,7 @@ H5Fvfd_swmr_end_tick(hid_t file_id)
H5TRACE1("e", "i", file_id);
/* Check args */
- if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ if(NULL == (file = (H5F_t *)H5VL_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "hid_t identifier is not a file ID")
/* This will work only if the file is opened with VFD SWMR configured.*/
diff --git a/src/H5FA.c b/src/H5FA.c
index 61aaa53..df53f27 100644
--- a/src/H5FA.c
+++ b/src/H5FA.c
@@ -41,6 +41,7 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5FApkg.h" /* Fixed Arrays */
#include "H5FLprivate.h" /* Free Lists */
+#include "H5MMprivate.h" /* Memory management */
#include "H5VMprivate.h" /* Vector functions */
@@ -371,7 +372,7 @@ H5FA_set(const H5FA_t *fa, hsize_t idx, const void *elmt))
/* Check for paging data block */
if(!dblock->npages) {
/* Set element in data block */
- HDmemcpy(((uint8_t *)dblock->elmts) + (hdr->cparam.cls->nat_elmt_size * idx), elmt, hdr->cparam.cls->nat_elmt_size);
+ H5MM_memcpy(((uint8_t *)dblock->elmts) + (hdr->cparam.cls->nat_elmt_size * idx), elmt, hdr->cparam.cls->nat_elmt_size);
dblock_cache_flags |= H5AC__DIRTIED_FLAG;
} /* end if */
else { /* paging */
@@ -410,7 +411,7 @@ H5FA_set(const H5FA_t *fa, hsize_t idx, const void *elmt))
H5E_THROW(H5E_CANTPROTECT, "unable to protect fixed array data block page, address = %llu", (unsigned long long)dblk_page_addr)
/* Set the element in the data block page */
- HDmemcpy(((uint8_t *)dblk_page->elmts) + (hdr->cparam.cls->nat_elmt_size * elmt_idx), elmt, hdr->cparam.cls->nat_elmt_size);
+ H5MM_memcpy(((uint8_t *)dblk_page->elmts) + (hdr->cparam.cls->nat_elmt_size * elmt_idx), elmt, hdr->cparam.cls->nat_elmt_size);
dblk_page_cache_flags |= H5AC__DIRTIED_FLAG;
} /* end else */
@@ -474,7 +475,7 @@ H5FA_get(const H5FA_t *fa, hsize_t idx, void *elmt))
/* Check for paged data block */
if(!dblock->npages)
/* Retrieve element from data block */
- HDmemcpy(elmt, ((uint8_t *)dblock->elmts) + (hdr->cparam.cls->nat_elmt_size * idx), hdr->cparam.cls->nat_elmt_size);
+ H5MM_memcpy(elmt, ((uint8_t *)dblock->elmts) + (hdr->cparam.cls->nat_elmt_size * idx), hdr->cparam.cls->nat_elmt_size);
else { /* paging */
size_t page_idx; /* Index of page within data block */
@@ -512,7 +513,7 @@ H5FA_get(const H5FA_t *fa, hsize_t idx, void *elmt))
H5E_THROW(H5E_CANTPROTECT, "unable to protect fixed array data block page, address = %llu", (unsigned long long)dblk_page_addr)
/* Retrieve element from data block */
- HDmemcpy(elmt, ((uint8_t *)dblk_page->elmts) + (hdr->cparam.cls->nat_elmt_size * elmt_idx), hdr->cparam.cls->nat_elmt_size);
+ H5MM_memcpy(elmt, ((uint8_t *)dblk_page->elmts) + (hdr->cparam.cls->nat_elmt_size * elmt_idx), hdr->cparam.cls->nat_elmt_size);
} /* end else */
} /* end else */
} /* end else */
@@ -685,20 +686,26 @@ END_FUNC(PRIV) /* end H5FA_delete() */
* Note: This is not very efficient, we should be iterating directly
* over the fixed array's direct block [pages].
*
- * Return: SUCCEED/FAIL
+ * Return: H5_ITER_CONT/H5_ITER_ERROR
*
* Programmer: Vailin Choi
* Thursday, April 30, 2009
*
+ * Modification:
+ * Prototype changed (HDFFV-10661)
+ * - herr_t to int
+ * - SUCCEED/FAIL to H5_ITER_CONT/H5_ITER_ERROR
+ * June 6, 2019 -BMR
*-------------------------------------------------------------------------
*/
BEGIN_FUNC(PRIV, ERR,
-herr_t, SUCCEED, FAIL,
+int, H5_ITER_CONT, H5_ITER_ERROR,
H5FA_iterate(H5FA_t *fa, H5FA_operator_t op, void *udata))
/* Local variables */
uint8_t *elmt = NULL;
hsize_t u;
+ int cb_ret = H5_ITER_CONT; /* Return value from callback */
/*
* Check arguments.
@@ -712,9 +719,7 @@ H5FA_iterate(H5FA_t *fa, H5FA_operator_t op, void *udata))
H5E_THROW(H5E_CANTALLOC, "memory allocation failed for fixed array element")
/* Iterate over all elements in array */
- for(u = 0; u < fa->hdr->stats.nelmts; u++) {
- int cb_ret; /* Return value from callback */
-
+ for(u = 0; u < fa->hdr->stats.nelmts && cb_ret == H5_ITER_CONT; u++) {
/* Get array element */
if(H5FA_get(fa, u, elmt) < 0)
H5E_THROW(H5E_CANTGET, "unable to delete fixed array")
diff --git a/src/H5FAcache.c b/src/H5FAcache.c
index c0ecca2..0a4f29f 100644
--- a/src/H5FAcache.c
+++ b/src/H5FAcache.c
@@ -41,6 +41,7 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5FApkg.h" /* Fixed Arrays */
#include "H5MFprivate.h" /* File memory management */
+#include "H5MMprivate.h" /* Memory management */
#include "H5VMprivate.h" /* Vectors and arrays */
#include "H5WBprivate.h" /* Wrapped Buffers */
@@ -412,7 +413,7 @@ H5FA__cache_hdr_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_UNUSED le
HDassert(hdr);
/* Magic number */
- HDmemcpy(image, H5FA_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ H5MM_memcpy(image, H5FA_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
image += H5_SIZEOF_MAGIC;
/* Version # */
@@ -696,7 +697,7 @@ H5FA__cache_dblock_deserialize(const void *_image, size_t len,
/* Page initialization flags */
if(dblock->npages > 0) {
- HDmemcpy(dblock->dblk_page_init, image, dblock->dblk_page_init_size);
+ H5MM_memcpy(dblock->dblk_page_init, image, dblock->dblk_page_init_size);
image += dblock->dblk_page_init_size;
} /* end if */
@@ -800,7 +801,7 @@ H5FA__cache_dblock_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_UNUSED
HDassert(dblock->hdr);
/* Magic number */
- HDmemcpy(image, H5FA_DBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ H5MM_memcpy(image, H5FA_DBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
image += H5_SIZEOF_MAGIC;
/* Version # */
@@ -815,7 +816,7 @@ H5FA__cache_dblock_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_UNUSED
/* Page init flags */
if(dblock->npages > 0) {
/* Store the 'page init' bitmasks */
- HDmemcpy(image, dblock->dblk_page_init, dblock->dblk_page_init_size);
+ H5MM_memcpy(image, dblock->dblk_page_init, dblock->dblk_page_init_size);
image += dblock->dblk_page_init_size;
} /* end if */
diff --git a/src/H5FAhdr.c b/src/H5FAhdr.c
index 2e3db0b..8f29b83 100644
--- a/src/H5FAhdr.c
+++ b/src/H5FAhdr.c
@@ -39,6 +39,7 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5FApkg.h" /* Fixed Arrays */
#include "H5MFprivate.h" /* File memory management */
+#include "H5MMprivate.h" /* Memory management */
/****************/
@@ -207,7 +208,7 @@ H5FA__hdr_create(H5F_t *f, const H5FA_create_t *cparam, void *ctx_udata))
hdr->dblk_addr = HADDR_UNDEF;
/* Set the creation parameters for the array */
- HDmemcpy(&hdr->cparam, cparam, sizeof(hdr->cparam));
+ H5MM_memcpy(&hdr->cparam, cparam, sizeof(hdr->cparam));
/* Finish initializing fixed array header */
if(H5FA__hdr_init(hdr, ctx_udata) < 0)
diff --git a/src/H5FAstat.c b/src/H5FAstat.c
index 3c06855..49a56a9 100644
--- a/src/H5FAstat.c
+++ b/src/H5FAstat.c
@@ -38,6 +38,7 @@
#include "H5private.h" /* Generic Functions */
#include "H5Eprivate.h" /* Error handling */
#include "H5FApkg.h" /* Fixed Arrays */
+#include "H5MMprivate.h" /* Memory management */
/****************/
@@ -105,7 +106,7 @@ HDfprintf(stderr, "%s: Called\n", FUNC);
HDassert(stats);
/* Copy fixed array statistics */
- HDmemcpy(stats, &fa->hdr->stats, sizeof(fa->hdr->stats));
+ H5MM_memcpy(stats, &fa->hdr->stats, sizeof(fa->hdr->stats));
END_FUNC(PRIV) /* end H5FA_get_stats() */
diff --git a/src/H5FAtest.c b/src/H5FAtest.c
index 27cd8b7..e55d408 100644
--- a/src/H5FAtest.c
+++ b/src/H5FAtest.c
@@ -315,7 +315,7 @@ H5FA__test_debug(FILE *stream, int indent, int fwidth, hsize_t idx,
HDassert(elmt);
/* Print element */
- sprintf(temp_str, "Element #%llu:", (unsigned long long)idx);
+ HDsprintf(temp_str, "Element #%llu:", (unsigned long long)idx);
HDfprintf(stream, "%*s%-*s %llu\n", indent, "", fwidth, temp_str,
(unsigned long long)*(const uint64_t *)elmt);
diff --git a/src/H5FD.c b/src/H5FD.c
index 1975a68..b104180 100644
--- a/src/H5FD.c
+++ b/src/H5FD.c
@@ -293,7 +293,7 @@ H5FD_register(const void *_cls, size_t size, hbool_t app_ref)
/* Copy the class structure so the caller can reuse or free it */
if(NULL == (saved = (H5FD_class_t *)H5MM_malloc(size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5I_INVALID_HID, "memory allocation failed for file driver class struct")
- HDmemcpy(saved, cls, size);
+ H5MM_memcpy(saved, cls, size);
/* Create the new class ID */
if((ret_value = H5I_register(H5I_VFL, saved, app_ref)) < 0)
@@ -1370,7 +1370,7 @@ H5FD_get_fs_type_map(const H5FD_t *file, H5FD_mem_t *type_map)
} /* end if */
else
/* Copy class's default free space type mapping */
- HDmemcpy(type_map, file->cls->fl_map, sizeof(file->cls->fl_map));
+ H5MM_memcpy(type_map, file->cls->fl_map, sizeof(file->cls->fl_map));
done:
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5FDcore.c b/src/H5FDcore.c
index 2ab04dc..6db8af6 100644
--- a/src/H5FDcore.c
+++ b/src/H5FDcore.c
@@ -54,6 +54,7 @@ typedef struct H5FD_core_t {
haddr_t eof; /* current allocated size */
size_t increment; /* multiples for mem allocation */
hbool_t backing_store; /* write to file name on flush */
+ hbool_t write_tracking; /* Whether to track writes */
size_t bstore_page_size; /* backing store page size */
int fd; /* backing store file descriptor */
/* Information for determining uniqueness of a file with a backing store */
@@ -93,10 +94,14 @@ typedef struct H5FD_core_t {
typedef struct H5FD_core_fapl_t {
size_t increment; /* how much to grow memory */
hbool_t backing_store; /* write to file name on flush */
+ hbool_t write_tracking; /* Whether to track writes */
+ size_t page_size; /* Page size for tracked writes */
} H5FD_core_fapl_t;
/* Allocate memory in multiples of this size by default */
-#define H5FD_CORE_INCREMENT 8192
+#define H5FD_CORE_INCREMENT 8192
+#define H5FD_CORE_WRITE_TRACKING_FLAG FALSE
+#define H5FD_CORE_WRITE_TRACKING_PAGE_SIZE 524288
/* These macros check for overflow of various quantities. These macros
* assume that file_offset_t is signed and haddr_t and size_t are unsigned.
@@ -343,14 +348,17 @@ H5FD__core_write_to_bstore(H5FD_core_t *file, haddr_t addr, size_t size)
HDassert(file);
- /* Write to backing store */
- if((off_t)addr != HDlseek(file->fd, (off_t)addr, SEEK_SET))
+#ifndef H5_HAVE_PREADWRITE
+ /* Seek to the correct location (if we don't have pwrite) */
+ if((HDoff_t)addr != HDlseek(file->fd, (off_t)addr, SEEK_SET))
HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "error seeking in backing store")
+#endif /* H5_HAVE_PREADWRITE */
while (size > 0) {
h5_posix_io_t bytes_in = 0; /* # of bytes to write */
h5_posix_io_ret_t bytes_wrote = -1; /* # of bytes written */
+ HDoff_t offset = (HDoff_t)addr;
/* Trying to write more bytes than the return type can handle is
* undefined behavior in POSIX.
@@ -361,15 +369,21 @@ H5FD__core_write_to_bstore(H5FD_core_t *file, haddr_t addr, size_t size)
bytes_in = (h5_posix_io_t)size;
do {
+#ifdef H5_HAVE_PREADWRITE
+ bytes_wrote = HDpwrite(file->fd, ptr, bytes_in, offset);
+ offset += bytes_wrote;
+#else
bytes_wrote = HDwrite(file->fd, ptr, bytes_in);
+#endif /* H5_HAVE_PREADWRITE */
} while(-1 == bytes_wrote && EINTR == errno);
if(-1 == bytes_wrote) { /* error */
int myerrno = errno;
time_t mytime = HDtime(NULL);
- HDoff_t myoffset = HDlseek(file->fd, (HDoff_t)0, SEEK_CUR);
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "write to backing store failed: time = %s, filename = '%s', file descriptor = %d, errno = %d, error message = '%s', ptr = %p, total write size = %llu, bytes this sub-write = %llu, bytes actually written = %llu, offset = %llu", HDctime(&mytime), file->name, file->fd, myerrno, HDstrerror(myerrno), ptr, (unsigned long long)size, (unsigned long long)bytes_in, (unsigned long long)bytes_wrote, (unsigned long long)myoffset);
+ offset = HDlseek(file->fd, (HDoff_t)0, SEEK_CUR);
+
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "write to backing store failed: time = %s, filename = '%s', file descriptor = %d, errno = %d, error message = '%s', ptr = %p, total write size = %llu, bytes this sub-write = %llu, bytes actually written = %llu, offset = %llu", HDctime(&mytime), file->name, file->fd, myerrno, HDstrerror(myerrno), ptr, (unsigned long long)size, (unsigned long long)bytes_in, (unsigned long long)bytes_wrote, (unsigned long long)offset);
} /* end if */
HDassert(bytes_wrote > 0);
@@ -415,8 +429,8 @@ done:
* Purpose: Initialize this driver by registering the driver with the
* library.
*
- * Return: Success: The driver ID for the core driver.
- * Failure: Negative.
+ * Return: Success: The driver ID for the core driver
+ * Failure: H5I_INVALID_HID
*
* Programmer: Robb Matzke
* Thursday, July 29, 1999
@@ -428,7 +442,7 @@ H5FD_core_init(void)
{
hid_t ret_value = H5I_INVALID_HID; /* Return value */
- FUNC_ENTER_NOAPI(FAIL)
+ FUNC_ENTER_NOAPI(H5I_INVALID_HID)
if(H5I_VFL != H5I_get_type(H5FD_CORE_g))
H5FD_CORE_g = H5FD_register(&H5FD_core_g, sizeof(H5FD_class_t), FALSE);
@@ -466,6 +480,100 @@ H5FD__core_term(void)
/*-------------------------------------------------------------------------
+ * Function: H5Pset_core_write_tracking
+ *
+ * Purpose: Enables/disables core VFD write tracking and page
+ * aggregation size.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Dana Robinson
+ * Tuesday, April 8, 2014
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Pset_core_write_tracking(hid_t plist_id, hbool_t is_enabled, size_t page_size)
+{
+ H5P_genplist_t *plist; /* Property list pointer */
+ H5FD_core_fapl_t fa; /* Core VFD info */
+ const H5FD_core_fapl_t *old_fa; /* Old core VFD info */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE3("e", "ibz", plist_id, is_enabled, page_size);
+
+ /* The page size cannot be zero */
+ if(page_size == 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "page_size cannot be zero")
+
+ /* Get the plist structure */
+ if(NULL == (plist = H5P_object_verify(plist_id, H5P_FILE_ACCESS)))
+ HGOTO_ERROR(H5E_PLIST, H5E_BADATOM, FAIL, "can't find object for ID")
+ if(H5FD_CORE != H5P_peek_driver(plist))
+ HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "incorrect VFL driver")
+ if(NULL == (old_fa = (const H5FD_core_fapl_t *)H5P_peek_driver_info(plist)))
+ HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "bad VFL driver info")
+
+ /* Set VFD info values */
+ HDmemset(&fa, 0, sizeof(H5FD_core_fapl_t));
+ fa.increment = old_fa->increment;
+ fa.backing_store = old_fa->backing_store;
+ fa.write_tracking = is_enabled;
+ fa.page_size = page_size;
+
+ /* Set the property values & the driver for the FAPL */
+ if(H5P_set_driver(plist, H5FD_CORE, &fa) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set core VFD as driver")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Pset_core_write_tracking() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Pget_core_write_tracking
+ *
+ * Purpose: Gets information about core VFD write tracking and page
+ * aggregation size.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Dana Robinson
+ * Tuesday, April 8, 2014
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Pget_core_write_tracking(hid_t plist_id, hbool_t *is_enabled, size_t *page_size)
+{
+ H5P_genplist_t *plist; /* Property list pointer */
+ const H5FD_core_fapl_t *fa; /* Core VFD info */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE3("e", "i*b*z", plist_id, is_enabled, page_size);
+
+ /* Get the plist structure */
+ if(NULL == (plist = H5P_object_verify(plist_id, H5P_FILE_ACCESS)))
+ HGOTO_ERROR(H5E_PLIST, H5E_BADATOM, FAIL, "can't find object for ID")
+ if(H5FD_CORE != H5P_peek_driver(plist))
+ HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "incorrect VFL driver")
+ if(NULL == (fa = (const H5FD_core_fapl_t *)H5P_peek_driver_info(plist)))
+ HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "bad VFL driver info")
+
+ /* Get values */
+ if(is_enabled)
+ *is_enabled = fa->write_tracking;
+ if(page_size)
+ *page_size = fa->page_size;
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Pget_core_write_tracking() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5Pset_fapl_core
*
* Purpose: Modify the file access property list to use the H5FD_CORE
@@ -482,9 +590,9 @@ H5FD__core_term(void)
herr_t
H5Pset_fapl_core(hid_t fapl_id, size_t increment, hbool_t backing_store)
{
- H5FD_core_fapl_t fa;
- H5P_genplist_t *plist; /* Property list pointer */
- herr_t ret_value;
+ H5P_genplist_t *plist; /* Property list pointer */
+ H5FD_core_fapl_t fa; /* Core VFD info */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE3("e", "izb", fapl_id, increment, backing_store);
@@ -493,10 +601,16 @@ H5Pset_fapl_core(hid_t fapl_id, size_t increment, hbool_t backing_store)
if(NULL == (plist = H5P_object_verify(fapl_id,H5P_FILE_ACCESS)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list")
+ /* Set VFD info values */
+ HDmemset(&fa, 0, sizeof(H5FD_core_fapl_t));
fa.increment = increment;
fa.backing_store = backing_store;
+ fa.write_tracking = H5FD_CORE_WRITE_TRACKING_FLAG;
+ fa.page_size = H5FD_CORE_WRITE_TRACKING_PAGE_SIZE;
- ret_value = H5P_set_driver(plist, H5FD_CORE, &fa);
+ /* Set the property values & the driver for the FAPL */
+ if(H5P_set_driver(plist, H5FD_CORE, &fa) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set core VFD as driver")
done:
FUNC_LEAVE_API(ret_value)
@@ -518,9 +632,9 @@ done:
herr_t
H5Pget_fapl_core(hid_t fapl_id, size_t *increment /*out*/, hbool_t *backing_store /*out*/)
{
- H5P_genplist_t *plist; /* Property list pointer */
- const H5FD_core_fapl_t *fa;
- herr_t ret_value = SUCCEED; /* Return value */
+ H5P_genplist_t *plist; /* Property list pointer */
+ const H5FD_core_fapl_t *fa; /* Core VFD info */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE3("e", "ixx", fapl_id, increment, backing_store);
@@ -559,7 +673,7 @@ static void *
H5FD__core_fapl_get(H5FD_t *_file)
{
H5FD_core_t *file = (H5FD_core_t*)_file;
- H5FD_core_fapl_t *fa;
+ H5FD_core_fapl_t *fa; /* Core VFD info */
void *ret_value = NULL; /* Return value */
FUNC_ENTER_STATIC
@@ -569,6 +683,8 @@ H5FD__core_fapl_get(H5FD_t *_file)
fa->increment = file->increment;
fa->backing_store = (hbool_t)(file->fd >= 0);
+ fa->write_tracking = file->write_tracking;
+ fa->page_size = file->bstore_page_size;
/* Set return value */
ret_value = fa;
@@ -732,7 +848,7 @@ H5FD__core_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr
HGOTO_ERROR(H5E_FILE, H5E_CANTCOPY, NULL, "image_memcpy callback failed")
} /* end if */
else
- HDmemcpy(file->mem, file_image_info.buffer, size);
+ H5MM_memcpy(file->mem, file_image_info.buffer, size);
} /* end if */
/* Read in existing data from the file if there is no image */
else {
@@ -745,6 +861,7 @@ H5FD__core_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr
while(size > 0) {
h5_posix_io_t bytes_in = 0; /* # of bytes to read */
h5_posix_io_ret_t bytes_read = -1; /* # of bytes actually read */
+ HDoff_t offset = (HDoff_t)0;
/* Trying to read more bytes than the return type can handle is
* undefined behavior in POSIX.
@@ -755,15 +872,21 @@ H5FD__core_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr
bytes_in = (h5_posix_io_t)size;
do {
+#ifdef H5_HAVE_PREADWRITE
+ bytes_read = HDpread(file->fd, mem, bytes_in, offset);
+ offset += bytes_read;
+#else
bytes_read = HDread(file->fd, mem, bytes_in);
+#endif /* H5_HAVE_PREADWRITE */
} while(-1 == bytes_read && EINTR == errno);
if(-1 == bytes_read) { /* error */
int myerrno = errno;
time_t mytime = HDtime(NULL);
- HDoff_t myoffset = HDlseek(file->fd, (HDoff_t)0, SEEK_CUR);
- HGOTO_ERROR(H5E_IO, H5E_READERROR, NULL, "file read failed: time = %s, filename = '%s', file descriptor = %d, errno = %d, error message = '%s', file->mem = %p, total read size = %llu, bytes this sub-read = %llu, bytes actually read = %llu, offset = %llu", HDctime(&mytime), file->name, file->fd, myerrno, HDstrerror(myerrno), file->mem, (unsigned long long)size, (unsigned long long)bytes_in, (unsigned long long)bytes_read, (unsigned long long)myoffset);
+ offset = HDlseek(file->fd, (HDoff_t)0, SEEK_CUR);
+
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, NULL, "file read failed: time = %s, filename = '%s', file descriptor = %d, errno = %d, error message = '%s', file->mem = %p, total read size = %llu, bytes this sub-read = %llu, bytes actually read = %llu, offset = %llu", HDctime(&mytime), file->name, file->fd, myerrno, HDstrerror(myerrno), file->mem, (unsigned long long)size, (unsigned long long)bytes_in, (unsigned long long)bytes_read, (unsigned long long)offset);
} /* end if */
HDassert(bytes_read >= 0);
@@ -776,35 +899,28 @@ H5FD__core_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr
} /* end if */
} /* end if */
+ /* Get the write tracking & page size */
+ file->write_tracking = fa->write_tracking;
+ file->bstore_page_size = fa->page_size;
+
/* Set up write tracking if the backing store is on */
file->dirty_list = NULL;
if(fa->backing_store) {
- hbool_t write_tracking_flag = FALSE; /* what the user asked for */
hbool_t use_write_tracking = FALSE; /* what we're actually doing */
- /* Get the write tracking flag */
- if(H5P_get(plist, H5F_ACS_CORE_WRITE_TRACKING_FLAG_NAME, &write_tracking_flag) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get core VFD write tracking flag");
-
- /* Get the page size */
- if(H5P_get(plist, H5F_ACS_CORE_WRITE_TRACKING_PAGE_SIZE_NAME, &(file->bstore_page_size)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get core VFD write tracking page size");
-
/* default is to have write tracking OFF for create (hence the check to see
* if the user explicitly set a page size) and ON with the default page size
* on open (when not read-only).
*/
/* Only use write tracking if the file is open for writing */
- use_write_tracking =
- TRUE == write_tracking_flag /* user asked for write tracking */
- && !(o_flags & O_RDONLY) /* file is open for writing (i.e. not read-only) */
- && file->bstore_page_size != 0; /* page size is not zero */
+ use_write_tracking = (TRUE == fa->write_tracking) /* user asked for write tracking */
+ && !(o_flags & O_RDONLY) /* file is open for writing (i.e. not read-only) */
+ && (file->bstore_page_size != 0); /* page size is not zero */
/* initialize the dirty list */
- if(use_write_tracking) {
+ if(use_write_tracking)
if(NULL == (file->dirty_list = H5SL_create(H5SL_TYPE_HADDR, NULL)))
HGOTO_ERROR(H5E_SLIST, H5E_CANTCREATE, NULL, "can't create core vfd dirty region list");
- } /* end if */
} /* end if */
/* Set return value */
@@ -1184,7 +1300,7 @@ H5FD__core_read(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type, hid_t H5_ATTR_UNU
nbytes = MIN(size,(size_t)(file->eof-addr));
#endif /* NDEBUG */
- HDmemcpy(buf, file->mem + addr, nbytes);
+ H5MM_memcpy(buf, file->mem + addr, nbytes);
size -= nbytes;
addr += nbytes;
buf = (char *)buf + nbytes;
@@ -1270,7 +1386,7 @@ H5FD__core_write(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type, hid_t H5_ATTR_UN
}
/* Write from BUF to memory */
- HDmemcpy(file->mem + addr, buf, size);
+ H5MM_memcpy(file->mem + addr, buf, size);
/* Mark memory buffer as modified */
file->dirty = TRUE;
diff --git a/src/H5FDdirect.c b/src/H5FDdirect.c
index 906ec28..33a0ef4 100644
--- a/src/H5FDdirect.c
+++ b/src/H5FDdirect.c
@@ -206,30 +206,27 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5FD_direct_init
+ * Function: H5FD_direct_init
*
- * Purpose: Initialize this driver by registering the driver with the
- * library.
+ * Purpose: Initialize this driver by registering the driver with the
+ * library.
*
- * Return: Success: The driver ID for the direct driver.
- *
- * Failure: Negative.
+ * Return: Success: The driver ID for the direct driver
+ * Failure: H5I_INVALID_HID
*
* Programmer: Raymond Lu
* Wednesday, 20 September 2006
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
hid_t
H5FD_direct_init(void)
{
- hid_t ret_value; /* Return value */
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
- FUNC_ENTER_NOAPI(FAIL)
+ FUNC_ENTER_NOAPI(H5I_INVALID_HID)
- if (H5I_VFL!=H5I_get_type(H5FD_DIRECT_g))
+ if (H5I_VFL != H5I_get_type(H5FD_DIRECT_g))
H5FD_DIRECT_g = H5FD_register(&H5FD_direct_g,sizeof(H5FD_class_t),FALSE);
/* Set return value */
@@ -237,7 +234,7 @@ H5FD_direct_init(void)
done:
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FD_direct_init() */
/*---------------------------------------------------------------------------
@@ -291,6 +288,7 @@ H5Pset_fapl_direct(hid_t fapl_id, size_t boundary, size_t block_size, size_t cbu
if(NULL == (plist = H5P_object_verify(fapl_id,H5P_FILE_ACCESS)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list")
+ HDmemset(&fa, 0, sizeof(H5FD_direct_fapl_t));
if(boundary != 0)
fa.mboundary = boundary;
else
@@ -417,14 +415,14 @@ static void *
H5FD_direct_fapl_copy(const void *_old_fa)
{
const H5FD_direct_fapl_t *old_fa = (const H5FD_direct_fapl_t*)_old_fa;
- H5FD_direct_fapl_t *new_fa = H5MM_malloc(sizeof(H5FD_direct_fapl_t));
+ H5FD_direct_fapl_t *new_fa = H5MM_calloc(sizeof(H5FD_direct_fapl_t));
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(new_fa);
/* Copy the general information */
- HDmemcpy(new_fa, old_fa, sizeof(H5FD_direct_fapl_t));
+ H5MM_memcpy(new_fa, old_fa, sizeof(H5FD_direct_fapl_t));
FUNC_LEAVE_NOAPI(new_fa)
} /* end H5FD_direct_fapl_copy() */
@@ -978,12 +976,12 @@ H5FD_direct_read(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type, hid_t H5_ATTR_UN
* next section of data. */
p2 = (unsigned char*)copy_buf + copy_offset;
if((copy_size + copy_offset) <= alloc_size) {
- HDmemcpy(buf, p2, copy_size);
+ H5MM_memcpy(buf, p2, copy_size);
buf = (unsigned char *)buf + copy_size;
copy_size = 0;
} /* end if */
else {
- HDmemcpy(buf, p2, alloc_size - copy_offset);
+ H5MM_memcpy(buf, p2, alloc_size - copy_offset);
buf = (unsigned char*)buf + alloc_size - copy_offset;
copy_size -= alloc_size - copy_offset;
copy_offset = 0;
@@ -1191,11 +1189,11 @@ H5FD_direct_write(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type, hid_t H5_ATTR_U
*/
p1 = (unsigned char *)copy_buf + copy_offset;
if((copy_size + copy_offset) <= alloc_size) {
- HDmemcpy(p1, p3, copy_size);
+ H5MM_memcpy(p1, p3, copy_size);
copy_size = 0;
} /* end if */
else {
- HDmemcpy(p1, p3, alloc_size - copy_offset);
+ H5MM_memcpy(p1, p3, alloc_size - copy_offset);
p3 = (const unsigned char *)p3 + (alloc_size - copy_offset);
copy_size -= alloc_size - copy_offset;
copy_offset = 0;
diff --git a/src/H5FDfamily.c b/src/H5FDfamily.c
index e52a71a..bc00403 100644
--- a/src/H5FDfamily.c
+++ b/src/H5FDfamily.c
@@ -171,28 +171,25 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5FD_family_init
+ * Function: H5FD_family_init
*
- * Purpose: Initialize this driver by registering the driver with the
- * library.
+ * Purpose: Initialize this driver by registering the driver with the
+ * library.
*
- * Return: Success: The driver ID for the family driver.
+ * Return: Success: The driver ID for the family driver
+ * Failure: H5I_INVALID_HID
*
- * Failure: Negative
- *
- * Programmer: Robb Matzke
+ * Programmer: Robb Matzke
* Wednesday, August 4, 1999
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
hid_t
H5FD_family_init(void)
{
- hid_t ret_value = H5FD_FAMILY_g; /* Return value */
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
- FUNC_ENTER_NOAPI(FAIL)
+ FUNC_ENTER_NOAPI(H5I_INVALID_HID)
if(H5I_VFL != H5I_get_type(H5FD_FAMILY_g))
H5FD_FAMILY_g = H5FD_register(&H5FD_family_g, sizeof(H5FD_class_t), FALSE);
@@ -414,7 +411,7 @@ H5FD_family_fapl_copy(const void *_old_fa)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* Copy the fields of the structure */
- HDmemcpy(new_fa, old_fa, sizeof(H5FD_family_fapl_t));
+ H5MM_memcpy(new_fa, old_fa, sizeof(H5FD_family_fapl_t));
/* Deep copy the property list objects in the structure */
if(old_fa->memb_fapl_id==H5P_FILE_ACCESS_DEFAULT) {
@@ -616,6 +613,14 @@ done:
*
*-------------------------------------------------------------------------
*/
+/* Disable warning for "format not a string literal" here -QAK */
+/*
+ * This pragma only needs to surround the snprintf() calls with
+ * memb_name & temp in the code below, but early (4.4.7, at least) gcc only
+ * allows diagnostic pragmas to be toggled outside of functions.
+ */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
static H5FD_t *
H5FD_family_open(const char *name, unsigned flags, hid_t fapl_id,
haddr_t maxaddr)
@@ -718,7 +723,7 @@ H5FD_family_open(const char *name, unsigned flags, hid_t fapl_id,
(0==file->nmembs ? flags : t_flags), file->memb_fapl_id, HADDR_UNDEF);
} H5E_END_TRY;
if (!file->memb[file->nmembs]) {
- if (0==file->nmembs)
+ if (0 == file->nmembs)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open member file")
H5E_clear_stack(NULL);
break;
@@ -726,7 +731,7 @@ H5FD_family_open(const char *name, unsigned flags, hid_t fapl_id,
file->nmembs++;
}
- /* If the file is reopened and there's only one member file existing, this file maybe
+ /* If the file is reopened and there's only one member file existing, this file may be
* smaller than the size specified through H5Pset_fapl_family(). Update the actual
* member size.
*/
@@ -766,6 +771,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5FD_family_open() */
+#pragma GCC diagnostic pop
/*-------------------------------------------------------------------------
@@ -945,6 +951,14 @@ H5FD_family_get_eoa(const H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type)
*
*-------------------------------------------------------------------------
*/
+/* Disable warning for "format not a string literal" here -QAK */
+/*
+ * This pragma only needs to surround the snprintf() call with
+ * memb_name in the code below, but early (4.4.7, at least) gcc only
+ * allows diagnostic pragmas to be toggled outside of functions.
+ */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
static herr_t
H5FD_family_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t abs_eoa)
{
@@ -1011,6 +1025,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
}
+#pragma GCC diagnostic pop
/*-------------------------------------------------------------------------
diff --git a/src/H5FDhdfs.c b/src/H5FDhdfs.c
new file mode 100644
index 0000000..819d200
--- /dev/null
+++ b/src/H5FDhdfs.c
@@ -0,0 +1,2167 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Read-Only HDFS Virtual File Driver (VFD) *
+ * Copyright (c) 2018, The HDF Group. *
+ * *
+ * All rights reserved. *
+ * *
+ * NOTICE: *
+ * All information contained herein is, and remains, the property of The HDF *
+ * Group. The intellectual and technical concepts contained herein are *
+ * proprietary to The HDF Group. Dissemination of this information or *
+ * reproduction of this material is strictly forbidden unless prior written *
+ * permission is obtained from The HDF Group. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Programmer: Jacob Smith
+ * 2018-04-23
+ *
+ * Purpose: Provide read-only access to files on the Hadoop Distributed
+ * File System (HDFS).
+ */
+
+/* This source code file is part of the H5FD driver module */
+#include "H5FDdrvr_module.h"
+
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5FDprivate.h" /* File drivers */
+#include "H5FDhdfs.h" /* hdfs file driver */
+#include "H5FLprivate.h" /* Free Lists */
+#include "H5Iprivate.h" /* IDs */
+#include "H5MMprivate.h" /* Memory management */
+
+#ifdef H5_HAVE_LIBHDFS
+#include "hdfs.h"
+#endif
+
+/* toggle function call prints: 1 turns on */
+#define HDFS_DEBUG 0
+
+/* toggle stats collection and reporting */
+#define HDFS_STATS 0
+
+/* The driver identification number, initialized at runtime */
+static hid_t H5FD_HDFS_g = 0;
+
+#if HDFS_STATS
+
+/* arbitrarily large value, such that any reasonable size read will be "less"
+ * than this value and set a true minimum
+ * not 0 because that may be a valid recorded minimum in degenerate cases
+ */
+#define HDFS_STATS_STARTING_MIN 0xfffffffful
+
+/* Configuration definitions for stats collection and breakdown
+ *
+ * 2^10 = 1024
+ * Reads up to 1024 bytes (1 kB) fall in bin 0
+ * 2^(10+(1*16)) = 2^26 = 64MB
+ * Reads of 64MB or greater fall in "overflow" bin[BIN_COUNT]
+ */
+#define HDFS_STATS_BASE 2
+#define HDFS_STATS_INTERVAL 1
+#define HDFS_STATS_START_POWER 10
+#define HDFS_STATS_BIN_COUNT 16 /* MUST BE GREATER THAN 0 */
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Calculate `BASE ^ (START_POWER + (INTERVAL * bin_i))`
+ * Stores result at `(unsigned long long *) out_ptr`.
+ * Used in computing boundaries between stats bins.
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ */
+#define HDFS_STATS_POW(bin_i, out_ptr) { \
+ unsigned long long donotshadowresult = 1; \
+ unsigned donotshadowindex = 0; \
+ for (donotshadowindex = 0; \
+ donotshadowindex < (((bin_i) * HDFS_STATS_INTERVAL) + \
+ HDFS_STATS_START_POWER); \
+ donotshadowindex++) \
+ { \
+ donotshadowresult *= HDFS_STATS_BASE; \
+ } \
+ *(out_ptr) = donotshadowresult; \
+}
+
+/* array to hold pre-computed boundaries for stats bins */
+static unsigned long long hdfs_stats_boundaries[HDFS_STATS_BIN_COUNT];
+
+
+/***************************************************************************
+ *
+ * Structure: hdfs_statsbin
+ *
+ * Purpose:
+ *
+ * Structure for storing per-file hdfs VFD usage statistics.
+ *
+ *
+ *
+ * `count` (unsigned long long)
+ *
+ * Number of reads with size in this bin's range.
+ *
+ * `bytes` (unsigned long long)
+ *
+ * Total number of bytes read through this bin.
+ *
+ * `min` (unsigned long long)
+ *
+ * Smallest read size in this bin.
+ *
+ * `max` (unsigned long long)
+ *
+ * Largest read size in this bin.
+ *
+ *
+ *
+ * Programmer: Jacob Smith
+ *
+ * Changes: None
+ *
+ ***************************************************************************/
+typedef struct {
+ unsigned long long count;
+ unsigned long long bytes;
+ unsigned long long min;
+ unsigned long long max;
+} hdfs_statsbin;
+
+#endif /* HDFS_STATS */
+
+#ifdef H5_HAVE_LIBHDFS
+
+/* "unique" identifier for `hdfs_t` structures.
+ * Randomly generated by unweighted dice rolls.
+ */
+#define HDFS_HDFST_MAGIC 0x1AD5DE84
+
+
+/***************************************************************************
+ *
+ * Structure: hdfs_t
+ *
+ * Purpose:
+ *
+ * Contain/retain information associated with a file hosted on Hadoop
+ * Distributed File System (HDFS). Instantiated and populated via
+ * `H5FD_hdfs_handle_open()` and cleaned up via `H5FD_hdfs_handle_close()`.
+ *
+ *
+ *
+ * `magic` (unisgned long)
+ *
+ * Number to indicate that this structure is of the promised
+ * type and should still be valid; should be HDFS_HDFST_MAGIC throughout
+ * the lifespan of the structure. Upon deletion of the structure, the
+ * programmer should set magic to anything but HDFS_HDFST_MAGIC, to
+ * indicate that the structure is to no longer be trusted.
+ *
+ * `filesystem` (hdfsFS)
+ *
+ * A libhdfs file system handle.
+ *
+ * `fileinfo` (hdfsFileInfo*)
+ *
+ * A pointer to a libhdfs file info structure.
+ *
+ * `file` (hdfsFile)
+ *
+ * A libhdfs file handle.
+ *
+ *
+ *
+ * Programmer: Jacob Smith
+ * May 2018
+ *
+ * Changes: None
+ *
+ ***************************************************************************
+ */
+typedef struct {
+ unsigned long magic;
+ hdfsFS filesystem;
+ hdfsFileInfo *fileinfo;
+ hdfsFile file;
+} hdfs_t;
+
+
+/*--------------------------------------------------------------------------
+ * Function: H5FD_hdfs_handle_open
+ *
+ * Purpose: Create a HDFS file handle, 'opening' the target file.
+ *
+ * Return: Success: Pointer to HDFS container/handle of opened file.
+ * Failure: NULL
+ *
+ * Programmer: Gerd Herber
+ * May 2018
+ *
+ * Changes: None.
+ *--------------------------------------------------------------------------
+ */
+static hdfs_t *
+H5FD_hdfs_handle_open(
+ const char *path,
+ const char *namenode_name,
+ const int32_t namenode_port,
+ const char *user_name,
+ const char *kerberos_ticket_cache,
+ const int32_t stream_buffer_size)
+{
+ struct hdfsBuilder *builder = NULL;
+ hdfs_t *handle = NULL;
+ hdfs_t *ret_value = NULL;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+#if HDFS_DEBUG
+ HDfprintf(stdout, "called H5FD_hdfs_handle_open.\n");
+#endif
+
+ if (path == NULL || path[0] == '\0') {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL,
+ "path cannot be null.\n")
+ }
+ if (namenode_name == NULL /* || namenode_name[0] == '\0' */ ) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL,
+ "namenode name cannot be null.\n")
+ }
+ if (namenode_port < 0 || namenode_port > 65535) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL,
+ "namenode port must be non-negative and <= 65535.\n")
+ }
+ if (stream_buffer_size < 0) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL,
+ "buffer size must non-negative.\n")
+ }
+
+ handle = (hdfs_t *)H5MM_malloc(sizeof(hdfs_t));
+ if (handle == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTALLOC, NULL,
+ "could not malloc space for handle.\n")
+ }
+
+ handle->magic = (unsigned long)HDFS_HDFST_MAGIC;
+ handle->filesystem = NULL; /* TODO: not a pointer; NULL may cause bug */
+ handle->fileinfo = NULL;
+ handle->file = NULL; /* TODO: not a pointer; NULL may cause bug */
+
+ builder = hdfsNewBuilder();
+ if (!builder) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL,
+ "(hdfs) failed to create builder")
+ }
+ hdfsBuilderSetNameNode(builder, namenode_name);
+ hdfsBuilderSetNameNodePort(builder, (tPort)namenode_port);
+ if (user_name != NULL && user_name[0] != '\0') {
+ hdfsBuilderSetUserName(builder, user_name);
+ }
+ if (kerberos_ticket_cache != NULL && kerberos_ticket_cache[0] != '\0') {
+ hdfsBuilderSetKerbTicketCachePath(builder, kerberos_ticket_cache);
+ }
+ /* Call to `hdfsBuilderConnect` releases builder, regardless of success. */
+ handle->filesystem = hdfsBuilderConnect(builder);
+ if (!handle->filesystem) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL,
+ "(hdfs) could not connect to default namenode")
+ }
+ handle->fileinfo = hdfsGetPathInfo(handle->filesystem, path);
+ if (!handle->fileinfo) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL,
+ "hdfsGetPathInfo failed")
+ }
+ handle->file = hdfsOpenFile(
+ handle->filesystem,
+ path,
+ O_RDONLY,
+ stream_buffer_size,
+ 0,
+ 0);
+ if (!handle->file) {
+ HGOTO_ERROR(H5E_VFL, H5E_CANTOPENFILE, NULL,
+ "(hdfs) could not open")
+ }
+
+ ret_value = handle;
+
+done:
+ if (ret_value == NULL && handle != NULL) {
+ /* error; clean up */
+ HDassert(handle->magic == HDFS_HDFST_MAGIC);
+ handle->magic++;
+ if (handle->file != NULL) {
+ if (FAIL == (hdfsCloseFile(handle->filesystem, handle->file))) {
+ HDONE_ERROR(H5E_VFL, H5E_CANTCLOSEFILE, NULL,
+ "unable to close hdfs file handle")
+ }
+ }
+ if (handle->fileinfo != NULL) {
+ hdfsFreeFileInfo(handle->fileinfo, 1);
+ }
+ if (handle->filesystem != NULL) {
+ if (FAIL == (hdfsDisconnect(handle->filesystem))) {
+ HDONE_ERROR(H5E_VFL, H5E_CANTCLOSEFILE, NULL,
+ "unable to disconnect from hdfs")
+ }
+ }
+ H5MM_xfree(handle);
+ }
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5FD_hdfs_handle_open() */
+
+
+/*--------------------------------------------------------------------------
+ * Function: H5FD_hdfs_handle_close
+ *
+ * Purpose: 'Close' an HDFS file container/handle, releasing underlying
+ * resources.
+ *
+ * Return: Success: `SUCCEED` (0)
+ * Failure: `FAIL` (-1)
+ *
+ * Programmer: Gerd Herber
+ * May 2018
+ *
+ * Changes: None.
+ *--------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_hdfs_handle_close(hdfs_t *handle)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+#if HDFS_DEBUG
+ HDfprintf(stdout, "called H5FD_hdfs_close.\n");
+#endif
+
+ if (handle == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "handle cannot be null.\n")
+ }
+ if (handle->magic != HDFS_HDFST_MAGIC) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "handle has invalid magic.\n")
+ }
+
+ handle->magic++;
+ if (handle->file != NULL) {
+ if (FAIL == (hdfsCloseFile(handle->filesystem, handle->file))) {
+ HDONE_ERROR(H5E_VFL, H5E_CANTCLOSEFILE, FAIL,
+ "unable to close hdfs file handle")
+ }
+ }
+ if (handle->fileinfo != NULL) {
+ hdfsFreeFileInfo(handle->fileinfo, 1);
+ }
+ if (handle->filesystem != NULL) {
+ if (FAIL == (hdfsDisconnect(handle->filesystem))) {
+ HDONE_ERROR(H5E_VFL, H5E_CANTCLOSEFILE, FAIL,
+ "unable to disconnect hdfs file system")
+ }
+ }
+
+ H5MM_xfree(handle);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5FD_hdfs_close() */
+
+#endif /* H5_HAVE_LIBHDFS */
+
+
+/***************************************************************************
+ *
+ * Structure: H5FD_hdfs_t
+ *
+ * Purpose:
+ *
+ * H5FD_hdfs_t is a structure used to store all information needed to
+ * maintain R/O access to a single HDF5 file in an HDFS file system.
+ * This structure is created when such a file is "opened" and
+ * discarded when it is "closed".
+ *
+ *
+ * `pub` (H5FD_t)
+ *
+ * Instance of H5FD_t which contains all fields common to all VFDs.
+ * It must be the first item in this structure, since at higher levels,
+ * this structure will be treated as an instance of H5FD_t.
+ *
+ * `fa` (H5FD_hdfs_fapl_t)
+ *
+ * Instance of `H5FD_hdfs_fapl_t` containing the HDFS configuration data
+ * needed to "open" the HDF5 file.
+ *
+ * `eoa` (haddr_t)
+ *
+ * End of addressed space in file. After open, it should always
+ * equal the file size.
+ *
+ * `hdfs_handle` (hdfs_t *)
+ *
+ * Instance of HDFS Request handle associated with the target resource.
+ * Responsible for communicating with remote host and presenting file
+ * contents as indistinguishable from a file on the local filesystem.
+ *
+ * *** present only if HDFS_SATS is flagged to enable stats collection ***
+ *
+ * `meta` (hdfs_statsbin[])
+ * `raw` (hdfs_statsbin[])
+ *
+ * Only present if hdfs stats collection is enabled.
+ *
+ * Arrays of `hdfs_statsbin` structures to record raw- and metadata reads.
+ *
+ * Records count and size of reads performed by the VFD, and is used to
+ * print formatted usage statistics to stdout upon VFD shutdown.
+ *
+ * Reads of each raw- and metadata type are recorded in an individual bin
+ * determined by the size of the read. The last bin of each type is
+ * reserved for "big" reads, with no defined upper bound.
+ *
+ * *** end HDFS_STATS ***
+ *
+ *
+ *
+ * Programmer: Jacob Smith
+ *
+ * Changes: None.
+ *
+ ***************************************************************************
+ */
+typedef struct H5FD_hdfs_t {
+ H5FD_t pub;
+ H5FD_hdfs_fapl_t fa;
+ haddr_t eoa;
+#ifdef H5_HAVE_LIBHDFS
+ hdfs_t *hdfs_handle;
+#endif
+#if HDFS_STATS
+ hdfs_statsbin meta[HDFS_STATS_BIN_COUNT + 1];
+ hdfs_statsbin raw[HDFS_STATS_BIN_COUNT + 1];
+#endif
+} H5FD_hdfs_t;
+
+/*
+ * These macros check for overflow of various quantities. These macros
+ * assume that HDoff_t is signed and haddr_t and size_t are unsigned.
+ *
+ * ADDR_OVERFLOW: Checks whether a file address of type `haddr_t'
+ * is too large to be represented by the second argument
+ * of the file seek function.
+ * Only included if HDFS code should compile.
+ *
+ */
+#define MAXADDR (((haddr_t)1<<(8*sizeof(HDoff_t)-1))-1)
+#ifdef H5_HAVE_LIBHDFS
+#define ADDR_OVERFLOW(A) (HADDR_UNDEF==(A) || ((A) & ~(haddr_t)MAXADDR))
+#endif /* H5_HAVE_LIBHDFS */
+
+/* Prototypes */
+static herr_t H5FD_hdfs_term(void);
+static void *H5FD_hdfs_fapl_get(H5FD_t *_file);
+static void *H5FD_hdfs_fapl_copy(const void *_old_fa);
+static herr_t H5FD_hdfs_fapl_free(void *_fa);
+static H5FD_t *H5FD_hdfs_open(const char *name, unsigned flags, hid_t fapl_id,
+ haddr_t maxaddr);
+static herr_t H5FD_hdfs_close(H5FD_t *_file);
+static int H5FD_hdfs_cmp(const H5FD_t *_f1, const H5FD_t *_f2);
+static herr_t H5FD_hdfs_query(const H5FD_t *_f1, unsigned long *flags);
+static haddr_t H5FD_hdfs_get_eoa(const H5FD_t *_file, H5FD_mem_t type);
+static herr_t H5FD_hdfs_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t addr);
+static haddr_t H5FD_hdfs_get_eof(const H5FD_t *_file, H5FD_mem_t type);
+static herr_t H5FD_hdfs_get_handle(H5FD_t *_file, hid_t fapl,
+ void** file_handle);
+static herr_t H5FD_hdfs_read(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id,
+ haddr_t addr, size_t size, void *buf);
+static herr_t H5FD_hdfs_write(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id,
+ haddr_t addr, size_t size, const void *buf);
+static herr_t H5FD_hdfs_truncate(H5FD_t *_file, hid_t dxpl_id,
+ hbool_t closing);
+static herr_t H5FD_hdfs_lock(H5FD_t *_file, hbool_t rw);
+static herr_t H5FD_hdfs_unlock(H5FD_t *_file);
+static herr_t H5FD_hdfs_validate_config(const H5FD_hdfs_fapl_t * fa);
+
+static const H5FD_class_t H5FD_hdfs_g = {
+ "hdfs", /* name */
+ MAXADDR, /* maxaddr */
+ H5F_CLOSE_WEAK, /* fc_degree */
+ H5FD_hdfs_term, /* terminate */
+ NULL, /* sb_size */
+ NULL, /* sb_encode */
+ NULL, /* sb_decode */
+ sizeof(H5FD_hdfs_fapl_t), /* fapl_size */
+ H5FD_hdfs_fapl_get, /* fapl_get */
+ H5FD_hdfs_fapl_copy, /* fapl_copy */
+ H5FD_hdfs_fapl_free, /* fapl_free */
+ 0, /* dxpl_size */
+ NULL, /* dxpl_copy */
+ NULL, /* dxpl_free */
+ H5FD_hdfs_open, /* open */
+ H5FD_hdfs_close, /* close */
+ H5FD_hdfs_cmp, /* cmp */
+ H5FD_hdfs_query, /* query */
+ NULL, /* get_type_map */
+ NULL, /* alloc */
+ NULL, /* free */
+ H5FD_hdfs_get_eoa, /* get_eoa */
+ H5FD_hdfs_set_eoa, /* set_eoa */
+ H5FD_hdfs_get_eof, /* get_eof */
+ H5FD_hdfs_get_handle, /* get_handle */
+ H5FD_hdfs_read, /* read */
+ H5FD_hdfs_write, /* write */
+ NULL, /* flush */
+ H5FD_hdfs_truncate, /* truncate */
+ H5FD_hdfs_lock, /* lock */
+ H5FD_hdfs_unlock, /* unlock */
+ H5FD_FLMAP_DICHOTOMY /* fl_map */
+};
+
+#ifdef H5_HAVE_LIBHDFS
+/* Declare a free list to manage the H5FD_hdfs_t struct */
+H5FL_DEFINE_STATIC(H5FD_hdfs_t);
+#endif /* H5_HAVE_LIBHDFS */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD__init_package
+ *
+ * Purpose: Initializes any interface-specific data or routines.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Changes: Rename as appropriate for hdfs vfd.
+ * Jacob Smith 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD__init_package(void)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ if (H5FD_hdfs_init() < 0) {
+ HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL,
+ "unable to initialize hdfs VFD")
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5FD__init_package() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_hdfs_init
+ *
+ * Purpose: Initialize this driver by registering the driver with the
+ * library.
+ *
+ * Return: Success: The driver ID for the hdfs driver.
+ * Failure: Negative
+ *
+ * Programmer: Robb Matzke
+ * Thursday, July 29, 1999
+ *
+ * Changes: Rename as appropriate for hdfs vfd.
+ * Jacob Smith 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5FD_hdfs_init(void)
+{
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
+ unsigned int bin_i;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+#if HDFS_DEBUG
+ HDfprintf(stdout, "H5FD_hdfs_init() called.\n");
+#endif
+
+ if (H5I_VFL != H5I_get_type(H5FD_HDFS_g)) {
+ H5FD_HDFS_g = H5FD_register(
+ &H5FD_hdfs_g,
+ sizeof(H5FD_class_t),
+ FALSE);
+ }
+
+#if HDFS_STATS
+ /* pre-compute statsbin boundaries
+ */
+ for (bin_i = 0; bin_i < HDFS_STATS_BIN_COUNT; bin_i++) {
+ unsigned long long value = 0;
+ HDFS_STATS_POW(bin_i, &value)
+ hdfs_stats_boundaries[bin_i] = value;
+ }
+#endif
+
+ ret_value = H5FD_HDFS_g;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* end H5FD_hdfs_init() */
+
+
+/*---------------------------------------------------------------------------
+ * Function: H5FD_hdfs_term
+ *
+ * Purpose: Shut down the VFD
+ *
+ * Returns: SUCCEED (Can't fail)
+ *
+ * Programmer: Quincey Koziol
+ * Friday, Jan 30, 2004
+ *
+ * Changes: Rename as appropriate for hdfs vfd.
+ * Jacob Smith 2018
+ *
+ *---------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_hdfs_term(void)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+#if HDFS_DEBUG
+ HDfprintf(stdout, "H5FD_hdfs_term() called.\n");
+#endif
+
+ /* Reset VFL ID */
+ H5FD_HDFS_g = 0;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5FD_hdfs_term() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Pset_fapl_hdfs
+ *
+ * Purpose: Modify the file access property list to use the H5FD_HDFS
+ * driver defined in this source file. All driver specfic
+ * properties are passed in as a pointer to a suitably
+ * initialized instance of H5FD_hdfs_fapl_t
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: John Mainzer
+ * 9/10/17
+ *
+ * Changes: Rename as appropriate for hdfs vfd.
+ * Jacob Smith 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Pset_fapl_hdfs(hid_t fapl_id,
+ H5FD_hdfs_fapl_t *fa)
+{
+ H5P_genplist_t *plist = NULL; /* Property list pointer */
+ herr_t ret_value = FAIL;
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE2("e", "i*x", fapl_id, fa);
+
+ HDassert(fa != NULL);
+
+#if HDFS_DEBUG
+ HDfprintf(stdout, "H5Pset_fapl_hdfs() called.\n");
+#endif
+
+ plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS);
+ if (plist == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, \
+ "not a file access property list")
+ }
+
+ if (FAIL == H5FD_hdfs_validate_config(fa)) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "invalid hdfs config")
+ }
+
+ ret_value = H5P_set_driver(plist, H5FD_HDFS, (void *)fa);
+
+done:
+ FUNC_LEAVE_API(ret_value)
+
+} /* H5Pset_fapl_hdfs() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_hdfs_validate_config()
+ *
+ * Purpose: Test to see if the supplied instance of H5FD_hdfs_fapl_t
+ * contains internally consistant data. Return SUCCEED if so,
+ * and FAIL otherwise.
+ *
+ * Note the difference between internally consistant and
+ * correct. As we will have to try to access the target
+ * object to determine whether the supplied data is correct,
+ * we will settle for internal consistancy at this point
+ *
+ * Return: SUCCEED if instance of H5FD_hdfs_fapl_t contains internally
+ * consistant data, FAIL otherwise.
+ *
+ * Programmer: Jacob Smith
+ * 9/10/17
+ *
+ * Changes: None.
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_hdfs_validate_config(const H5FD_hdfs_fapl_t * fa)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ HDassert(fa != NULL);
+
+ if ( fa->version != H5FD__CURR_HDFS_FAPL_T_VERSION ) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "Unknown H5FD_hdfs_fapl_t version");
+ }
+
+ if ( fa->namenode_port > 65535 ) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "Invalid namenode port number");
+ }
+ if ( fa->namenode_port < 0 ) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "Invalid namenode port number");
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5FD_hdfs_validate_config() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Pget_fapl_hdfs
+ *
+ * Purpose: Returns information about the hdfs file access property
+ * list though the function arguments.
+ *
+ * Return: Success: Non-negative
+ *
+ * Failure: Negative
+ *
+ * Programmer: John Mainzer
+ * 9/10/17
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Pget_fapl_hdfs(hid_t fapl_id,
+ H5FD_hdfs_fapl_t *fa_out)
+{
+ const H5FD_hdfs_fapl_t *fa = NULL;
+ H5P_genplist_t *plist = NULL;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE2("e", "i*x", fapl_id, fa_out);
+
+#if HDFS_DEBUG
+ HDfprintf(stdout, "H5Pget_fapl_hdfs() called.\n");
+#endif
+
+ if (fa_out == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "fa_out is NULL")
+ }
+ plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS);
+ if (plist == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL,
+ "not a file access list")
+ }
+ if (H5FD_HDFS != H5P_peek_driver(plist)) {
+ HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL,
+ "incorrect VFL driver")
+ }
+
+ fa = (const H5FD_hdfs_fapl_t *)H5P_peek_driver_info(plist);
+ if (fa == NULL) {
+ HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL,
+ "bad VFL driver info")
+ }
+
+ /* Copy the hdfs fapl data out */
+ HDmemcpy(fa_out, fa, sizeof(H5FD_hdfs_fapl_t));
+
+done:
+ FUNC_LEAVE_API(ret_value)
+
+} /* H5Pget_fapl_hdfs() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_hdfs_fapl_get
+ *
+ * Purpose: Gets a file access property list which could be used to
+ * create an identical file.
+ *
+ * Return: Success: Ptr to new file access property list value.
+ *
+ * Failure: NULL
+ *
+ * Programmer: John Mainzer
+ * 9/8/17
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5FD_hdfs_fapl_get(H5FD_t *_file)
+{
+ H5FD_hdfs_t *file = (H5FD_hdfs_t*)_file;
+ H5FD_hdfs_fapl_t *fa = NULL;
+ void *ret_value = NULL;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ fa = (H5FD_hdfs_fapl_t *)H5MM_calloc(sizeof(H5FD_hdfs_fapl_t));
+ if (fa == NULL) {
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL,
+ "memory allocation failed")
+ }
+
+ /* Copy the fields of the structure */
+ HDmemcpy(fa, &(file->fa), sizeof(H5FD_hdfs_fapl_t));
+
+ ret_value = fa;
+
+done:
+ if (ret_value == NULL && fa != NULL) {
+ H5MM_xfree(fa); /* clean up on error */
+ }
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5FD_hdfs_fapl_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_hdfs_fapl_copy
+ *
+ * Purpose: Copies the hdfs-specific file access properties.
+ *
+ * Return: Success: Ptr to a new property list
+ *
+ * Failure: NULL
+ *
+ * Programmer: John Mainzer
+ * 9/8/17
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5FD_hdfs_fapl_copy(const void *_old_fa)
+{
+ const H5FD_hdfs_fapl_t *old_fa = (const H5FD_hdfs_fapl_t*)_old_fa;
+ H5FD_hdfs_fapl_t *new_fa = NULL;
+ void *ret_value = NULL;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ new_fa = (H5FD_hdfs_fapl_t *)H5MM_malloc(sizeof(H5FD_hdfs_fapl_t));
+ if (new_fa == NULL) {
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL,
+ "memory allocation failed")
+ }
+
+ HDmemcpy(new_fa, old_fa, sizeof(H5FD_hdfs_fapl_t));
+ ret_value = new_fa;
+
+done:
+ if (ret_value == NULL && new_fa != NULL) {
+ H5MM_xfree(new_fa); /* clean up on error */
+ }
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5FD_hdfs_fapl_copy() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_hdfs_fapl_free
+ *
+ * Purpose: Frees the hdfs-specific file access properties.
+ *
+ * Return: SUCCEED (cannot fail)
+ *
+ * Programmer: John Mainzer
+ * 9/8/17
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_hdfs_fapl_free(void *_fa)
+{
+ H5FD_hdfs_fapl_t *fa = (H5FD_hdfs_fapl_t*)_fa;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ HDassert(fa != NULL); /* sanity check */
+
+ H5MM_xfree(fa);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+
+} /* H5FD_hdfs_fapl_free() */
+
+#if HDFS_STATS
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: hdfs_reset_stats()
+ *
+ * Purpose:
+ *
+ * Reset the stats collection elements in this virtual file structure.
+ *
+ * Clears any set data in stats bins; initializes/zeroes values.
+ *
+ * Return:
+ *
+ * - SUCCESS: `SUCCEED`
+ * - FAILURE: `FAIL`
+ * - Occurs if the file is invalid somehow
+ *
+ * Programmer: Jacob Smith
+ * 2017-12-08
+ *
+ * Changes: None.
+ *
+ *----------------------------------------------------------------------------
+ */
+static herr_t
+hdfs_reset_stats(H5FD_hdfs_t *file)
+{
+ unsigned i = 0;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+#if HDFS_DEBUG
+ HDprintf("hdfs_reset_stats() called\n");
+#endif
+
+ if (file == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "file was null")
+ }
+
+ for (i = 0; i <= HDFS_STATS_BIN_COUNT; i++) {
+ file->raw[i].bytes = 0;
+ file->raw[i].count = 0;
+ file->raw[i].min = (unsigned long long)HDFS_STATS_STARTING_MIN;
+ file->raw[i].max = 0;
+
+ file->meta[i].bytes = 0;
+ file->meta[i].count = 0;
+ file->meta[i].min = (unsigned long long)HDFS_STATS_STARTING_MIN;
+ file->meta[i].max = 0;
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+
+} /* hdfs_reset_stats */
+#endif /* HDFS_STATS */
+
+
+/*-------------------------------------------------------------------------
+ *
+ * Function: H5FD_hdfs_open()
+ *
+ * Purpose:
+ *
+ * Create and/or opens a file as an HDF5 file.
+ *
+ * Any flag except H5F_ACC_RDONLY will cause an error.
+ *
+ * Return:
+ *
+ * Success: A pointer to a new file data structure.
+ * The public fields will be initialized by the caller, which is
+ * always H5FD_open().
+ *
+ * Failure: NULL
+ *
+ * Programmer: Jacob Smith
+ * 2017-11-02
+ *
+ * Changes: None.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifdef H5_HAVE_LIBHDFS
+static H5FD_t *
+H5FD_hdfs_open(
+ const char *path,
+ unsigned flags,
+ hid_t fapl_id,
+ haddr_t maxaddr)
+{
+ H5FD_t *ret_value = NULL;
+ H5FD_hdfs_t *file = NULL;
+ hdfs_t *handle = NULL;
+ H5FD_hdfs_fapl_t fa;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+#if HDFS_DEBUG
+ HDfprintf(stdout, "H5FD_hdfs_open() called.\n");
+#endif /* HDFS_DEBUG */
+
+ /* Sanity check on file offsets */
+ HDcompile_assert(sizeof(HDoff_t) >= sizeof(size_t));
+
+ /* Check arguments */
+ if (!path || !*path) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL,
+ "invalid file name")
+ }
+ if (0 == maxaddr || HADDR_UNDEF == maxaddr) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, NULL,
+ "bogus maxaddr")
+ }
+ if (ADDR_OVERFLOW(maxaddr)) {
+ HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, NULL,
+ "bogus maxaddr")
+ }
+ if (flags != H5F_ACC_RDONLY) {
+ HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, NULL,
+ "only Read-Only access allowed")
+ }
+ if (fapl_id == H5P_DEFAULT || fapl_id == H5P_FILE_ACCESS_DEFAULT) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL,
+ "fapl cannot be H5P_DEFAULT")
+ }
+ if (FAIL == H5Pget_fapl_hdfs(fapl_id, &fa)) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL,
+ "can't get property list")
+ }
+
+ handle = H5FD_hdfs_handle_open(
+ path,
+ fa.namenode_name,
+ fa.namenode_port,
+ fa.user_name,
+ fa.kerberos_ticket_cache,
+ fa.stream_buffer_size);
+
+ if (handle == NULL) {
+ HGOTO_ERROR(H5E_VFL, H5E_CANTOPENFILE, NULL,
+ "could not open")
+ }
+
+ HDassert(handle->magic == HDFS_HDFST_MAGIC);
+
+ /* create new file struct
+ */
+ file = H5FL_CALLOC(H5FD_hdfs_t);
+ if (file == NULL) {
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL,
+ "unable to allocate file struct")
+ }
+ file->hdfs_handle = handle;
+ HDmemcpy(&(file->fa), &fa, sizeof(H5FD_hdfs_fapl_t));
+
+#if HDFS_STATS
+ if (FAIL == hdfs_reset_stats(file)) {
+ HGOTO_ERROR(H5E_INTERNAL, H5E_UNINITIALIZED, NULL,
+ "unable to reset file statistics")
+ }
+#endif /* HDFS_STATS */
+
+ ret_value = (H5FD_t*)file;
+
+done:
+ if (ret_value == NULL) {
+ if (handle != NULL) {
+ if (FAIL == H5FD_hdfs_handle_close(handle)) {
+ HDONE_ERROR(H5E_VFL, H5E_CANTCLOSEFILE, NULL,
+ "unable to close HDFS file handle")
+ }
+ }
+ if (file != NULL) {
+ file = H5FL_FREE(H5FD_hdfs_t, file);
+ }
+ } /* end if null return value (error) */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5FD_hdfs_open() */
+
+#else /* H5_HAVE_LIBHDFS not defined */
+
+static H5FD_t *
+H5FD_hdfs_open(
+ const char H5_ATTR_UNUSED *path,
+ unsigned H5_ATTR_UNUSED flags,
+ hid_t H5_ATTR_UNUSED fapl_id,
+ haddr_t H5_ATTR_UNUSED maxaddr)
+{
+ H5FD_t *ret_value = NULL;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ HGOTO_ERROR(H5E_VFL, H5E_UNSUPPORTED, NULL,
+ "Illegal open of unsupported virtual file (hdfs)");
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5FD_hdfs_open() */
+
+#endif /* H5_HAVE_LIBHDFS */
+
+#if HDFS_STATS
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: hdfs_fprint_stats()
+ *
+ * Purpose:
+ *
+ * Tabulate and pretty-print statistics for this virtual file.
+ *
+ * Should be called upon file close.
+ *
+ * Shows number of reads and bytes read, broken down by
+ * "raw" (H5FD_MEM_DRAW)
+ * or "meta" (any other flag)
+ *
+ * Prints filename and listing of total number of reads and bytes read,
+ * both as a grand total and separate meta- and rawdata reads.
+ *
+ * If any reads were done, prints out two tables:
+ *
+ * 1. overview of raw- and metadata reads
+ * - min (smallest size read)
+ * - average of size read
+ * - k,M,G suffixes by powers of 1024 (2^10)
+ * - max (largest size read)
+ * 2. tabulation of "bins", sepraring reads into exponentially-larger
+ * ranges of size.
+ * - columns for number of reads, total bytes, and average size, with
+ * separate sub-colums for raw- and metadata reads.
+ * - each row represents one bin, identified by the top of its range
+ *
+ * Bin ranges can be modified with pound-defines at the top of this file.
+ *
+ * Bins without any reads in their bounds are not printed.
+ *
+ * An "overflow" bin is also present, to catch "big" reads.
+ *
+ * Output for all bins (and range ceiling and average size report)
+ * is divied by powers of 1024. By corollary, four digits before the decimal
+ * is valid.
+ *
+ * - 41080 bytes is represented by 40.177k, not 41.080k
+ * - 1004.831M represents approx. 1052642000 bytes
+ *
+ * Return:
+ *
+ * - SUCCESS: `SUCCEED`
+ * - FAILURE: `FAIL`
+ * - occurs if the file passed in is invalid
+ * - TODO: if stream is invalid? how can we check this?
+ *
+ * Programmer: Jacob Smith
+ *
+ * Changes: None.
+ *
+ *----------------------------------------------------------------------------
+ */
+static herr_t
+hdfs_fprint_stats(
+ FILE *stream,
+ const H5FD_hdfs_t *file)
+{
+ herr_t ret_value = SUCCEED;
+ parsed_url_t *purl = NULL;
+ unsigned i = 0;
+ unsigned long count_meta = 0;
+ unsigned long count_raw = 0;
+ double average_meta = 0.0;
+ double average_raw = 0.0;
+ unsigned long long min_meta = (unsigned long long)HDFS_STATS_STARTING_MIN;
+ unsigned long long min_raw = (unsigned long long)HDFS_STATS_STARTING_MIN;
+ unsigned long long max_meta = 0;
+ unsigned long long max_raw = 0;
+ unsigned long long bytes_raw = 0;
+ unsigned long long bytes_meta = 0;
+ double re_dub = 0.0; /* re-usable double variable */
+ unsigned suffix_i = 0;
+ const char suffixes[] = { ' ', 'K', 'M', 'G', 'T', 'P' };
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ if (stream == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "file stream cannot be null" )
+ }
+ if (file == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "file cannot be null")
+ }
+ if (file->hdfs_handle == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "hdfs handle cannot be null")
+ }
+ if (file->hdfs_handle->magic != HDFS_HDFST_MAGIC) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "hdfs handle has invalid magic")
+ }
+
+ /*******************
+ * AGGREGATE STATS *
+ *******************/
+
+ for (i = 0; i <= HDFS_STATS_BIN_COUNT; i++) {
+ const hdfs_statsbin *r = &file->raw[i];
+ const hdfs_statsbin *m = &file->meta[i];
+
+ if (m->min < min_meta) { min_meta = m->min; }
+ if (r->min < min_raw) { min_raw = r->min; }
+ if (m->max > max_meta) { max_meta = m->max; }
+ if (r->max > max_raw) { max_raw = r->max; }
+
+ count_raw += r->count;
+ count_meta += m->count;
+ bytes_raw += r->bytes;
+ bytes_meta += m->bytes;
+ }
+ if (count_raw > 0) {
+ average_raw = (double)bytes_raw / (double)count_raw;
+ }
+ if (count_meta > 0) {
+ average_meta = (double)bytes_meta / (double)count_meta;
+ }
+
+ /******************
+ * PRINT OVERVIEW *
+ ******************/
+
+ HDfprintf(stream, "TOTAL READS: %llu (%llu meta, %llu raw)\n",
+ count_raw + count_meta, count_meta, count_raw);
+ HDfprintf(stream, "TOTAL BYTES: %llu (%llu meta, %llu raw)\n",
+ bytes_raw + bytes_meta, bytes_meta, bytes_raw);
+
+ if (count_raw + count_meta == 0) {
+ goto done;
+ }
+
+ /*************************
+ * PRINT AGGREGATE STATS *
+ *************************/
+
+ HDfprintf(stream, "SIZES meta raw\n");
+ HDfprintf(stream, " min ");
+ if (count_meta == 0) {
+ HDfprintf(stream, " 0.000 ");
+ } else {
+ re_dub = (double)min_meta;
+ for (suffix_i = 0; re_dub >= 1024.0; suffix_i++) {
+ re_dub /= 1024.0;
+ }
+ HDassert(suffix_i < sizeof(suffixes));
+ HDfprintf(stream, "%8.3lf%c ", re_dub, suffixes[suffix_i]);
+ }
+
+ if (count_raw == 0) {
+ HDfprintf(stream, " 0.000 \n");
+ } else {
+ re_dub = (double)min_raw;
+ for (suffix_i = 0; re_dub >= 1024.0; suffix_i++) {
+ re_dub /= 1024.0;
+ }
+ HDassert(suffix_i < sizeof(suffixes));
+ HDfprintf(stream, "%8.3lf%c\n", re_dub, suffixes[suffix_i]);
+ }
+
+ HDfprintf(stream, " avg ");
+ re_dub = (double)average_meta;
+ for (suffix_i = 0; re_dub >= 1024.0; suffix_i++) {
+ re_dub /= 1024.0;
+ }
+ HDassert(suffix_i < sizeof(suffixes));
+ HDfprintf(stream, "%8.3lf%c ", re_dub, suffixes[suffix_i]);
+
+ re_dub = (double)average_raw;
+ for (suffix_i = 0; re_dub >= 1024.0; suffix_i++) {
+ re_dub /= 1024.0;
+ }
+ HDassert(suffix_i < sizeof(suffixes));
+ HDfprintf(stream, "%8.3lf%c\n", re_dub, suffixes[suffix_i]);
+
+ HDfprintf(stream, " max ");
+ re_dub = (double)max_meta;
+ for (suffix_i = 0; re_dub >= 1024.0; suffix_i++) {
+ re_dub /= 1024.0;
+ }
+ HDassert(suffix_i < sizeof(suffixes));
+ HDfprintf(stream, "%8.3lf%c ", re_dub, suffixes[suffix_i]);
+
+ re_dub = (double)max_raw;
+ for (suffix_i = 0; re_dub >= 1024.0; suffix_i++) {
+ re_dub /= 1024.0;
+ }
+ HDassert(suffix_i < sizeof(suffixes));
+ HDfprintf(stream, "%8.3lf%c\n", re_dub, suffixes[suffix_i]);
+
+ /******************************
+ * PRINT INDIVIDUAL BIN STATS *
+ ******************************/
+
+ HDfprintf(stream,
+ "BINS # of reads total bytes average size\n");
+ HDfprintf(stream,
+ " up-to meta raw meta raw meta raw\n");
+
+ for (i = 0; i <= HDFS_STATS_BIN_COUNT; i++) {
+ const hdfs_statsbin *m;
+ const hdfs_statsbin *r;
+ unsigned long long range_end = 0;
+ char bm_suffix = ' '; /* bytes-meta */
+ double bm_val = 0.0;
+ char br_suffix = ' '; /* bytes-raw */
+ double br_val = 0.0;
+ char am_suffix = ' '; /* average-meta */
+ double am_val = 0.0;
+ char ar_suffix = ' '; /* average-raw */
+ double ar_val = 0.0;
+
+ m = &file->meta[i];
+ r = &file->raw[i];
+ if (r->count == 0 && m->count == 0) {
+ continue;
+ }
+
+ range_end = hdfs_stats_boundaries[i];
+
+ if (i == HDFS_STATS_BIN_COUNT) {
+ range_end = hdfs_stats_boundaries[i-1];
+ HDfprintf(stream, ">");
+ } else {
+ HDfprintf(stream, " ");
+ }
+
+ bm_val = (double)m->bytes;
+ for (suffix_i = 0; bm_val >= 1024.0; suffix_i++) {
+ bm_val /= 1024.0;
+ }
+ HDassert(suffix_i < sizeof(suffixes));
+ bm_suffix = suffixes[suffix_i];
+
+ br_val = (double)r->bytes;
+ for (suffix_i = 0; br_val >= 1024.0; suffix_i++) {
+ br_val /= 1024.0;
+ }
+ HDassert(suffix_i < sizeof(suffixes));
+ br_suffix = suffixes[suffix_i];
+
+ if (m->count > 0) {
+ am_val = (double)(m->bytes) / (double)(m->count);
+ }
+ for (suffix_i = 0; am_val >= 1024.0; suffix_i++) {
+ am_val /= 1024.0;
+ }
+ HDassert(suffix_i < sizeof(suffixes));
+ am_suffix = suffixes[suffix_i];
+
+ if (r->count > 0) {
+ ar_val = (double)(r->bytes) / (double)(r->count);
+ }
+ for (suffix_i = 0; ar_val >= 1024.0; suffix_i++) {
+ ar_val /= 1024.0;
+ }
+ HDassert(suffix_i < sizeof(suffixes));
+ ar_suffix = suffixes[suffix_i];
+
+ re_dub = (double)range_end;
+ for (suffix_i = 0; re_dub >= 1024.0; suffix_i++) {
+ re_dub /= 1024.0;
+ }
+ HDassert(suffix_i < sizeof(suffixes));
+
+ HDfprintf(
+ stream,
+ " %8.3f%c %7d %7d %8.3f%c %8.3f%c %8.3f%c %8.3f%c\n",
+ re_dub, suffixes[suffix_i], /* bin ceiling */
+ m->count, /* metadata reads */
+ r->count, /* rawdata reads */
+ bm_val, bm_suffix, /* metadata bytes */
+ br_val, br_suffix, /* rawdata bytes */
+ am_val, am_suffix, /* metadata average */
+ ar_val, ar_suffix); /* rawdata average */
+ fflush(stream);
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* hdfs_fprint_stats */
+#endif /* HDFS_STATS */
+
+
+/*-------------------------------------------------------------------------
+ *
+ * Function: H5FD_hdfs_close()
+ *
+ * Purpose:
+ *
+ * Close an HDF5 file.
+ *
+ * Return:
+ *
+ * SUCCEED/FAIL
+ *
+ * Programmer: Jacob Smith
+ * 2017-11-02
+ *
+ * Changes: None.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifdef H5_HAVE_LIBHDFS
+
+static herr_t
+H5FD_hdfs_close(H5FD_t *_file)
+{
+ herr_t ret_value = SUCCEED;
+ H5FD_hdfs_t *file = (H5FD_hdfs_t *)_file;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+#if HDFS_DEBUG
+ HDfprintf(stdout, "H5FD_hdfs_close() called.\n");
+#endif
+
+ /* Sanity checks
+ */
+ HDassert(file != NULL);
+ HDassert(file->hdfs_handle != NULL);
+ HDassert(file->hdfs_handle->magic == HDFS_HDFST_MAGIC);
+
+ /* Close the underlying request handle
+ */
+ if (file->hdfs_handle != NULL) {
+ if (FAIL == H5FD_hdfs_handle_close(file->hdfs_handle)) {
+ HGOTO_ERROR(H5E_VFL, H5E_CANTCLOSEFILE, FAIL,
+ "unable to close HDFS file handle")
+ }
+ }
+
+#if HDFS_STATS
+ /* TODO: mechanism to re-target stats printout */
+ if (FAIL == hdfs_fprint_stats(stdout, file)) {
+ HGOTO_ERROR(H5E_INTERNAL, H5E_ERROR, FAIL,
+ "problem while writing file statistics")
+ }
+#endif /* HDFS_STATS */
+
+ /* Release the file info
+ */
+ file = H5FL_FREE(H5FD_hdfs_t, file);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_hdfs_close() */
+
+#else /* H5_HAVE_LIBHDFS not defined */
+
+static herr_t
+H5FD_hdfs_close(H5FD_t H5_ATTR_UNUSED *_file)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ HGOTO_ERROR(H5E_VFL, H5E_CANTCLOSEFILE, FAIL,
+ "Illegal close of unsupported Virtual File (hdfs)")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_hdfs_close() */
+
+#endif /* H5_HAVE_LIBHDFS */
+
+
+/*-------------------------------------------------------------------------
+ *
+ * Function: H5FD_hdfs_cmp()
+ *
+ * Purpose:
+ *
+ * Compares two files using this driver by their HDFS-provided file info,
+ * field-by-field.
+ *
+ * Return:
+ * + Equivalent: 0
+ * + Not Equivalent: -1
+ *
+ * Programmer: Gerd Herber
+ * May 2018
+ *
+ * Changes:
+ *
+ * + Replace `if (ret_value == 0)` chain with `HGOTO_DONE` jumps.
+ * Jacob Smith 17 May 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifdef H5_HAVE_LIBHDFS
+
+static int
+H5FD_hdfs_cmp(
+ const H5FD_t *_f1,
+ const H5FD_t *_f2)
+{
+ int ret_value = 0;
+ const H5FD_hdfs_t *f1 = (const H5FD_hdfs_t *)_f1;
+ const H5FD_hdfs_t *f2 = (const H5FD_hdfs_t *)_f2;
+ hdfsFileInfo *finfo1 = NULL;
+ hdfsFileInfo *finfo2 = NULL;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+#if HDFS_DEBUG
+ HDfprintf(stdout, "H5FD_hdfs_cmp() called.\n");
+#endif /* HDFS_DEBUG */
+
+ HDassert(f1->hdfs_handle != NULL);
+ HDassert(f2->hdfs_handle != NULL);
+ HDassert(f1->hdfs_handle->magic == HDFS_HDFST_MAGIC);
+ HDassert(f2->hdfs_handle->magic == HDFS_HDFST_MAGIC);
+
+ finfo1 = f1->hdfs_handle->fileinfo;
+ finfo2 = f2->hdfs_handle->fileinfo;
+ HDassert(finfo1 != NULL);
+ HDassert(finfo2 != NULL);
+
+ if (finfo1->mKind != finfo2->mKind) { HGOTO_DONE(-1); }
+ if (finfo1->mName != finfo2->mName) { HGOTO_DONE(-1); }
+ if (finfo1->mLastMod != finfo2->mLastMod) { HGOTO_DONE(-1); }
+ if (finfo1->mSize != finfo2->mSize) { HGOTO_DONE(-1); }
+ if (finfo1->mReplication != finfo2->mReplication) { HGOTO_DONE(-1); }
+ if (finfo1->mBlockSize != finfo2->mBlockSize) { HGOTO_DONE(-1); }
+ if (strcmp(finfo1->mOwner, finfo2->mOwner)) { HGOTO_DONE(-1); }
+ if (strcmp(finfo1->mGroup, finfo2->mGroup)) { HGOTO_DONE(-1); }
+ if (finfo1->mPermissions != finfo2->mPermissions) { HGOTO_DONE(-1); }
+ if (finfo1->mLastAccess != finfo2->mLastAccess) { HGOTO_DONE(-1); }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5FD_hdfs_cmp() */
+
+#else /* H5_HAVE_LIBHDFS not defined */
+
+static int
+H5FD_hdfs_cmp(
+ const H5FD_t H5_ATTR_UNUSED *_f1,
+ const H5FD_t H5_ATTR_UNUSED *_f2)
+{
+ int ret_value = 0;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5FD_hdfs_cmp() */
+
+#endif /* H5_HAVE_LIBHDFS */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_hdfs_query
+ *
+ * Purpose: Set the flags that this VFL driver is capable of supporting.
+ * (listed in H5FDpublic.h)
+ *
+ * Note that since the HDFS VFD is read only, most flags
+ * are irrelevant.
+ *
+ * The term "set" is highly misleading...
+ * stores/copies the supported flags in the out-pointer `flags`.
+ *
+ * Return: SUCCEED (Can't fail)
+ *
+ * Programmer: John Mainzer
+ * 9/11/17
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_hdfs_query(
+ const H5FD_t H5_ATTR_UNUSED *_file,
+ unsigned long *flags) /* out variable */
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+#if HDFS_DEBUG
+ HDfprintf(stdout, "H5FD_hdfs_query() called.\n");
+#endif
+
+ if (flags) {
+ *flags = 0;
+ *flags |= H5FD_FEAT_DATA_SIEVE;
+ }
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5FD_hdfs_query() */
+
+
+/*-------------------------------------------------------------------------
+ *
+ * Function: H5FD_hdfs_get_eoa()
+ *
+ * Purpose:
+ *
+ * Gets the end-of-address marker for the file. The EOA marker
+ * is the first address past the last byte allocated in the
+ * format address space.
+ *
+ * Return:
+ *
+ * The end-of-address marker.
+ *
+ * Programmer: Jacob Smith
+ * 2017-11-02
+ *
+ * Changes: None.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifdef H5_HAVE_LIBHDFS
+
+static haddr_t
+H5FD_hdfs_get_eoa(
+ const H5FD_t *_file,
+ H5FD_mem_t H5_ATTR_UNUSED type)
+{
+ const H5FD_hdfs_t *file = (const H5FD_hdfs_t *)_file;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+#if HDFS_DEBUG
+ HDfprintf(stdout, "H5FD_hdfs_get_eoa() called.\n");
+#endif
+
+ FUNC_LEAVE_NOAPI(file->eoa)
+} /* end H5FD_hdfs_get_eoa() */
+
+#else /* H5_HAVE_LIBHDFS not defined */
+
+static haddr_t
+H5FD_hdfs_get_eoa(
+ const H5FD_t H5_ATTR_UNUSED *_file,
+ H5FD_mem_t H5_ATTR_UNUSED type)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+#if HDFS_DEBUG
+ HDfprintf(stdout, "H5FD_hdfs_get_eoa() called.\n");
+#endif
+
+ FUNC_LEAVE_NOAPI(0)
+} /* end H5FD_hdfs_get_eoa() */
+
+#endif /* H5_HAVE_LIBHDFS */
+
+
+/*-------------------------------------------------------------------------
+ *
+ * Function: H5FD_hdfs_set_eoa()
+ *
+ * Purpose:
+ *
+ * Set the end-of-address marker for the file.
+ *
+ * Return:
+ *
+ * SUCCEED (can't fail)
+ *
+ * Programmer: Jacob Smith
+ * 2017-11-03
+ *
+ * Changes: None.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifdef H5_HAVE_LIBHDFS
+
+static herr_t
+H5FD_hdfs_set_eoa(
+ H5FD_t *_file,
+ H5FD_mem_t H5_ATTR_UNUSED type,
+ haddr_t addr)
+{
+ H5FD_hdfs_t *file = (H5FD_hdfs_t *)_file;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+#if HDFS_DEBUG
+ HDfprintf(stdout, "H5FD_hdfs_set_eoa() called.\n");
+#endif
+
+ file->eoa = addr;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5FD_hdfs_set_eoa() */
+
+#else /* H5_HAVE_LIBHDFS not defined */
+
+static herr_t
+H5FD_hdfs_set_eoa(
+ H5FD_t H5_ATTR_UNUSED *_file,
+ H5FD_mem_t H5_ATTR_UNUSED type,
+ haddr_t H5_ATTR_UNUSED addr)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+#if HDFS_DEBUG
+ HDfprintf(stdout, "H5FD_hdfs_set_eoa() called.\n");
+#endif
+
+ FUNC_LEAVE_NOAPI(FAIL)
+} /* H5FD_hdfs_set_eoa() */
+
+#endif /* H5_HAVE_LIBHDFS */
+
+
+/*-------------------------------------------------------------------------
+ *
+ * Function: H5FD_hdfs_get_eof()
+ *
+ * Purpose:
+ *
+ * Returns the end-of-file marker.
+ *
+ * Return:
+ *
+ * EOF: the first address past the end of the "file", either the
+ * filesystem file or the HDF5 file.
+ *
+ * Programmer: Jacob Smith
+ * 2017-11-02
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifdef H5_HAVE_LIBHDFS
+
+static haddr_t
+H5FD_hdfs_get_eof(
+ const H5FD_t *_file,
+ H5FD_mem_t H5_ATTR_UNUSED type)
+{
+ const H5FD_hdfs_t *file = (const H5FD_hdfs_t *)_file;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+#if HDFS_DEBUG
+ HDfprintf(stdout, "H5FD_hdfs_get_eof() called.\n");
+#endif
+
+ HDassert(file->hdfs_handle != NULL);
+ HDassert(file->hdfs_handle->magic == HDFS_HDFST_MAGIC);
+
+ FUNC_LEAVE_NOAPI((size_t) file->hdfs_handle->fileinfo->mSize)
+} /* end H5FD_hdfs_get_eof() */
+
+#else /* H5_HAVE_LIBHDFS not defined */
+
+static haddr_t
+H5FD_hdfs_get_eof(
+ const H5FD_t H5_ATTR_UNUSED *_file,
+ H5FD_mem_t H5_ATTR_UNUSED type)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+#if HDFS_DEBUG
+ HDfprintf(stdout, "H5FD_hdfs_get_eof() called.\n");
+#endif
+
+ FUNC_LEAVE_NOAPI((size_t)0)
+} /* end H5FD_hdfs_get_eof() */
+
+#endif /* H5_HAVE_LIBHDFS */
+
+
+/*-------------------------------------------------------------------------
+ *
+ * Function: H5FD_hdfs_get_handle()
+ *
+ * Purpose:
+ *
+ * Returns the HDFS handle (hdfs_t) of hdfs file driver.
+ *
+ * Returns:
+ *
+ * SUCCEED/FAIL
+ *
+ * Programmer: Jacob Smith
+ * 2017-11-02
+ *
+ * Changes: None.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifdef H5_HAVE_LIBHDFS
+
+static herr_t
+H5FD_hdfs_get_handle(
+ H5FD_t *_file,
+ hid_t H5_ATTR_UNUSED fapl,
+ void **file_handle)
+{
+ herr_t ret_value = SUCCEED;
+ H5FD_hdfs_t *file = (H5FD_hdfs_t *)_file;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+#if HDFS_DEBUG
+ HDfprintf(stdout, "H5FD_hdfs_get_handle() called.\n");
+#endif /* HDFS_DEBUG */
+
+ if (!file_handle) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "file handle not valid")
+ }
+
+ *file_handle = file->hdfs_handle;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_hdfs_get_handle() */
+
+#else /* H5_HAVE_LIBHDFS not defined */
+
+static herr_t
+H5FD_hdfs_get_handle(
+ H5FD_t H5_ATTR_UNUSED *_file,
+ hid_t H5_ATTR_UNUSED fapl,
+ void H5_ATTR_UNUSED **file_handle)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+#if HDFS_DEBUG
+ HDfprintf(stdout, "H5FD_hdfs_get_handle() called.\n");
+#endif /* HDFS_DEBUG */
+
+ HGOTO_ERROR(H5E_VFL, H5E_UNSUPPORTED, FAIL,
+ "Illegal get-handle of unsupported virtual file (hdfs)");
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_hdfs_get_handle() */
+
+#endif /* H5_HAVE_LIBHDFS */
+
+
+/*-------------------------------------------------------------------------
+ *
+ * Function: H5FD_hdfs_read()
+ *
+ * Purpose:
+ *
+ * Reads SIZE bytes of data from FILE beginning at address ADDR
+ * into buffer BUF according to data transfer properties in DXPL_ID.
+ *
+ * Return:
+ *
+ * Success: `SUCCEED`
+ * - Result is stored in caller-supplied buffer BUF.
+ * Failure: `FAIL`
+ * - Unable to complete read.
+ * - Contents of buffer `buf` are undefined.
+ *
+ * Programmer: Jacob Smith
+ * 2017-11-??
+ *
+ * Changes: None.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifdef H5_HAVE_LIBHDFS
+
+static herr_t
+H5FD_hdfs_read(
+ H5FD_t *_file,
+ H5FD_mem_t H5_ATTR_UNUSED type,
+ hid_t H5_ATTR_UNUSED dxpl_id,
+ haddr_t addr, /* start offset */
+ size_t size, /* length of read */
+ void *buf) /* out */
+{
+ herr_t ret_value = SUCCEED;
+ H5FD_hdfs_t *file = (H5FD_hdfs_t *)_file;
+ size_t filesize = 0;
+#if HDFS_STATS
+ /* working variables for storing stats */
+ hdfs_statsbin *bin = NULL;
+ unsigned bin_i = 0;
+#endif /* HDFS_STATS */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+#if HDFS_DEBUG
+ HDfprintf(stdout, "H5FD_hdfs_read() called.\n");
+#endif /* HDFS_DEBUG */
+
+ HDassert(file != NULL);
+ HDassert(file->hdfs_handle != NULL);
+ HDassert(file->hdfs_handle->magic == HDFS_HDFST_MAGIC);
+ HDassert(buf != NULL);
+
+ filesize = (size_t) file->hdfs_handle->fileinfo->mSize;
+
+ if ((addr > filesize) || ((addr + size) > filesize)) {
+ HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, FAIL,
+ "range exceeds file address")
+ }
+
+ if (FAIL == hdfsPread(
+ file->hdfs_handle->filesystem,
+ file->hdfs_handle->file,
+ (tOffset)addr,
+ buf,
+ (tSize)size))
+ {
+ HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL,
+ "unable to execute read")
+ }
+
+#if HDFS_STATS
+
+ /* Find which "bin" this read fits in. Can be "overflow" bin.
+ */
+ for (bin_i = 0; bin_i < HDFS_STATS_BIN_COUNT; bin_i++) {
+ if ((unsigned long long)size < hdfs_stats_boundaries[bin_i]) {
+ break;
+ }
+ }
+ bin = (type == H5FD_MEM_DRAW)
+ ? &file->raw[bin_i]
+ : &file->meta[bin_i];
+
+ /* Store collected stats in appropriate bin
+ */
+ if (bin->count == 0) {
+ bin->min = size;
+ bin->max = size;
+ }
+ else {
+ if (size < bin->min) { bin->min = size; }
+ if (size > bin->max) { bin->max = size; }
+ }
+ bin->count++;
+ bin->bytes += (unsigned long long)size;
+
+#endif /* HDFS_STATS */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_hdfs_read() */
+
+#else /* H5_HAVE_LIBHDFS not defined */
+
+static herr_t
+H5FD_hdfs_read(
+ H5FD_t H5_ATTR_UNUSED *_file,
+ H5FD_mem_t H5_ATTR_UNUSED type,
+ hid_t H5_ATTR_UNUSED dxpl_id,
+ haddr_t H5_ATTR_UNUSED addr,
+ size_t H5_ATTR_UNUSED size,
+ void H5_ATTR_UNUSED *buf)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+#if HDFS_DEBUG
+ HDfprintf(stdout, "H5FD_hdfs_read() called.\n");
+#endif /* HDFS_DEBUG */
+
+ HGOTO_ERROR(H5E_VFL, H5E_UNSUPPORTED, FAIL,
+ "Illegal get-handle of unsupported virtual file (hdfs)");
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_hdfs_read() */
+
+#endif /* H5_HAVE_LIBHDFS */
+
+
+/*-------------------------------------------------------------------------
+ *
+ * Function: H5FD_hdfs_write()
+ *
+ * Purpose:
+ *
+ * Write bytes to file.
+ * UNSUPPORTED IN READ-ONLY HDFS VFD.
+ *
+ * Return:
+ *
+ * FAIL (Not possible with Read-Only S3 file.)
+ *
+ * Programmer: Jacob Smith
+ * 2017-10-23
+ *
+ * Changes: None.
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_hdfs_write(
+ H5FD_t H5_ATTR_UNUSED *_file,
+ H5FD_mem_t H5_ATTR_UNUSED type,
+ hid_t H5_ATTR_UNUSED dxpl_id,
+ haddr_t H5_ATTR_UNUSED addr,
+ size_t H5_ATTR_UNUSED size,
+ const void H5_ATTR_UNUSED *buf)
+{
+ herr_t ret_value = FAIL;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+#if HDFS_DEBUG
+ HDfprintf(stdout, "H5FD_hdfs_write() called.\n");
+#endif
+
+ HGOTO_ERROR(H5E_VFL, H5E_UNSUPPORTED, FAIL,
+ "cannot write to read-only file.")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5FD_hdfs_write() */
+
+
+/*-------------------------------------------------------------------------
+ *
+ * Function: H5FD_hdfs_truncate()
+ *
+ * Purpose:
+ *
+ * Makes sure that the true file size is the same (or larger)
+ * than the end-of-address.
+ *
+ * NOT POSSIBLE ON READ-ONLY S3 FILES.
+ *
+ * Return:
+ *
+ * FAIL (Not possible on Read-Only S3 files.)
+ *
+ * Programmer: Jacob Smith
+ * 2017-10-23
+ *
+ * Changes: None.
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_hdfs_truncate(
+ H5FD_t H5_ATTR_UNUSED *_file,
+ hid_t H5_ATTR_UNUSED dxpl_id,
+ hbool_t H5_ATTR_UNUSED closing)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+#if HDFS_DEBUG
+ HDfprintf(stdout, "H5FD_hdfs_truncate() called.\n");
+#endif
+
+ HGOTO_ERROR(H5E_VFL, H5E_UNSUPPORTED, FAIL,
+ "cannot truncate read-only file.")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_hdfs_truncate() */
+
+
+/*-------------------------------------------------------------------------
+ *
+ * Function: H5FD_hdfs_lock()
+ *
+ * Purpose:
+ *
+ * Place an advisory lock on a file.
+ * No effect on Read-Only S3 file.
+ *
+ * Suggestion: remove lock/unlock from class
+ * > would result in error at H5FD_[un]lock() (H5FD.c)
+ *
+ * Return:
+ *
+ * SUCCEED (No-op always succeeds)
+ *
+ * Programmer: Jacob Smith
+ * 2017-11-03
+ *
+ * Changes: None.
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_hdfs_lock(
+ H5FD_t H5_ATTR_UNUSED *_file,
+ hbool_t H5_ATTR_UNUSED rw)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5FD_hdfs_lock() */
+
+
+/*-------------------------------------------------------------------------
+ *
+ * Function: H5FD_hdfs_unlock()
+ *
+ * Purpose:
+ *
+ * Remove the existing lock on the file.
+ * No effect on Read-Only S3 file.
+ *
+ * Return:
+ *
+ * SUCCEED (No-op always succeeds)
+ *
+ * Programmer: Jacob Smith
+ * 2017-11-03
+ *
+ * Changes: None.
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_hdfs_unlock(H5FD_t H5_ATTR_UNUSED *_file)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5FD_hdfs_unlock() */
+
diff --git a/src/H5FDhdfs.h b/src/H5FDhdfs.h
new file mode 100644
index 0000000..3d4128d
--- /dev/null
+++ b/src/H5FDhdfs.h
@@ -0,0 +1,122 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Read-Only HDFS Virtual File Driver (VFD) *
+ * Copyright (c) 2018, The HDF Group. *
+ * *
+ * All rights reserved. *
+ * *
+ * NOTICE: *
+ * All information contained herein is, and remains, the property of The HDF *
+ * Group. The intellectual and technical concepts contained herein are *
+ * proprietary to The HDF Group. Dissemination of this information or *
+ * reproduction of this material is strictly forbidden unless prior written *
+ * permission is obtained from The HDF Group. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Programmer: Jacob Smith
+ * 2018-04-23
+ *
+ * Purpose: The public header file for the hdfs driver.
+ */
+
+#ifndef H5FDhdfs_H
+#define H5FDhdfs_H
+
+#define H5FD_HDFS (H5FD_hdfs_init())
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/****************************************************************************
+ *
+ * Structure: H5FD_hdfs_fapl_t
+ *
+ * Purpose:
+ *
+ * H5FD_hdfs_fapl_t is a public structure that is used to pass
+ * configuration information to the appropriate HDFS VFD via the FAPL.
+ * A pointer to an instance of this structure is a parameter to
+ * H5Pset_fapl_hdfs() and H5Pget_fapl_hdfs().
+ *
+ *
+ *
+ * `version` (int32_t)
+ *
+ * Version number of the `H5FD_hdfs_fapl_t` structure. Any instance passed
+ * to the above calls must have a recognized version number, or an error
+ * will be flagged.
+ *
+ * This field should be set to `H5FD__CURR_HDFS_FAPL_T_VERSION`.
+ *
+ * `namenode_name` (const char[])
+ *
+ * Name of "Name Node" to access as the HDFS server.
+ *
+ * Must not be longer than `H5FD__HDFS_NODE_NAME_SPACE`.
+ *
+ * TBD: Can be NULL.
+ *
+ * `namenode_port` (int32_t) TBD
+ *
+ * Port number to use to connect with Name Node.
+ *
+ * TBD: If 0, uses a default port.
+ *
+ * `kerberos_ticket_cache` (const char[])
+ *
+ * Path to the location of the Kerberos authentication cache.
+ *
+ * Must not be longer than `H5FD__HDFS_KERB_CACHE_PATH_SPACE`.
+ *
+ * TBD: Can be NULL.
+ *
+ * `user_name` (const char[])
+ *
+ * Username to use when accessing file.
+ *
+ * Must not be longer than `H5FD__HDFS_USER_NAME_SPACE`.
+ *
+ * TBD: Can be NULL.
+ *
+ * `stream_buffer_size` (int32_t)
+ *
+ * Size (in bytes) of the file read stream buffer.
+ *
+ * TBD: If -1, relies on a default value.
+ *
+ *
+ *
+ * Programmer: Jacob Smith
+ * 2018-04-23
+ *
+ * Changes: None
+ *
+ ****************************************************************************/
+
+#define H5FD__CURR_HDFS_FAPL_T_VERSION 1
+
+#define H5FD__HDFS_NODE_NAME_SPACE 128
+#define H5FD__HDFS_USER_NAME_SPACE 128
+#define H5FD__HDFS_KERB_CACHE_PATH_SPACE 128
+
+typedef struct H5FD_hdfs_fapl_t {
+ int32_t version;
+ char namenode_name[H5FD__HDFS_NODE_NAME_SPACE + 1];
+ int32_t namenode_port;
+ char user_name[H5FD__HDFS_USER_NAME_SPACE + 1];
+ char kerberos_ticket_cache[H5FD__HDFS_KERB_CACHE_PATH_SPACE + 1];
+ int32_t stream_buffer_size;
+} H5FD_hdfs_fapl_t;
+
+H5_DLL hid_t H5FD_hdfs_init(void);
+H5_DLL herr_t H5Pget_fapl_hdfs(hid_t fapl_id, H5FD_hdfs_fapl_t *fa_out);
+H5_DLL herr_t H5Pset_fapl_hdfs(hid_t fapl_id, H5FD_hdfs_fapl_t *fa);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ifndef H5FDhdfs_H */
+
+
diff --git a/src/H5FDlog.c b/src/H5FDlog.c
index 7c2297a..ac5667f 100644
--- a/src/H5FDlog.c
+++ b/src/H5FDlog.c
@@ -117,7 +117,7 @@ typedef struct H5FD_log_t {
* Whether to eliminate the family driver info and convert this file to
* a single file
*/
- hbool_t fam_to_sec2;
+ hbool_t fam_to_single;
/* Fields for tracking I/O operations */
unsigned char *nread; /* Number of reads from a file location */
@@ -252,8 +252,8 @@ done:
* Purpose: Initialize this driver by registering the driver with the
* library.
*
- * Return: Success: The driver ID for the log driver.
- * Failure: Negative.
+ * Return: Success: The driver ID for the log driver
+ * Failure: H5I_INVALID_HID
*
* Programmer: Robb Matzke
* Thursday, July 29, 1999
@@ -265,7 +265,7 @@ H5FD_log_init(void)
{
hid_t ret_value = H5I_INVALID_HID; /* Return value */
- FUNC_ENTER_NOAPI(FAIL)
+ FUNC_ENTER_NOAPI(H5I_INVALID_HID)
if(H5I_VFL != H5I_get_type(H5FD_LOG_g))
H5FD_LOG_g = H5FD_register(&H5FD_log_g, sizeof(H5FD_class_t), FALSE);
@@ -329,16 +329,24 @@ H5Pset_fapl_log(hid_t fapl_id, const char *logfile, unsigned long long flags, si
if(NULL == (plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list")
- /* This shallow copy is correct! The string will be properly
- * copied deep down in the H5P code.
+ HDmemset(&fa, 0, sizeof(H5FD_log_fapl_t));
+
+ /* Duplicate the log file string
+ * A little wasteful, since this string will just be copied later, but
+ * passing it in as a pointer sets off a chain of impossible-to-resolve
+ * const cast warnings.
*/
- fa.logfile = (char *)logfile;
+ if(logfile != NULL && NULL == (fa.logfile = H5MM_xstrdup(logfile)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to copy log file name")
fa.flags = flags;
fa.buf_size = buf_size;
ret_value = H5P_set_driver(plist, H5FD_LOG, &fa);
done:
+ if(fa.logfile)
+ H5MM_free(fa.logfile);
+
FUNC_LEAVE_API(ret_value)
} /* end H5Pset_fapl_log() */
@@ -403,7 +411,7 @@ H5FD_log_fapl_copy(const void *_old_fa)
HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, NULL, "unable to allocate log file FAPL")
/* Copy the general information */
- HDmemcpy(new_fa, old_fa, sizeof(H5FD_log_fapl_t));
+ H5MM_memcpy(new_fa, old_fa, sizeof(H5FD_log_fapl_t));
/* Deep copy the log file name */
if(old_fa->logfile != NULL)
@@ -635,13 +643,13 @@ H5FD_log_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr)
/* Check for non-default FAPL */
if(H5P_FILE_ACCESS_DEFAULT != fapl_id) {
/* This step is for h5repart tool only. If user wants to change file driver from
- * family to sec2 while using h5repart, this private property should be set so that
- * in the later step, the library can ignore the family driver information saved
- * in the superblock.
+ * family to one that uses single files (sec2, etc.) while using h5repart, this
+ * private property should be set so that in the later step, the library can ignore
+ * the family driver information saved in the superblock.
*/
- if(H5P_exist_plist(plist, H5F_ACS_FAMILY_TO_SEC2_NAME) > 0)
- if(H5P_get(plist, H5F_ACS_FAMILY_TO_SEC2_NAME, &file->fam_to_sec2) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTGET, NULL, "can't get property of changing family to sec2")
+ if(H5P_exist_plist(plist, H5F_ACS_FAMILY_TO_SINGLE_NAME) > 0)
+ if(H5P_get(plist, H5F_ACS_FAMILY_TO_SINGLE_NAME, &file->fam_to_single) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTGET, NULL, "can't get property of changing family to single")
} /* end if */
/* Set return value */
@@ -900,7 +908,7 @@ H5FD_log_query(const H5FD_t *_file, unsigned long *flags /* out */)
*flags |= H5FD_FEAT_DEFAULT_VFD_COMPATIBLE; /* VFD creates a file which can be opened with the default VFD */
/* Check for flags that are set by h5repart */
- if(file && file->fam_to_sec2)
+ if(file && file->fam_to_single)
*flags |= H5FD_FEAT_IGNORE_DRVRINFO; /* Ignore the driver info when file is opened (which eliminates it) */
} /* end if */
@@ -1189,7 +1197,8 @@ H5FD_log_read(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id, hadd
} /* end if */
} /* end if */
- /* Seek to the correct location */
+#ifndef H5_HAVE_PREADWRITE
+ /* Seek to the correct location (if we don't have pread) */
if(addr != file->pos || OP_READ != file->op) {
#ifdef H5_HAVE_GETTIMEOFDAY
if(file->fa.flags & H5FD_LOG_TIME_SEEK)
@@ -1232,6 +1241,7 @@ H5FD_log_read(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id, hadd
#endif /* H5_HAVE_GETTIMEOFDAY */
} /* end if */
} /* end if */
+#endif /* H5_HAVE_PREADWRITE */
/*
* Read data, being careful of interrupted system calls, partial results,
@@ -1245,6 +1255,7 @@ H5FD_log_read(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id, hadd
h5_posix_io_t bytes_in = 0; /* # of bytes to read */
h5_posix_io_ret_t bytes_read = -1; /* # of bytes actually read */
+ HDoff_t offset = (HDoff_t)addr;
/* Trying to read more bytes than the return type can handle is
* undefined behavior in POSIX.
@@ -1255,18 +1266,24 @@ H5FD_log_read(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id, hadd
bytes_in = (h5_posix_io_t)size;
do {
+#ifdef H5_HAVE_PREADWRITE
+ bytes_read = HDpread(file->fd, buf, bytes_in, offset);
+ offset += bytes_read;
+#else
bytes_read = HDread(file->fd, buf, bytes_in);
+#endif /* H5_HAVE_PREADWRITE */
} while(-1 == bytes_read && EINTR == errno);
if(-1 == bytes_read) { /* error */
int myerrno = errno;
time_t mytime = HDtime(NULL);
- HDoff_t myoffset = HDlseek(file->fd, (HDoff_t)0, SEEK_CUR);
+
+ offset = HDlseek(file->fd, (HDoff_t)0, SEEK_CUR);
if(file->fa.flags & H5FD_LOG_LOC_READ)
HDfprintf(file->logfp, "Error! Reading: %10a-%10a (%10Zu bytes)\n", orig_addr, (orig_addr + orig_size) - 1, orig_size);
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file read failed: time = %s, filename = '%s', file descriptor = %d, errno = %d, error message = '%s', buf = %p, total read size = %llu, bytes this sub-read = %llu, bytes actually read = %llu, offset = %llu", HDctime(&mytime), file->filename, file->fd, myerrno, HDstrerror(myerrno), buf, (unsigned long long)size, (unsigned long long)bytes_in, (unsigned long long)bytes_read, (unsigned long long)myoffset);
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file read failed: time = %s, filename = '%s', file descriptor = %d, errno = %d, error message = '%s', buf = %p, total read size = %llu, bytes this sub-read = %llu, bytes actually read = %llu, offset = %llu", HDctime(&mytime), file->filename, file->fd, myerrno, HDstrerror(myerrno), buf, (unsigned long long)size, (unsigned long long)bytes_in, (unsigned long long)bytes_read, (unsigned long long)offset);
} /* end if */
if(0 == bytes_read) {
@@ -1396,7 +1413,8 @@ H5FD_log_write(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id, had
file->nwrite[tmp_addr++]++;
} /* end if */
- /* Seek to the correct location */
+#ifndef H5_HAVE_PREADWRITE
+ /* Seek to the correct location (if we don't have pwrite) */
if(addr != file->pos || OP_WRITE != file->op) {
#ifdef H5_HAVE_GETTIMEOFDAY
if(file->fa.flags & H5FD_LOG_TIME_SEEK)
@@ -1439,6 +1457,7 @@ H5FD_log_write(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id, had
#endif /* H5_HAVE_GETTIMEOFDAY */
} /* end if */
} /* end if */
+#endif /* H5_HAVE_PREADWRITE */
/*
* Write the data, being careful of interrupted system calls and partial
@@ -1452,6 +1471,7 @@ H5FD_log_write(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id, had
h5_posix_io_t bytes_in = 0; /* # of bytes to write */
h5_posix_io_ret_t bytes_wrote = -1; /* # of bytes written */
+ HDoff_t offset = (HDoff_t)addr;
/* Trying to write more bytes than the return type can handle is
* undefined behavior in POSIX.
@@ -1462,18 +1482,24 @@ H5FD_log_write(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id, had
bytes_in = (h5_posix_io_t)size;
do {
+#ifdef H5_HAVE_PREADWRITE
+ bytes_wrote = HDpwrite(file->fd, buf, bytes_in, offset);
+ offset += bytes_wrote;
+#else
bytes_wrote = HDwrite(file->fd, buf, bytes_in);
+#endif /* H5_HAVE_PREADWRITE */
} while(-1 == bytes_wrote && EINTR == errno);
if(-1 == bytes_wrote) { /* error */
int myerrno = errno;
time_t mytime = HDtime(NULL);
- HDoff_t myoffset = HDlseek(file->fd, (HDoff_t)0, SEEK_CUR);
+
+ offset = HDlseek(file->fd, (HDoff_t)0, SEEK_CUR);
if(file->fa.flags & H5FD_LOG_LOC_WRITE)
HDfprintf(file->logfp, "Error! Writing: %10a-%10a (%10Zu bytes)\n", orig_addr, (orig_addr + orig_size) - 1, orig_size);
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed: time = %s, filename = '%s', file descriptor = %d, errno = %d, error message = '%s', buf = %p, total write size = %llu, bytes this sub-write = %llu, bytes actually written = %llu, offset = %llu", HDctime(&mytime), file->filename, file->fd, myerrno, HDstrerror(myerrno), buf, (unsigned long long)size, (unsigned long long)bytes_in, (unsigned long long)bytes_wrote, (unsigned long long)myoffset);
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed: time = %s, filename = '%s', file descriptor = %d, errno = %d, error message = '%s', buf = %p, total write size = %llu, bytes this sub-write = %llu, bytes actually written = %llu, offset = %llu", HDctime(&mytime), file->filename, file->fd, myerrno, HDstrerror(myerrno), buf, (unsigned long long)size, (unsigned long long)bytes_in, (unsigned long long)bytes_wrote, (unsigned long long)offset);
} /* end if */
HDassert(bytes_wrote > 0);
diff --git a/src/H5FDmpi.c b/src/H5FDmpi.c
index 7d58b7a..b2959a5 100644
--- a/src/H5FDmpi.c
+++ b/src/H5FDmpi.c
@@ -267,115 +267,6 @@ H5FD_mpi_haddr_to_MPIOff(haddr_t addr, MPI_Offset *mpi_off/*out*/)
FUNC_LEAVE_NOAPI(ret_value)
}
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_mpi_comm_info_dup
- *
- * Purpose: Make duplicates of communicator and Info object.
- * If the Info object is in fact MPI_INFO_NULL, no duplicate
- * is made but the same value assigned to the new Info object
- * handle.
- *
- * Return: Success: Non-negative. The new communicator and Info
- * object handles are returned via comm_new and
- * info_new pointers.
- *
- * Failure: Negative.
- *
- * Programmer: Albert Cheng
- * Jan 8, 2003
- *
- * Modifications:
- *-------------------------------------------------------------------------
- */
-herr_t
-H5FD_mpi_comm_info_dup(MPI_Comm comm, MPI_Info info, MPI_Comm *comm_new, MPI_Info *info_new)
-{
- herr_t ret_value=SUCCEED;
- MPI_Comm comm_dup=MPI_COMM_NULL;
- MPI_Info info_dup=MPI_INFO_NULL;
- int mpi_code;
-
- FUNC_ENTER_NOAPI(FAIL)
-
- /* Check arguments */
- if (MPI_COMM_NULL == comm)
- HGOTO_ERROR(H5E_INTERNAL, H5E_BADVALUE, FAIL, "not a valid argument")
- if (!comm_new || !info_new)
- HGOTO_ERROR(H5E_INTERNAL, H5E_BADVALUE, FAIL, "bad pointers")
-
- /* Dup them. Using temporary variables for error recovery cleanup. */
- if (MPI_SUCCESS != (mpi_code=MPI_Comm_dup(comm, &comm_dup)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Comm_dup failed", mpi_code)
- if (MPI_INFO_NULL != info){
- if (MPI_SUCCESS != (mpi_code=MPI_Info_dup(info, &info_dup)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Info_dup failed", mpi_code)
- }else{
- /* No dup, just copy it. */
- info_dup = info;
- }
-
- /* Set MPI_ERRORS_RETURN on comm_dup so that MPI failures are not fatal,
- and return codes can be checked and handled. May 23, 2017 FTW */
- if (MPI_SUCCESS != (mpi_code = MPI_Comm_set_errhandler(comm_dup, MPI_ERRORS_RETURN)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Errhandler_set failed", mpi_code)
-
- /* copy them to the return arguments */
- *comm_new = comm_dup;
- *info_new = info_dup;
-
-done:
- if (FAIL == ret_value){
- /* need to free anything created here */
- if (MPI_COMM_NULL != comm_dup)
- MPI_Comm_free(&comm_dup);
- if (MPI_INFO_NULL != info_dup)
- MPI_Info_free(&info_dup);
- }
-
- FUNC_LEAVE_NOAPI(ret_value)
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_mpi_comm_info_free
- *
- * Purpose: Free the communicator and Info object.
- * If comm or info is in fact MPI_COMM_NULL or MPI_INFO_NULL
- * respectively, no action occurs to it.
- *
- * Return: Success: Non-negative. The values the pointers refer
- * to will be set to the corresponding NULL
- * handles.
- *
- * Failure: Negative.
- *
- * Programmer: Albert Cheng
- * Jan 8, 2003
- *
- * Modifications:
- *-------------------------------------------------------------------------
- */
-herr_t
-H5FD_mpi_comm_info_free(MPI_Comm *comm, MPI_Info *info)
-{
- herr_t ret_value=SUCCEED;
-
- FUNC_ENTER_NOAPI(FAIL)
-
- /* Check arguments */
- if (!comm || !info)
- HGOTO_ERROR(H5E_INTERNAL, H5E_BADVALUE, FAIL, "not a valid argument")
-
- if (MPI_COMM_NULL != *comm)
- MPI_Comm_free(comm);
- if (MPI_INFO_NULL != *info)
- MPI_Info_free(info);
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-}
-
#ifdef NOT_YET
/*-------------------------------------------------------------------------
diff --git a/src/H5FDmpio.c b/src/H5FDmpio.c
index 87f8b6a..11f0411 100644
--- a/src/H5FDmpio.c
+++ b/src/H5FDmpio.c
@@ -22,15 +22,15 @@
#include "H5FDdrvr_module.h" /* This source code file is part of the H5FD driver module */
-#include "H5private.h" /* Generic Functions */
+#include "H5private.h" /* Generic Functions */
#include "H5CXprivate.h" /* API Contexts */
-#include "H5Dprivate.h" /* Dataset functions */
-#include "H5Eprivate.h" /* Error handling */
-#include "H5Fprivate.h" /* File access */
-#include "H5FDprivate.h" /* File drivers */
-#include "H5FDmpi.h" /* MPI-based file drivers */
-#include "H5Iprivate.h" /* IDs */
-#include "H5MMprivate.h" /* Memory management */
+#include "H5Dprivate.h" /* Dataset functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fprivate.h" /* File access */
+#include "H5FDprivate.h" /* File drivers */
+#include "H5FDmpi.h" /* MPI-based file drivers */
+#include "H5Iprivate.h" /* IDs */
+#include "H5MMprivate.h" /* Memory management */
#include "H5Pprivate.h" /* Property lists */
#ifdef H5_HAVE_PARALLEL
@@ -58,84 +58,81 @@ static char H5FD_mpi_native_g[] = "native";
* driver doesn't bother to keep it updated since it's an expensive operation.
*/
typedef struct H5FD_mpio_t {
- H5FD_t pub; /*public stuff, must be first */
- MPI_File f; /*MPIO file handle */
- MPI_Comm comm; /*communicator */
- MPI_Info info; /*file information */
- int mpi_rank; /* This process's rank */
- int mpi_size; /* Total number of processes */
- haddr_t eof; /*end-of-file marker */
- haddr_t eoa; /*end-of-address marker */
- haddr_t last_eoa; /* Last known end-of-address marker */
- haddr_t local_eof; /* Local end-of-file address for each process */
+ H5FD_t pub; /* Public stuff, must be first */
+ MPI_File f; /* MPIO file handle */
+ MPI_Comm comm; /* MPI Communicator */
+ MPI_Info info; /* MPI info object */
+ int mpi_rank; /* This process's rank */
+ int mpi_size; /* Total number of processes */
+ haddr_t eof; /* End-of-file marker */
+ haddr_t eoa; /* End-of-address marker */
+ haddr_t last_eoa; /* Last known end-of-address marker */
+ haddr_t local_eof; /* Local end-of-file address for each process */
} H5FD_mpio_t;
/* Private Prototypes */
/* Callbacks */
-static herr_t H5FD_mpio_term(void);
-static void *H5FD_mpio_fapl_get(H5FD_t *_file);
-static void *H5FD_mpio_fapl_copy(const void *_old_fa);
-static herr_t H5FD_mpio_fapl_free(void *_fa);
-static H5FD_t *H5FD_mpio_open(const char *name, unsigned flags, hid_t fapl_id,
- haddr_t maxaddr);
-static herr_t H5FD_mpio_close(H5FD_t *_file);
-static herr_t H5FD_mpio_query(const H5FD_t *_f1, unsigned long *flags);
-static haddr_t H5FD_mpio_get_eoa(const H5FD_t *_file, H5FD_mem_t type);
-static herr_t H5FD_mpio_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t addr);
-static haddr_t H5FD_mpio_get_eof(const H5FD_t *_file, H5FD_mem_t type);
-static herr_t H5FD_mpio_get_handle(H5FD_t *_file, hid_t fapl, void** file_handle);
-static herr_t H5FD_mpio_read(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr,
+static herr_t H5FD__mpio_term(void);
+static H5FD_t *H5FD__mpio_open(const char *name, unsigned flags, hid_t fapl_id,
+ haddr_t maxaddr);
+static herr_t H5FD__mpio_close(H5FD_t *_file);
+static herr_t H5FD__mpio_query(const H5FD_t *_f1, unsigned long *flags);
+static haddr_t H5FD__mpio_get_eoa(const H5FD_t *_file, H5FD_mem_t type);
+static herr_t H5FD__mpio_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t addr);
+static haddr_t H5FD__mpio_get_eof(const H5FD_t *_file, H5FD_mem_t type);
+static herr_t H5FD__mpio_get_handle(H5FD_t *_file, hid_t fapl, void** file_handle);
+static herr_t H5FD__mpio_read(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr,
size_t size, void *buf);
-static herr_t H5FD_mpio_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr,
+static herr_t H5FD__mpio_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr,
size_t size, const void *buf);
-static herr_t H5FD_mpio_flush(H5FD_t *_file, hid_t dxpl_id, hbool_t closing);
-static herr_t H5FD_mpio_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing);
-static int H5FD_mpio_mpi_rank(const H5FD_t *_file);
-static int H5FD_mpio_mpi_size(const H5FD_t *_file);
-static MPI_Comm H5FD_mpio_communicator(const H5FD_t *_file);
-static herr_t H5FD_mpio_get_info(H5FD_t *_file, void** mpi_info);
+static herr_t H5FD__mpio_flush(H5FD_t *_file, hid_t dxpl_id, hbool_t closing);
+static herr_t H5FD__mpio_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing);
+static int H5FD__mpio_mpi_rank(const H5FD_t *_file);
+static int H5FD__mpio_mpi_size(const H5FD_t *_file);
+static MPI_Comm H5FD__mpio_communicator(const H5FD_t *_file);
+static herr_t H5FD__mpio_get_info(H5FD_t *_file, void** mpi_info);
/* The MPIO file driver information */
static const H5FD_class_mpi_t H5FD_mpio_g = {
{ /* Start of superclass information */
"mpio", /*name */
HADDR_MAX, /*maxaddr */
- H5F_CLOSE_SEMI, /* fc_degree */
- H5FD_mpio_term, /*terminate */
+ H5F_CLOSE_SEMI, /*fc_degree */
+ H5FD__mpio_term, /*terminate */
NULL, /*sb_size */
NULL, /*sb_encode */
NULL, /*sb_decode */
- sizeof(H5FD_mpio_fapl_t), /*fapl_size */
- H5FD_mpio_fapl_get, /*fapl_get */
- H5FD_mpio_fapl_copy, /*fapl_copy */
- H5FD_mpio_fapl_free, /*fapl_free */
+ 0, /*fapl_size */
+ NULL, /*fapl_get */
+ NULL, /*fapl_copy */
+ NULL, /*fapl_free */
0, /*dxpl_size */
NULL, /*dxpl_copy */
NULL, /*dxpl_free */
- H5FD_mpio_open, /*open */
- H5FD_mpio_close, /*close */
+ H5FD__mpio_open, /*open */
+ H5FD__mpio_close, /*close */
NULL, /*cmp */
- H5FD_mpio_query, /*query */
+ H5FD__mpio_query, /*query */
NULL, /*get_type_map */
NULL, /*alloc */
NULL, /*free */
- H5FD_mpio_get_eoa, /*get_eoa */
- H5FD_mpio_set_eoa, /*set_eoa */
- H5FD_mpio_get_eof, /*get_eof */
- H5FD_mpio_get_handle, /*get_handle */
- H5FD_mpio_read, /*read */
- H5FD_mpio_write, /*write */
- H5FD_mpio_flush, /*flush */
- H5FD_mpio_truncate, /*truncate */
+ H5FD__mpio_get_eoa, /*get_eoa */
+ H5FD__mpio_set_eoa, /*set_eoa */
+ H5FD__mpio_get_eof, /*get_eof */
+ H5FD__mpio_get_handle, /*get_handle */
+ H5FD__mpio_read, /*read */
+ H5FD__mpio_write, /*write */
+ H5FD__mpio_flush, /*flush */
+ H5FD__mpio_truncate, /*truncate */
NULL, /*lock */
NULL, /*unlock */
H5FD_FLMAP_DICHOTOMY /*fl_map */
}, /* End of superclass information */
- H5FD_mpio_mpi_rank, /*get_rank */
- H5FD_mpio_mpi_size, /*get_size */
- H5FD_mpio_communicator, /*get_comm */
- H5FD_mpio_get_info /*get_info */
+ H5FD__mpio_mpi_rank, /*get_rank */
+ H5FD__mpio_mpi_size, /*get_size */
+ H5FD__mpio_communicator, /*get_comm */
+ H5FD__mpio_get_info /*get_info */
};
#ifdef H5FDmpio_DEBUG
@@ -162,10 +159,13 @@ static int H5FD_mpio_Debug[256] =
/*--------------------------------------------------------------------------
NAME
H5FD__init_package -- Initialize interface-specific information
+
USAGE
herr_t H5FD__init_package()
+
RETURNS
- Non-negative on success/Negative on failure
+ SUCCEED/FAIL
+
DESCRIPTION
Initializes any interface-specific data or routines. (Just calls
H5FD_mpio_init currently).
@@ -187,15 +187,15 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5FD_mpio_init
+ * Function: H5FD_mpio_init
*
- * Purpose: Initialize this driver by registering the driver with the
- * library.
+ * Purpose: Initialize this driver by registering the driver with the
+ * library.
*
- * Return: Success: The driver ID for the mpio driver.
- * Failure: Negative.
+ * Return: Success: The driver ID for the mpio driver
+ * Failure: H5I_INVALID_HID
*
- * Programmer: Robb Matzke
+ * Programmer: Robb Matzke
* Thursday, August 5, 1999
*
*-------------------------------------------------------------------------
@@ -206,10 +206,10 @@ H5FD_mpio_init(void)
#ifdef H5FDmpio_DEBUG
static int H5FD_mpio_Debug_inited = 0;
#endif /* H5FDmpio_DEBUG */
- const char *s; /* String for environment variables */
- hid_t ret_value; /* Return value */
+ const char *s; /* String for environment variables */
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
- FUNC_ENTER_NOAPI(FAIL)
+ FUNC_ENTER_NOAPI(H5I_INVALID_HID)
/* Register the MPI-IO VFD, if it isn't already */
if(H5I_VFL != H5I_get_type(H5FD_MPIO_g))
@@ -217,8 +217,10 @@ H5FD_mpio_init(void)
/* Allow MPI buf-and-file-type optimizations? */
s = HDgetenv("HDF5_MPI_OPT_TYPES");
- if(s && HDisdigit(*s))
- H5FD_mpi_opt_types_g = (hbool_t)HDstrtol(s, NULL, 0);
+ if(s && HDisdigit(*s)) {
+ long env_val = HDstrtol(s, NULL, 0);
+ H5FD_mpi_opt_types_g = (0 == env_val) ? FALSE : TRUE;
+ }
#ifdef H5FDmpio_DEBUG
if(!H5FD_mpio_Debug_inited) {
@@ -226,12 +228,12 @@ H5FD_mpio_init(void)
s = HDgetenv("H5FD_mpio_Debug");
if(s) {
/* Set debug mask */
- while(*s) {
- H5FD_mpio_Debug[(int)*s]++;
- s++;
- } /* end while */
+ while(*s) {
+ H5FD_mpio_Debug[(int)*s]++;
+ s++;
+ } /* end while */
} /* end if */
- H5FD_mpio_Debug_inited++;
+ H5FD_mpio_Debug_inited++;
} /* end if */
#endif /* H5FDmpio_DEBUG */
@@ -244,9 +246,9 @@ done:
/*---------------------------------------------------------------------------
- * Function: H5FD_mpio_term
+ * Function: H5FD__mpio_term
*
- * Purpose: Shut down the VFD
+ * Purpose: Shut down the VFD
*
* Returns: Non-negative on success or negative on failure
*
@@ -256,74 +258,73 @@ done:
*---------------------------------------------------------------------------
*/
static herr_t
-H5FD_mpio_term(void)
+H5FD__mpio_term(void)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
/* Reset VFL ID */
- H5FD_MPIO_g=0;
+ H5FD_MPIO_g = 0;
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5FD_mpio_term() */
+} /* end H5FD__mpio_term() */
/*-------------------------------------------------------------------------
- * Function: H5Pset_fapl_mpio
+ * Function: H5Pset_fapl_mpio
*
- * Purpose: Store the user supplied MPIO communicator comm and info in
- * the file access property list FAPL_ID which can then be used
- * to create and/or open the file. This function is available
- * only in the parallel HDF5 library and is not collective.
+ * Purpose: Store the user supplied MPIO communicator comm and info in
+ * the file access property list FAPL_ID which can then be used
+ * to create and/or open the file. This function is available
+ * only in the parallel HDF5 library and is not collective.
*
- * comm is the MPI communicator to be used for file open as
- * defined in MPI_FILE_OPEN of MPI-2. This function makes a
- * duplicate of comm. Any modification to comm after this function
- * call returns has no effect on the access property list.
+ * comm is the MPI communicator to be used for file open as
+ * defined in MPI_FILE_OPEN of MPI-2. This function makes a
+ * duplicate of comm. Any modification to comm after this function
+ * call returns has no effect on the access property list.
*
- * info is the MPI Info object to be used for file open as
- * defined in MPI_FILE_OPEN of MPI-2. This function makes a
- * duplicate of info. Any modification to info after this
- * function call returns has no effect on the access property
- * list.
+ * info is the MPI Info object to be used for file open as
+ * defined in MPI_FILE_OPEN of MPI-2. This function makes a
+ * duplicate of info. Any modification to info after this
+ * function call returns has no effect on the access property
+ * list.
*
* If fapl_id has previously set comm and info values, they
* will be replaced and the old communicator and Info object
* are freed.
*
- * Return: Success: Non-negative
+ * Return: Success: Non-negative
+ * Failure: Negative
*
- * Failure: Negative
- *
- * Programmer: Albert Cheng
- * Feb 3, 1998
+ * Programmer: Albert Cheng
+ * Feb 3, 1998
*
*-------------------------------------------------------------------------
*/
herr_t
H5Pset_fapl_mpio(hid_t fapl_id, MPI_Comm comm, MPI_Info info)
{
- H5FD_mpio_fapl_t fa;
H5P_genplist_t *plist; /* Property list pointer */
herr_t ret_value;
FUNC_ENTER_API(FAIL)
H5TRACE3("e", "iMcMi", fapl_id, comm, info);
+ /* Check arguments */
if(fapl_id == H5P_DEFAULT)
HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "can't set values in default property list")
-
- /* Check arguments */
if(NULL == (plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS)))
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a file access list")
if(MPI_COMM_NULL == comm)
- HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a valid communicator")
+ HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "MPI_COMM_NULL is not a valid communicator")
- /* Initialize driver specific properties */
- fa.comm = comm;
- fa.info = info;
+ /* Set the MPI communicator and info object */
+ if(H5P_set(plist, H5F_ACS_MPI_PARAMS_COMM_NAME, &comm) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set MPI communicator")
+ if(H5P_set(plist, H5F_ACS_MPI_PARAMS_INFO_NAME, &info) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set MPI info object")
/* duplication is done during driver setting. */
- ret_value = H5P_set_driver(plist, H5FD_MPIO, &fa);
+ ret_value = H5P_set_driver(plist, H5FD_MPIO, NULL);
done:
FUNC_LEAVE_API(ret_value)
@@ -331,26 +332,25 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5Pget_fapl_mpio
- *
- * Purpose: If the file access property list is set to the H5FD_MPIO
- * driver then this function returns duplicates of the MPI
- * communicator and Info object stored through the comm and
- * info pointers. It is the responsibility of the application
- * to free the returned communicator and Info object.
+ * Function: H5Pget_fapl_mpio
+ *
+ * Purpose: If the file access property list is set to the H5FD_MPIO
+ * driver then this function returns duplicates of the MPI
+ * communicator and Info object stored through the comm and
+ * info pointers. It is the responsibility of the application
+ * to free the returned communicator and Info object.
+ *
+ * Return: Success: Non-negative with the communicator and
+ * Info object returned through the comm and
+ * info arguments if non-null. Since they are
+ * duplicates of the stored objects, future
+ * modifications to the access property list do
+ * not affect them and it is the responsibility
+ * of the application to free them.
+ * Failure: Negative
*
- * Return: Success: Non-negative with the communicator and
- * Info object returned through the comm and
- * info arguments if non-null. Since they are
- * duplicates of the stored objects, future
- * modifications to the access property list do
- * not affect them and it is the responsibility
- * of the application to free them.
- *
- * Failure: Negative
- *
- * Programmer: Robb Matzke
- * Thursday, February 26, 1998
+ * Programmer: Robb Matzke
+ * Thursday, February 26, 1998
*
*-------------------------------------------------------------------------
*/
@@ -358,75 +358,67 @@ herr_t
H5Pget_fapl_mpio(hid_t fapl_id, MPI_Comm *comm/*out*/, MPI_Info *info/*out*/)
{
H5P_genplist_t *plist; /* Property list pointer */
- const H5FD_mpio_fapl_t *fa; /* MPIO fapl info */
- MPI_Comm comm_tmp = MPI_COMM_NULL;
- hbool_t comm_copied = FALSE; /* MPI Comm has been duplicated */
- int mpi_code; /* MPI return code */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE3("e", "ixx", fapl_id, comm, info);
+ /* Set comm and info in case we have problems */
+ if(comm)
+ *comm = MPI_COMM_NULL;
+ if(info)
+ *info = MPI_INFO_NULL;
+
+ /* Check arguments */
if(NULL == (plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS)))
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a file access list")
if(H5FD_MPIO != H5P_peek_driver(plist))
- HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "incorrect VFL driver")
- if(NULL == (fa = (const H5FD_mpio_fapl_t *)H5P_peek_driver_info(plist)))
- HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "bad VFL driver info")
-
- /* Store the duplicated communicator in a temporary variable for error */
- /* recovery in case the INFO duplication fails. */
- if(comm) {
- if(MPI_SUCCESS != (mpi_code = MPI_Comm_dup(fa->comm, &comm_tmp)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Comm_dup failed", mpi_code)
- comm_copied = TRUE;
- } /* end if */
-
- if(info) {
- if(MPI_INFO_NULL != fa->info) {
- if(MPI_SUCCESS != (mpi_code = MPI_Info_dup(fa->info, info)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Info_dup failed", mpi_code)
- } /* end if */
- else
- /* do not dup it */
- *info = MPI_INFO_NULL;
- } /* end if */
+ HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "VFL driver is not MPI-I/O")
- /* Store the copied communicator, now that the Info object has been
- * successfully copied.
- */
+ /* Get the MPI communicator and info object */
if(comm)
- *comm = comm_tmp;
+ if(H5P_get(plist, H5F_ACS_MPI_PARAMS_COMM_NAME, comm) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get MPI communicator")
+ if(info)
+ if(H5P_get(plist, H5F_ACS_MPI_PARAMS_INFO_NAME, info) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get MPI info object")
done:
- if(ret_value < 0)
- /* need to free anything created here */
- if(comm_copied)
- MPI_Comm_free(&comm_tmp);
+ /* Clean up anything duplicated on errors. The free calls will set
+ * the output values to MPI_COMM|INFO_NULL.
+ */
+ if(ret_value != SUCCEED) {
+ if(comm)
+ if(H5_mpi_comm_free(comm) < 0)
+ HDONE_ERROR(H5E_PLIST, H5E_CANTFREE, FAIL, "unable to free MPI communicator")
+ if(info)
+ if(H5_mpi_info_free(info) < 0)
+ HDONE_ERROR(H5E_PLIST, H5E_CANTFREE, FAIL, "unable to free MPI info object")
+ }
FUNC_LEAVE_API(ret_value)
} /* end H5Pget_fapl_mpio() */
/*-------------------------------------------------------------------------
- * Function: H5Pset_dxpl_mpio
+ * Function: H5Pset_dxpl_mpio
*
- * Purpose: Set the data transfer property list DXPL_ID to use transfer
- * mode XFER_MODE. The property list can then be used to control
- * the I/O transfer mode during data I/O operations. The valid
- * transfer modes are:
+ * Purpose: Set the data transfer property list DXPL_ID to use transfer
+ * mode XFER_MODE. The property list can then be used to control
+ * the I/O transfer mode during data I/O operations. The valid
+ * transfer modes are:
*
- * H5FD_MPIO_INDEPENDENT:
- * Use independent I/O access (the default).
+ * H5FD_MPIO_INDEPENDENT:
+ * Use independent I/O access (the default).
*
- * H5FD_MPIO_COLLECTIVE:
- * Use collective I/O access.
+ * H5FD_MPIO_COLLECTIVE:
+ * Use collective I/O access.
*
- * Return: Success: Non-negative
- * Failure: Negative
+ * Return: Success: Non-negative
+ * Failure: Negative
*
- * Programmer: Albert Cheng
- * April 2, 1998
+ * Programmer: Albert Cheng
+ * April 2, 1998
*
*-------------------------------------------------------------------------
*/
@@ -439,10 +431,9 @@ H5Pset_dxpl_mpio(hid_t dxpl_id, H5FD_mpio_xfer_t xfer_mode)
FUNC_ENTER_API(FAIL)
H5TRACE2("e", "iDt", dxpl_id, xfer_mode);
+ /* Check arguments */
if(dxpl_id == H5P_DEFAULT)
HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "can't set values in default property list")
-
- /* Check arguments */
if(NULL == (plist = H5P_object_verify(dxpl_id, H5P_DATASET_XFER)))
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a dxpl")
if(H5FD_MPIO_INDEPENDENT != xfer_mode && H5FD_MPIO_COLLECTIVE != xfer_mode)
@@ -458,19 +449,18 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5Pget_dxpl_mpio
- *
- * Purpose: Queries the transfer mode current set in the data transfer
- * property list DXPL_ID. This is not collective.
+ * Function: H5Pget_dxpl_mpio
*
- * Return: Success: Non-negative, with the transfer mode returned
- * through the XFER_MODE argument if it is
- * non-null.
+ * Purpose: Queries the transfer mode current set in the data transfer
+ * property list DXPL_ID. This is not collective.
*
- * Failure: Negative
+ * Return: Success: Non-negative, with the transfer mode returned
+ * through the XFER_MODE argument if it is
+ * non-null.
+ * Failure: Negative
*
- * Programmer: Albert Cheng
- * April 2, 1998
+ * Programmer: Albert Cheng
+ * April 2, 1998
*
*-------------------------------------------------------------------------
*/
@@ -483,6 +473,7 @@ H5Pget_dxpl_mpio(hid_t dxpl_id, H5FD_mpio_xfer_t *xfer_mode/*out*/)
FUNC_ENTER_API(FAIL)
H5TRACE2("e", "ix", dxpl_id, xfer_mode);
+ /* Check arguments */
if(NULL == (plist = H5P_object_verify(dxpl_id, H5P_DATASET_XFER)))
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a dxpl")
@@ -497,21 +488,20 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5Pset_dxpl_mpio_collective_opt
+ * Function: H5Pset_dxpl_mpio_collective_opt
*
- * Purpose: To set a flag to choose linked chunk I/O or multi-chunk I/O
- * without involving decision-making inside HDF5
+ * Purpose: To set a flag to choose linked chunk I/O or multi-chunk I/O
+ * without involving decision-making inside HDF5
*
- * Note: The library will do linked chunk I/O or multi-chunk I/O without
- * involving communications for decision-making process.
- * The library won't behave as it asks for only when we find
- * that the low-level MPI-IO package doesn't support this.
+ * Note: The library will do linked chunk I/O or multi-chunk I/O without
+ * involving communications for decision-making process.
+ * The library won't behave as it asks for only when we find
+ * that the low-level MPI-IO package doesn't support this.
*
- * Return: Success: Non-negative
- * Failure: Negative
+ * Return: Success: Non-negative
+ * Failure: Negative
*
- * Programmer: Kent Yang
- * ? ?, ?
+ * Programmer: Kent Yang
*
*-------------------------------------------------------------------------
*/
@@ -524,10 +514,9 @@ H5Pset_dxpl_mpio_collective_opt(hid_t dxpl_id, H5FD_mpio_collective_opt_t opt_mo
FUNC_ENTER_API(FAIL)
H5TRACE2("e", "iDc", dxpl_id, opt_mode);
+ /* Check arguments */
if(dxpl_id == H5P_DEFAULT)
HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "can't set values in default property list")
-
- /* Check arguments */
if(NULL == (plist = H5P_object_verify(dxpl_id, H5P_DATASET_XFER)))
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a dxpl")
@@ -541,21 +530,20 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5Pset_dxpl_mpio_chunk_opt
+ * Function: H5Pset_dxpl_mpio_chunk_opt
*
- * Purpose: To set a flag to choose linked chunk I/O or multi-chunk I/O
- * without involving decision-making inside HDF5
+ * Purpose: To set a flag to choose linked chunk I/O or multi-chunk I/O
+ * without involving decision-making inside HDF5
*
- * Note: The library will do linked chunk I/O or multi-chunk I/O without
- * involving communications for decision-making process.
- * The library won't behave as it asks for only when we find
- * that the low-level MPI-IO package doesn't support this.
+ * Note: The library will do linked chunk I/O or multi-chunk I/O without
+ * involving communications for decision-making process.
+ * The library won't behave as it asks for only when we find
+ * that the low-level MPI-IO package doesn't support this.
*
- * Return: Success: Non-negative
- * Failure: Negative
+ * Return: Success: Non-negative
+ * Failure: Negative
*
- * Programmer: Kent Yang
- * ? ?, ?
+ * Programmer: Kent Yang
*
*-------------------------------------------------------------------------
*/
@@ -568,10 +556,9 @@ H5Pset_dxpl_mpio_chunk_opt(hid_t dxpl_id, H5FD_mpio_chunk_opt_t opt_mode)
FUNC_ENTER_API(FAIL)
H5TRACE2("e", "iDh", dxpl_id, opt_mode);
+ /* Check arguments */
if(dxpl_id == H5P_DEFAULT)
HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "can't set values in default property list")
-
- /* Check arguments */
if(NULL == (plist = H5P_object_verify(dxpl_id, H5P_DATASET_XFER)))
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a dxpl")
@@ -585,19 +572,18 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5Pset_dxpl_mpio_chunk_opt_num
+ * Function: H5Pset_dxpl_mpio_chunk_opt_num
*
- * Purpose: To set a threshold for doing linked chunk IO
+ * Purpose: To set a threshold for doing linked chunk IO
*
- * Note: If the number is greater than the threshold set by the user,
- * the library will do linked chunk I/O; otherwise, I/O will be
- * done for every chunk.
+ * Note: If the number is greater than the threshold set by the user,
+ * the library will do linked chunk I/O; otherwise, I/O will be
+ * done for every chunk.
*
- * Return: Success: Non-negative
- * Failure: Negative
+ * Return: Success: Non-negative
+ * Failure: Negative
*
- * Programmer: Kent Yang
- * ? ?, ?
+ * Programmer: Kent Yang
*
*-------------------------------------------------------------------------
*/
@@ -610,10 +596,9 @@ H5Pset_dxpl_mpio_chunk_opt_num(hid_t dxpl_id, unsigned num_chunk_per_proc)
FUNC_ENTER_API(FAIL)
H5TRACE2("e", "iIu", dxpl_id, num_chunk_per_proc);
+ /* Check arguments */
if(dxpl_id == H5P_DEFAULT)
HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "can't set values in default property list")
-
- /* Check arguments */
if(NULL == (plist = H5P_object_verify(dxpl_id, H5P_DATASET_XFER)))
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a dxpl")
@@ -627,22 +612,21 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5Pset_dxpl_mpio_chunk_opt_ratio
+ * Function: H5Pset_dxpl_mpio_chunk_opt_ratio
*
- * Purpose: To set a threshold for doing collective I/O for each chunk
+ * Purpose: To set a threshold for doing collective I/O for each chunk
*
- * Note: The library will calculate the percentage of the number of
- * process holding selections at each chunk. If that percentage
- * of number of process in the individual chunk is greater than
- * the threshold set by the user, the library will do collective
- * chunk I/O for this chunk; otherwise, independent I/O will be
- * done for this chunk.
+ * Note: The library will calculate the percentage of the number of
+ * process holding selections at each chunk. If that percentage
+ * of number of process in the individual chunk is greater than
+ * the threshold set by the user, the library will do collective
+ * chunk I/O for this chunk; otherwise, independent I/O will be
+ * done for this chunk.
*
- * Return: Success: Non-negative
- * Failure: Negative
+ * Return: Success: Non-negative
+ * Failure: Negative
*
- * Programmer: Kent Yang
- * ? ?, ?
+ * Programmer: Kent Yang
*
*-------------------------------------------------------------------------
*/
@@ -655,10 +639,9 @@ H5Pset_dxpl_mpio_chunk_opt_ratio(hid_t dxpl_id, unsigned percent_num_proc_per_ch
FUNC_ENTER_API(FAIL)
H5TRACE2("e", "iIu", dxpl_id, percent_num_proc_per_chunk);
+ /* Check arguments */
if(dxpl_id == H5P_DEFAULT)
HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "can't set values in default property list")
-
- /* Check arguments */
if(NULL == (plist = H5P_object_verify(dxpl_id, H5P_DATASET_XFER)))
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a dxpl")
@@ -672,154 +655,14 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5FD_mpio_fapl_get
- *
- * Purpose: Returns a file access property list which could be used to
- * create another file the same as this one.
- *
- * Return: Success: Ptr to new file access property list with all
- * fields copied from the file pointer.
- *
- * Failure: NULL
- *
- * Programmer: Robb Matzke
- * Friday, August 13, 1999
- *
- *-------------------------------------------------------------------------
- */
-static void *
-H5FD_mpio_fapl_get(H5FD_t *_file)
-{
- H5FD_mpio_t *file = (H5FD_mpio_t*)_file;
- H5FD_mpio_fapl_t *fa = NULL;
- void *ret_value; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT
-
- HDassert(file);
- HDassert(H5FD_MPIO == file->pub.driver_id);
-
- if(NULL == (fa = (H5FD_mpio_fapl_t *)H5MM_calloc(sizeof(H5FD_mpio_fapl_t))))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
-
- /* Duplicate communicator and Info object. */
- if(FAIL == H5FD_mpi_comm_info_dup(file->comm, file->info, &fa->comm, &fa->info))
- HGOTO_ERROR(H5E_INTERNAL, H5E_CANTCOPY, NULL, "Communicator/Info duplicate failed")
-
- /* Set return value */
- ret_value = fa;
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_mpio_fapl_copy
- *
- * Purpose: Copies the mpio-specific file access properties.
- *
- * Return: Success: Ptr to a new property list
- *
- * Failure: NULL
- *
- * Programmer: Albert Cheng
- * Jan 8, 2003
- *
- *-------------------------------------------------------------------------
- */
-static void *
-H5FD_mpio_fapl_copy(const void *_old_fa)
-{
- void *ret_value = NULL;
- const H5FD_mpio_fapl_t *old_fa = (const H5FD_mpio_fapl_t*)_old_fa;
- H5FD_mpio_fapl_t *new_fa = NULL;
-
- FUNC_ENTER_NOAPI_NOINIT
-#ifdef H5FDmpio_DEBUG
-if (H5FD_mpio_Debug[(int)'t'])
-fprintf(stderr, "enter H5FD_mpio_fapl_copy\n");
-#endif
-
- if(NULL == (new_fa = (H5FD_mpio_fapl_t *)H5MM_malloc(sizeof(H5FD_mpio_fapl_t))))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
-
- /* Copy the general information */
- HDmemcpy(new_fa, old_fa, sizeof(H5FD_mpio_fapl_t));
-
- /* Duplicate communicator and Info object. */
- if(FAIL == H5FD_mpi_comm_info_dup(old_fa->comm, old_fa->info, &new_fa->comm, &new_fa->info))
- HGOTO_ERROR(H5E_INTERNAL, H5E_CANTCOPY, NULL, "Communicator/Info duplicate failed")
- ret_value = new_fa;
-
-done:
- if (NULL == ret_value){
- /* cleanup */
- if (new_fa)
- H5MM_xfree(new_fa);
- }
-
-#ifdef H5FDmpio_DEBUG
-if (H5FD_mpio_Debug[(int)'t'])
-fprintf(stderr, "leaving H5FD_mpio_fapl_copy\n");
-#endif
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FD_mpio_fapl_copy() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_mpio_fapl_free
- *
- * Purpose: Frees the mpio-specific file access properties.
- *
- * Return: Success: 0
- *
- * Failure: -1
- *
- * Programmer: Albert Cheng
- * Jan 8, 2003
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5FD_mpio_fapl_free(void *_fa)
-{
- herr_t ret_value = SUCCEED;
- H5FD_mpio_fapl_t *fa = (H5FD_mpio_fapl_t*)_fa;
-
- FUNC_ENTER_NOAPI_NOINIT_NOERR
-#ifdef H5FDmpio_DEBUG
-if (H5FD_mpio_Debug[(int)'t'])
-fprintf(stderr, "in H5FD_mpio_fapl_free\n");
-#endif
- HDassert(fa);
-
- /* Free the internal communicator and INFO object */
- HDassert(MPI_COMM_NULL!=fa->comm);
- H5FD_mpi_comm_info_free(&fa->comm, &fa->info);
- H5MM_xfree(fa);
-
-#ifdef H5FDmpio_DEBUG
-if (H5FD_mpio_Debug[(int)'t'])
-fprintf(stderr, "leaving H5FD_mpio_fapl_free\n");
-#endif
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FD_mpio_fapl_free() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_set_mpio_atomicity
- *
- * Purpose: Sets the atomicity mode
+ * Function: H5FD_set_mpio_atomicity
*
- * Return: Success: Non-negative
+ * Purpose: Sets the atomicity mode
*
- * Failure: Negative
+ * Return: SUCCEED/FAIL
*
- * Programmer: Mohamad Chaarawi
- * Feb 14, 2012
+ * Programmer: Mohamad Chaarawi
+ * Feb 14, 2012
*
*-------------------------------------------------------------------------
*/
@@ -834,39 +677,38 @@ H5FD_set_mpio_atomicity(H5FD_t *_file, hbool_t flag)
FUNC_ENTER_NOAPI_NOINIT
#ifdef H5FDmpio_DEBUG
- if (H5FD_mpio_Debug[(int)'t'])
- fprintf(stdout, "Entering H5FD_set_mpio_atomicity\n");
+ if(H5FD_mpio_Debug[(int)'t'])
+ HDfprintf(stdout, "%s: Entering\n", FUNC);
#endif
- if (FALSE == flag)
+ if(FALSE == flag)
temp_flag = 0;
else
temp_flag = 1;
/* set atomicity value */
- if (MPI_SUCCESS != (mpi_code=MPI_File_set_atomicity(file->f, temp_flag)))
+ if(MPI_SUCCESS != (mpi_code = MPI_File_set_atomicity(file->f, temp_flag)))
HMPI_GOTO_ERROR(FAIL, "MPI_File_set_atomicity", mpi_code)
done:
#ifdef H5FDmpio_DEBUG
- if (H5FD_mpio_Debug[(int)'t'])
- fprintf(stdout, "Leaving H5FD_set_mpio_atomicity\n");
+ if(H5FD_mpio_Debug[(int)'t'])
+ HDfprintf(stdout, "%s: Leaving\n", FUNC);
#endif
+
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FD_set_mpio_atomicity() */
/*-------------------------------------------------------------------------
- * Function: H5FD_get_mpio_atomicity
+ * Function: H5FD_get_mpio_atomicity
*
- * Purpose: Returns the atomicity mode
+ * Purpose: Returns the atomicity mode
*
- * Return: Success: Non-negative
+ * Return: SUCCEED/FAIL
*
- * Failure: Negative
- *
- * Programmer: Mohamad Chaarawi
- * Feb 14, 2012
+ * Programmer: Mohamad Chaarawi
+ * Feb 14, 2012
*
*-------------------------------------------------------------------------
*/
@@ -881,94 +723,83 @@ H5FD_get_mpio_atomicity(H5FD_t *_file, hbool_t *flag)
FUNC_ENTER_NOAPI_NOINIT
#ifdef H5FDmpio_DEBUG
- if (H5FD_mpio_Debug[(int)'t'])
- fprintf(stdout, "Entering H5FD_get_mpio_atomicity\n");
+ if(H5FD_mpio_Debug[(int)'t'])
+ HDfprintf(stdout, "%s: Entering\n", FUNC);
#endif
- /* get atomicity value */
- if (MPI_SUCCESS != (mpi_code=MPI_File_get_atomicity(file->f, &temp_flag)))
+ /* Get atomicity value */
+ if(MPI_SUCCESS != (mpi_code = MPI_File_get_atomicity(file->f, &temp_flag)))
HMPI_GOTO_ERROR(FAIL, "MPI_File_get_atomicity", mpi_code)
- if (0 != temp_flag)
+ if(0 != temp_flag)
*flag = TRUE;
else
*flag = FALSE;
done:
#ifdef H5FDmpio_DEBUG
- if (H5FD_mpio_Debug[(int)'t'])
- fprintf(stdout, "Leaving H5FD_get_mpio_atomicity\n");
+ if(H5FD_mpio_Debug[(int)'t'])
+ HDfprintf(stdout, "%s: Leaving\n", FUNC);
#endif
+
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FD_get_mpio_atomicity() */
/*-------------------------------------------------------------------------
- * Function: H5FD_mpio_open
+ * Function: H5FD__mpio_open
*
* Purpose: Opens a file with name NAME. The FLAGS are a bit field with
- * purpose similar to the second argument of open(2) and which
- * are defined in H5Fpublic.h. The file access property list
- * FAPL_ID contains the properties driver properties and MAXADDR
- * is the largest address which this file will be expected to
- * access. This is collective.
- *
- * Return: Success: A new file pointer.
+ * purpose similar to the second argument of open(2) and which
+ * are defined in H5Fpublic.h. The file access property list
+ * FAPL_ID contains the properties driver properties and MAXADDR
+ * is the largest address which this file will be expected to
+ * access. This is collective.
*
- * Failure: NULL
+ * Return: Success: A new file pointer
+ * Failure: NULL
*
- * Programmer:
+ * Programmer: Robert Kim Yates
* January 30, 1998
*
*-------------------------------------------------------------------------
*/
static H5FD_t *
-H5FD_mpio_open(const char *name, unsigned flags, hid_t fapl_id,
- haddr_t H5_ATTR_UNUSED maxaddr)
+H5FD__mpio_open(const char *name, unsigned flags, hid_t fapl_id,
+ haddr_t H5_ATTR_UNUSED maxaddr)
{
- H5FD_mpio_t *file=NULL;
- MPI_File fh;
- unsigned file_opened=0; /* Flag to indicate that the file was successfully opened */
- int mpi_amode;
- int mpi_rank; /* MPI rank of this process */
- int mpi_size; /* Total number of MPI processes */
- int mpi_code; /* mpi return code */
- MPI_Offset size;
- const H5FD_mpio_fapl_t *fa = NULL;
- H5FD_mpio_fapl_t _fa;
+ H5FD_mpio_t *file = NULL;
+ MPI_File fh;
+ hbool_t file_opened = FALSE; /* Flag to indicate that the file was successfully opened */
+ int mpi_amode;
+ int mpi_rank; /* MPI rank of this process */
+ int mpi_size; /* Total number of MPI processes */
+ int mpi_code; /* MPI return code */
+ MPI_Offset size;
H5P_genplist_t *plist; /* Property list pointer */
- MPI_Comm comm_dup = MPI_COMM_NULL;
- MPI_Info info_dup = MPI_INFO_NULL;
- H5FD_t *ret_value; /* Return value */
+ MPI_Comm comm = MPI_COMM_NULL;
+ MPI_Info info = MPI_INFO_NULL;
+ H5FD_t *ret_value = NULL; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
#ifdef H5FDmpio_DEBUG
- if (H5FD_mpio_Debug[(int)'t']) {
- fprintf(stdout, "Entering H5FD_mpio_open(name=\"%s\", flags=0x%x, "
- "fapl_id=%d, maxaddr=%lu)\n", name, flags, (int)fapl_id, (unsigned long)maxaddr);
- }
+ if(H5FD_mpio_Debug[(int)'t'])
+ HDfprintf(stdout, "%s: Entering - name = \"%s\", flags = 0x%x, fapl_id = %d, maxaddr = %lu\n", FUNC, name, flags, (int)fapl_id, (unsigned long)maxaddr);
#endif
- /* Obtain a pointer to mpio-specific file access properties */
+ /* Get a pointer to the fapl */
if(NULL == (plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list")
- if(H5P_FILE_ACCESS_DEFAULT == fapl_id || H5FD_MPIO != H5P_peek_driver(plist)) {
- _fa.comm = MPI_COMM_SELF; /*default*/
- _fa.info = MPI_INFO_NULL; /*default*/
- fa = &_fa;
- } /* end if */
- else {
- if(NULL == (fa = (const H5FD_mpio_fapl_t *)H5P_peek_driver_info(plist)))
- HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, NULL, "bad VFL driver info")
- } /* end else */
- /* Duplicate communicator and Info object for use by this file. */
- if(FAIL == H5FD_mpi_comm_info_dup(fa->comm, fa->info, &comm_dup, &info_dup))
- HGOTO_ERROR(H5E_INTERNAL, H5E_CANTCOPY, NULL, "Communicator/Info duplicate failed")
+ /* Get the MPI communicator and info object from the property list */
+ if(H5P_get(plist, H5F_ACS_MPI_PARAMS_COMM_NAME, &comm) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTGET, NULL, "can't get MPI communicator")
+ if(H5P_get(plist, H5F_ACS_MPI_PARAMS_INFO_NAME, &info) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTGET, NULL, "can't get MPI info object")
- /* convert HDF5 flags to MPI-IO flags */
- /* some combinations are illegal; let MPI-IO figure it out */
+ /* Convert HDF5 flags to MPI-IO flags */
+ /* Some combinations are illegal; let MPI-IO figure it out */
mpi_amode = (flags & H5F_ACC_RDWR) ? MPI_MODE_RDWR : MPI_MODE_RDONLY;
if(flags & H5F_ACC_CREAT)
mpi_amode |= MPI_MODE_CREATE;
@@ -977,39 +808,37 @@ H5FD_mpio_open(const char *name, unsigned flags, hid_t fapl_id,
#ifdef H5FDmpio_DEBUG
/* Check for debug commands in the info parameter */
- {
- if(MPI_INFO_NULL != info_dup) {
- char debug_str[128];
- int flag;
-
- MPI_Info_get(fa->info, H5F_MPIO_DEBUG_KEY, sizeof(debug_str) - 1, debug_str, &flag);
- if(flag) {
- int i;
-
- fprintf(stdout, "H5FD_mpio debug flags = '%s'\n", debug_str);
- for(i = 0; debug_str[i]/*end of string*/ && i < 128/*just in case*/; ++i)
- H5FD_mpio_Debug[(int)debug_str[i]] = 1;
- }
- }
- }
+ if(MPI_INFO_NULL != info) {
+ char debug_str[128];
+ int flag;
+
+ MPI_Info_get(info, H5F_MPIO_DEBUG_KEY, sizeof(debug_str) - 1, debug_str, &flag);
+ if(flag) {
+ int i;
+
+ HDfprintf(stdout, "H5FD_mpio debug flags = '%s'\n", debug_str);
+ for(i = 0; debug_str[i]/*end of string*/ && i < 128/*just in case*/; ++i)
+ H5FD_mpio_Debug[(int)debug_str[i]] = 1;
+ } /* end if */
+ } /* end if */
#endif
- if(MPI_SUCCESS != (mpi_code = MPI_File_open(comm_dup, name, mpi_amode, info_dup, &fh)))
+ if(MPI_SUCCESS != (mpi_code = MPI_File_open(comm, name, mpi_amode, info, &fh)))
HMPI_GOTO_ERROR(NULL, "MPI_File_open failed", mpi_code)
- file_opened=1;
+ file_opened = TRUE;
/* Get the MPI rank of this process and the total number of processes */
- if (MPI_SUCCESS != (mpi_code=MPI_Comm_rank (comm_dup, &mpi_rank)))
+ if (MPI_SUCCESS != (mpi_code = MPI_Comm_rank (comm, &mpi_rank)))
HMPI_GOTO_ERROR(NULL, "MPI_Comm_rank failed", mpi_code)
- if (MPI_SUCCESS != (mpi_code=MPI_Comm_size (comm_dup, &mpi_size)))
+ if (MPI_SUCCESS != (mpi_code = MPI_Comm_size (comm, &mpi_size)))
HMPI_GOTO_ERROR(NULL, "MPI_Comm_size failed", mpi_code)
/* Build the return value and initialize it */
if(NULL == (file = (H5FD_mpio_t *)H5MM_calloc(sizeof(H5FD_mpio_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
file->f = fh;
- file->comm = comm_dup;
- file->info = info_dup;
+ file->comm = comm;
+ file->info = info;
file->mpi_rank = mpi_rank;
file->mpi_size = mpi_size;
@@ -1020,7 +849,7 @@ H5FD_mpio_open(const char *name, unsigned flags, hid_t fapl_id,
} /* end if */
/* Broadcast file size */
- if(MPI_SUCCESS != (mpi_code = MPI_Bcast(&size, (int)sizeof(MPI_Offset), MPI_BYTE, 0, comm_dup)))
+ if(MPI_SUCCESS != (mpi_code = MPI_Bcast(&size, (int)sizeof(MPI_Offset), MPI_BYTE, 0, comm)))
HMPI_GOTO_ERROR(NULL, "MPI_Bcast failed", mpi_code)
/* Determine if the file should be truncated */
@@ -1029,7 +858,7 @@ H5FD_mpio_open(const char *name, unsigned flags, hid_t fapl_id,
HMPI_GOTO_ERROR(NULL, "MPI_File_set_size failed", mpi_code)
/* Don't let any proc return until all have truncated the file. */
- if (MPI_SUCCESS!= (mpi_code=MPI_Barrier(comm_dup)))
+ if (MPI_SUCCESS != (mpi_code = MPI_Barrier(comm)))
HMPI_GOTO_ERROR(NULL, "MPI_Barrier failed", mpi_code)
/* File is zero size now */
@@ -1041,116 +870,99 @@ H5FD_mpio_open(const char *name, unsigned flags, hid_t fapl_id,
file->local_eof = file->eof;
/* Set return value */
- ret_value=(H5FD_t*)file;
+ ret_value = (H5FD_t*)file;
done:
- if(ret_value==NULL) {
+ if(ret_value == NULL) {
if(file_opened)
MPI_File_close(&fh);
- if (MPI_COMM_NULL != comm_dup)
- MPI_Comm_free(&comm_dup);
- if (MPI_INFO_NULL != info_dup)
- MPI_Info_free(&info_dup);
- if (file)
- H5MM_xfree(file);
+ if(H5_mpi_comm_free(&comm) < 0)
+ HDONE_ERROR(H5E_VFL, H5E_CANTFREE, NULL, "unable to free MPI communicator")
+ if(H5_mpi_info_free(&info) < 0)
+ HDONE_ERROR(H5E_VFL, H5E_CANTFREE, NULL, "unable to free MPI info object")
+ if(file)
+ H5MM_xfree(file);
} /* end if */
#ifdef H5FDmpio_DEBUG
- if (H5FD_mpio_Debug[(int)'t'])
- fprintf(stdout, "Leaving H5FD_mpio_open\n" );
+ if(H5FD_mpio_Debug[(int)'t'])
+ HDfprintf(stdout, "%s: Leaving\n", FUNC);
#endif
+
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FD_mpio_open() */
+} /* end H5FD__mpio_open() */
/*-------------------------------------------------------------------------
- * Function: H5FD_mpio_close
+ * Function: H5FD__mpio_close
*
* Purpose: Closes a file. This is collective.
*
- * Return: Success: Non-negative
- *
- * Failure: Negative
+ * Return: SUCCEED/FAIL
*
* Programmer: Unknown
* January 30, 1998
*
- * Modifications:
- * Robb Matzke, 1998-02-18
- * Added the ACCESS_PARMS argument.
- *
- * Robb Matzke, 1999-08-06
- * Modified to work with the virtual file layer.
- *
- * Albert Cheng, 2003-04-17
- * Free the communicator stored.
*-------------------------------------------------------------------------
*/
static herr_t
-H5FD_mpio_close(H5FD_t *_file)
+H5FD__mpio_close(H5FD_t *_file)
{
- H5FD_mpio_t *file = (H5FD_mpio_t*)_file;
- int mpi_code; /* MPI return code */
- herr_t ret_value=SUCCEED; /* Return value */
+ H5FD_mpio_t *file = (H5FD_mpio_t*)_file;
+ int mpi_code; /* MPI return code */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
#ifdef H5FDmpio_DEBUG
- if (H5FD_mpio_Debug[(int)'t'])
- fprintf(stdout, "Entering H5FD_mpio_close\n");
+ if(H5FD_mpio_Debug[(int)'t'])
+ HDfprintf(stdout, "%s: Entering\n", FUNC);
#endif
+
+ /* Sanity checks */
HDassert(file);
- HDassert(H5FD_MPIO==file->pub.driver_id);
+ HDassert(H5FD_MPIO == file->pub.driver_id);
/* MPI_File_close sets argument to MPI_FILE_NULL */
- if (MPI_SUCCESS != (mpi_code=MPI_File_close(&(file->f)/*in,out*/)))
+ if(MPI_SUCCESS != (mpi_code = MPI_File_close(&(file->f)/*in,out*/)))
HMPI_GOTO_ERROR(FAIL, "MPI_File_close failed", mpi_code)
/* Clean up other stuff */
- H5FD_mpi_comm_info_free(&file->comm, &file->info);
+ H5_mpi_comm_free(&file->comm);
+ H5_mpi_info_free(&file->info);
H5MM_xfree(file);
done:
#ifdef H5FDmpio_DEBUG
- if (H5FD_mpio_Debug[(int)'t'])
- fprintf(stdout, "Leaving H5FD_mpio_close\n");
+ if(H5FD_mpio_Debug[(int)'t'])
+ HDfprintf(stdout, "%s: Leaving\n", FUNC);
#endif
+
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FD__mpio_close() */
/*-------------------------------------------------------------------------
- * Function: H5FD_mpio_query
+ * Function: H5FD__mpio_query
*
- * Purpose: Set the flags that this VFL driver is capable of supporting.
+ * Purpose: Set the flags that this VFL driver is capable of supporting.
* (listed in H5FDpublic.h)
*
- * Return: Success: non-negative
+ * Return: SUCCEED/FAIL
*
- * Failure: negative
- *
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* Friday, August 25, 2000
*
- * Modifications:
- *
- * John Mainzer -- 9/21/05
- * Modified code to turn off the
- * H5FD_FEAT_ACCUMULATE_METADATA_WRITE flag.
- * With the movement of
- * all cache writes to process 0, this flag has become
- * problematic in PHDF5.
- *
*-------------------------------------------------------------------------
*/
static herr_t
-H5FD_mpio_query(const H5FD_t H5_ATTR_UNUSED *_file, unsigned long *flags /* out */)
+H5FD__mpio_query(const H5FD_t H5_ATTR_UNUSED *_file, unsigned long *flags /* out */)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
/* Set the VFL feature flags that this driver supports */
if(flags) {
- *flags=0;
+ *flags = 0;
*flags |= H5FD_FEAT_AGGREGATE_METADATA; /* OK to aggregate metadata allocations */
*flags |= H5FD_FEAT_AGGREGATE_SMALLDATA; /* OK to aggregate "small" raw data allocations */
*flags |= H5FD_FEAT_HAS_MPI; /* This driver uses MPI */
@@ -1159,145 +971,130 @@ H5FD_mpio_query(const H5FD_t H5_ATTR_UNUSED *_file, unsigned long *flags /* out
} /* end if */
FUNC_LEAVE_NOAPI(SUCCEED)
-}
+} /* end H5FD__mpio_query() */
/*-------------------------------------------------------------------------
- * Function: H5FD_mpio_get_eoa
+ * Function: H5FD__mpio_get_eoa
*
- * Purpose: Gets the end-of-address marker for the file. The EOA marker
- * is the first address past the last byte allocated in the
- * format address space.
+ * Purpose: Gets the end-of-address marker for the file. The EOA marker
+ * is the first address past the last byte allocated in the
+ * format address space.
*
- * Return: Success: The end-of-address marker.
+ * Return: Success: The end-of-address marker
+ * Failure: HADDR_UNDEF
*
- * Failure: HADDR_UNDEF
- *
- * Programmer: Robb Matzke
+ * Programmer: Robb Matzke
* Friday, August 6, 1999
*
- * Modifications:
- * Raymond Lu
- * 21 Dec. 2006
- * Added the parameter TYPE. It's only used for MULTI driver.
- *
*-------------------------------------------------------------------------
*/
static haddr_t
-H5FD_mpio_get_eoa(const H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type)
+H5FD__mpio_get_eoa(const H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type)
{
- const H5FD_mpio_t *file = (const H5FD_mpio_t*)_file;
+ const H5FD_mpio_t *file = (const H5FD_mpio_t*)_file;
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
+ /* Sanity checks */
HDassert(file);
- HDassert(H5FD_MPIO==file->pub.driver_id);
+ HDassert(H5FD_MPIO == file->pub.driver_id);
FUNC_LEAVE_NOAPI(file->eoa)
-}
+} /* end H5FD__mpio_get_eoa() */
/*-------------------------------------------------------------------------
- * Function: H5FD_mpio_set_eoa
+ * Function: H5FD__mpio_set_eoa
*
- * Purpose: Set the end-of-address marker for the file. This function is
- * called shortly after an existing HDF5 file is opened in order
- * to tell the driver where the end of the HDF5 data is located.
+ * Purpose: Set the end-of-address marker for the file. This function is
+ * called shortly after an existing HDF5 file is opened in order
+ * to tell the driver where the end of the HDF5 data is located.
*
- * Return: Success: 0
+ * Return: SUCCEED/FAIL
*
- * Failure: -1
- *
- * Programmer: Robb Matzke
+ * Programmer: Robb Matzke
* Friday, August 6, 1999
*
- * Modifications:
- * Raymond Lu
- * 21 Dec. 2006
- * Added the parameter TYPE. It's only used for MULTI driver.
- *
*-------------------------------------------------------------------------
*/
static herr_t
-H5FD_mpio_set_eoa(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type, haddr_t addr)
+H5FD__mpio_set_eoa(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type, haddr_t addr)
{
- H5FD_mpio_t *file = (H5FD_mpio_t*)_file;
+ H5FD_mpio_t *file = (H5FD_mpio_t*)_file;
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
+ /* Sanity checks */
HDassert(file);
- HDassert(H5FD_MPIO==file->pub.driver_id);
+ HDassert(H5FD_MPIO == file->pub.driver_id);
file->eoa = addr;
FUNC_LEAVE_NOAPI(SUCCEED)
-}
+} /* end H5FD__mpio_set_eoa() */
/*-------------------------------------------------------------------------
- * Function: H5FD_mpio_get_eof
+ * Function: H5FD__mpio_get_eof
*
- * Purpose: Gets the end-of-file marker for the file. The EOF marker
- * is the real size of the file.
+ * Purpose: Gets the end-of-file marker for the file. The EOF marker
+ * is the real size of the file.
*
- * The MPIO driver doesn't bother keeping this field updated
- * since that's a relatively expensive operation. Fortunately
- * the library only needs the EOF just after the file is opened
- * in order to determine whether the file is empty, truncated,
- * or okay. Therefore, any MPIO I/O function will set its value
- * to HADDR_UNDEF which is the error return value of this
- * function.
+ * The MPIO driver doesn't bother keeping this field updated
+ * since that's a relatively expensive operation. Fortunately
+ * the library only needs the EOF just after the file is opened
+ * in order to determine whether the file is empty, truncated,
+ * or okay. Therefore, any MPIO I/O function will set its value
+ * to HADDR_UNDEF which is the error return value of this
+ * function.
*
* Keeping the EOF updated (during write calls) is expensive
* because any process may extend the physical end of the
* file. -QAK
*
- * Return: Success: The end-of-address marker.
- *
- * Failure: HADDR_UNDEF
+ * Return: Success: The end-of-file marker
+ * Failure: HADDR_UNDEF
*
- * Programmer: Robb Matzke
+ * Programmer: Robb Matzke
* Friday, August 6, 1999
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
static haddr_t
-H5FD_mpio_get_eof(const H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type)
+H5FD__mpio_get_eof(const H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type)
{
- const H5FD_mpio_t *file = (const H5FD_mpio_t*)_file;
+ const H5FD_mpio_t *file = (const H5FD_mpio_t*)_file;
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
+ /* Sanity checks */
HDassert(file);
- HDassert(H5FD_MPIO==file->pub.driver_id);
+ HDassert(H5FD_MPIO == file->pub.driver_id);
FUNC_LEAVE_NOAPI(file->eof)
-}
+} /* end H5FD__mpio_get_eof() */
/*-------------------------------------------------------------------------
- * Function: H5FD_mpio_get_handle
+ * Function: H5FD__mpio_get_handle
*
* Purpose: Returns the file handle of MPIO file driver.
*
- * Returns: Non-negative if succeed or negative if fails.
+ * Returns: SUCCEED/FAIL
*
* Programmer: Raymond Lu
* Sept. 16, 2002
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
static herr_t
-H5FD_mpio_get_handle(H5FD_t *_file, hid_t H5_ATTR_UNUSED fapl, void** file_handle)
+H5FD__mpio_get_handle(H5FD_t *_file, hid_t H5_ATTR_UNUSED fapl, void** file_handle)
{
- H5FD_mpio_t *file = (H5FD_mpio_t *)_file;
- herr_t ret_value = SUCCEED;
+ H5FD_mpio_t *file = (H5FD_mpio_t *)_file;
+ herr_t ret_value = SUCCEED;
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
if(!file_handle)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file handle not valid")
@@ -1306,140 +1103,63 @@ H5FD_mpio_get_handle(H5FD_t *_file, hid_t H5_ATTR_UNUSED fapl, void** file_handl
done:
FUNC_LEAVE_NOAPI(ret_value)
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_mpio_get_info
- *
- * Purpose: Returns the file info of MPIO file driver.
- *
- * Returns: Non-negative if succeed or negative if fails.
- *
- * Programmer: John Mainzer
- * April 4, 2017
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
-*/
-static herr_t
-H5FD_mpio_get_info(H5FD_t *_file, void** mpi_info)
-{
- H5FD_mpio_t *file = (H5FD_mpio_t *)_file;
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI_NOINIT
-
- if(!mpi_info)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "mpi info not valid")
-
- *mpi_info = &(file->info);
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-
-} /* H5FD_mpio_get_info() */
+} /* end H5FD__mpio_get_handle() */
/*-------------------------------------------------------------------------
- * Function: H5FD_mpio_read
- *
- * Purpose: Reads SIZE bytes of data from FILE beginning at address ADDR
- * into buffer BUF according to data transfer properties in
- * DXPL_ID using potentially complex file and buffer types to
- * effect the transfer.
- *
- * Reading past the end of the MPI file returns zeros instead of
- * failing. MPI is able to coalesce requests from different
- * processes (collective or independent).
- *
- * Return: Success: Zero. Result is stored in caller-supplied
- * buffer BUF.
- *
- * Failure: -1, Contents of buffer BUF are undefined.
- *
- * Programmer: rky, 1998-01-30
- *
- * Modifications:
- * Robb Matzke, 1998-02-18
- * Added the ACCESS_PARMS argument.
- *
- * rky, 1998-04-10
- * Call independent or collective MPI read, based on
- * ACCESS_PARMS.
- *
- * Albert Cheng, 1998-06-01
- * Added XFER_MODE to control independent or collective MPI
- * read.
- *
- * rky, 1998-08-16
- * Use BTYPE, FTYPE, and DISP from access parms. The guts of
- * H5FD_mpio_read and H5FD_mpio_write should be replaced by a
- * single dual-purpose routine.
+ * Function: H5FD__mpio_read
*
- * Robb Matzke, 1999-04-21
- * Changed XFER_MODE to XFER_PARMS for all H5F_*_read()
- * callbacks.
+ * Purpose: Reads SIZE bytes of data from FILE beginning at address ADDR
+ * into buffer BUF according to data transfer properties in
+ * DXPL_ID using potentially complex file and buffer types to
+ * effect the transfer.
*
- * Robb Matzke, 1999-07-28
- * The ADDR argument is passed by value.
+ * Reading past the end of the MPI file returns zeros instead of
+ * failing. MPI is able to coalesce requests from different
+ * processes (collective or independent).
*
- * Robb Matzke, 1999-08-06
- * Modified to work with the virtual file layer.
+ * Return: Success: SUCCEED. Result is stored in caller-supplied
+ * buffer BUF.
*
- * Quincey Koziol, 2002-05-14
- * Only call MPI_Get_count if we can use MPI_BYTE for the MPI type
- * for the I/O transfer. Someday we might include code to decode
- * the MPI type used for more complicated transfers and call
- * MPI_Get_count all the time.
+ * Failure: FAIL. Contents of buffer BUF are undefined.
*
- * Quincey Koziol - 2002/06/17
- * Removed 'disp' parameter from H5FD_mpio_setup routine and use
- * the address of the dataset in MPI_File_set_view() calls, as
- * necessary.
- *
- * Quincey Koziol - 2002/06/24
- * Removed "lazy" MPI_File_set_view() calls, since they would fail
- * if the first I/O was a collective I/O using MPI derived types
- * and the next I/O was an independent I/O.
- *
- * Quincey Koziol - 2003/10/22-31
- * Restructured code massively, straightening out logic and finally
- * getting the bytes_read stuff working.
+ * Programmer: rky, 1998-01-30
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5FD_mpio_read(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type,
+H5FD__mpio_read(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type,
hid_t H5_ATTR_UNUSED dxpl_id, haddr_t addr, size_t size, void *buf/*out*/)
{
- H5FD_mpio_t *file = (H5FD_mpio_t*)_file;
- MPI_Offset mpi_off;
- MPI_Status mpi_stat; /* Status from I/O operation */
- int mpi_code; /* mpi return code */
- MPI_Datatype buf_type = MPI_BYTE; /* MPI description of the selection in memory */
- int size_i; /* Integer copy of 'size' to read */
+ H5FD_mpio_t *file = (H5FD_mpio_t*)_file;
+ MPI_Offset mpi_off;
+ MPI_Status mpi_stat; /* Status from I/O operation */
+ int mpi_code; /* mpi return code */
+ MPI_Datatype buf_type = MPI_BYTE; /* MPI description of the selection in memory */
+ int size_i; /* Integer copy of 'size' to read */
#if MPI_VERSION >= 3
- MPI_Count bytes_read; /* Number of bytes read in */
- MPI_Count type_size; /* MPI datatype used for I/O's size */
- MPI_Count io_size; /* Actual number of bytes requested */
- MPI_Count n;
+ MPI_Count bytes_read = 0; /* Number of bytes read in */
+ MPI_Count type_size; /* MPI datatype used for I/O's size */
+ MPI_Count io_size; /* Actual number of bytes requested */
+ MPI_Count n;
#else
- int bytes_read; /* Number of bytes read in */
- int type_size; /* MPI datatype used for I/O's size */
- int io_size; /* Actual number of bytes requested */
- int n;
+ int bytes_read = 0; /* Number of bytes read in */
+ int type_size; /* MPI datatype used for I/O's size */
+ int io_size; /* Actual number of bytes requested */
+ int n;
#endif
- hbool_t use_view_this_time = FALSE;
- herr_t ret_value = SUCCEED;
+ hbool_t use_view_this_time = FALSE;
+ hbool_t rank0_bcast = FALSE; /* If read-with-rank0-and-bcast flag was used */
+ herr_t ret_value = SUCCEED;
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
#ifdef H5FDmpio_DEBUG
- if (H5FD_mpio_Debug[(int)'t'])
- fprintf(stdout, "Entering H5FD_mpio_read\n" );
+ if(H5FD_mpio_Debug[(int)'t'])
+ HDfprintf(stdout, "%s: Entering\n", FUNC);
#endif
+
+ /* Sanity checks */
HDassert(file);
HDassert(H5FD_MPIO==file->pub.driver_id);
HDassert(buf);
@@ -1448,21 +1168,20 @@ H5FD_mpio_read(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type,
HDmemset(&mpi_stat,0,sizeof(MPI_Status));
/* some numeric conversions */
- if (H5FD_mpi_haddr_to_MPIOff(addr, &mpi_off/*out*/)<0)
+ if(H5FD_mpi_haddr_to_MPIOff(addr, &mpi_off/*out*/) < 0)
HGOTO_ERROR(H5E_INTERNAL, H5E_BADRANGE, FAIL, "can't convert from haddr to MPI off")
size_i = (int)size;
- if ((hsize_t)size_i != size)
+ if((hsize_t)size_i != size)
HGOTO_ERROR(H5E_INTERNAL, H5E_BADRANGE, FAIL, "can't convert from size to size_i")
#ifdef H5FDmpio_DEBUG
- if (H5FD_mpio_Debug[(int)'r'])
- fprintf(stdout, "in H5FD_mpio_read mpi_off=%ld size_i=%d\n",
- (long)mpi_off, size_i );
+ if(H5FD_mpio_Debug[(int)'r'])
+ HDfprintf(stdout, "%s: mpi_off = %ld size_i = %d\n", FUNC, (long)mpi_off, size_i);
#endif
/* Only look for MPI views for raw data transfers */
if(type == H5FD_MEM_DRAW) {
- H5FD_mpio_xfer_t xfer_mode; /* I/O transfer mode */
+ H5FD_mpio_xfer_t xfer_mode; /* I/O transfer mode */
/* Get the transfer mode from the API context */
if(H5CX_get_io_xfer_mode(&xfer_mode) < 0)
@@ -1474,8 +1193,8 @@ H5FD_mpio_read(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type,
* us to test that btype=ftype=MPI_BYTE (or even MPI_TYPE_NULL, which
* could mean "use MPI_BYTE" by convention).
*/
- if(xfer_mode==H5FD_MPIO_COLLECTIVE) {
- MPI_Datatype file_type;
+ if(xfer_mode == H5FD_MPIO_COLLECTIVE) {
+ MPI_Datatype file_type;
/* Remember that views are used */
use_view_this_time = TRUE;
@@ -1502,8 +1221,8 @@ H5FD_mpio_read(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type,
H5FD_mpio_collective_opt_t coll_opt_mode;
#ifdef H5FDmpio_DEBUG
- if (H5FD_mpio_Debug[(int)'t'])
- fprintf(stdout, "H5FD_mpio_read: using MPIO collective mode\n");
+ if(H5FD_mpio_Debug[(int)'r'])
+ HDfprintf(stdout, "%s: using MPIO collective mode\n", FUNC);
#endif
/* 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)
@@ -1511,16 +1230,33 @@ H5FD_mpio_read(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type,
if(coll_opt_mode == H5FD_MPIO_COLLECTIVE_IO) {
#ifdef H5FDmpio_DEBUG
- if(H5FD_mpio_Debug[(int)'t'])
- fprintf(stdout, "H5FD_mpio_read: doing MPI collective IO\n");
+ if(H5FD_mpio_Debug[(int)'r'])
+ HDfprintf(stdout, "%s: doing MPI collective IO\n", FUNC);
+#endif
+ /* Check whether we should read from rank 0 and broadcast to other ranks */
+ if(H5CX_get_mpio_rank0_bcast()) {
+#ifdef H5FDmpio_DEBUG
+ if(H5FD_mpio_Debug[(int)'r'])
+ HDfprintf(stdout, "%s: doing read-rank0-and-MPI_Bcast\n", FUNC);
#endif
- if(MPI_SUCCESS != (mpi_code = MPI_File_read_at_all(file->f, mpi_off, buf, size_i, buf_type, &mpi_stat)))
- HMPI_GOTO_ERROR(FAIL, "MPI_File_read_at_all failed", mpi_code)
+ /* Indicate path we've taken */
+ rank0_bcast = TRUE;
+
+ /* Read on rank 0 Bcast to other ranks */
+ if(file->mpi_rank == 0)
+ if(MPI_SUCCESS != (mpi_code = MPI_File_read_at(file->f, mpi_off, buf, size_i, buf_type, &mpi_stat)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_File_read_at failed", mpi_code)
+ if(MPI_SUCCESS != (mpi_code = MPI_Bcast(buf, size_i, buf_type, 0, file->comm)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Bcast failed", mpi_code)
+ } /* end if */
+ else
+ if(MPI_SUCCESS != (mpi_code = MPI_File_read_at_all(file->f, mpi_off, buf, size_i, buf_type, &mpi_stat)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_File_read_at_all failed", mpi_code)
} /* end if */
else {
#ifdef H5FDmpio_DEBUG
- if(H5FD_mpio_Debug[(int)'t'])
- fprintf(stdout, "H5FD_mpio_read: doing MPI independent IO\n");
+ if(H5FD_mpio_Debug[(int)'r'])
+ HDfprintf(stdout, "%s: doing MPI independent IO\n", FUNC);
#endif
if(MPI_SUCCESS != (mpi_code = MPI_File_read_at(file->f, mpi_off, buf, size_i, buf_type, &mpi_stat)))
@@ -1532,182 +1268,96 @@ H5FD_mpio_read(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type,
*/
if(MPI_SUCCESS != (mpi_code = MPI_File_set_view(file->f, (MPI_Offset)0, MPI_BYTE, MPI_BYTE, H5FD_mpi_native_g, file->info)))
HMPI_GOTO_ERROR(FAIL, "MPI_File_set_view failed", mpi_code)
- } else {
+ } /* end if */
+ else
if(MPI_SUCCESS != (mpi_code = MPI_File_read_at(file->f, mpi_off, buf, size_i, buf_type, &mpi_stat)))
HMPI_GOTO_ERROR(FAIL, "MPI_File_read_at failed", mpi_code)
- }
- /* How many bytes were actually read? */
+ /* Only retrieve bytes read if this rank _actually_ participated in I/O */
+ if(!rank0_bcast || (rank0_bcast && file->mpi_rank == 0) ) {
+ /* How many bytes were actually read? */
#if MPI_VERSION >= 3
- if (MPI_SUCCESS != (mpi_code = MPI_Get_elements_x(&mpi_stat, buf_type, &bytes_read)))
+ if(MPI_SUCCESS != (mpi_code = MPI_Get_elements_x(&mpi_stat, buf_type, &bytes_read)))
#else
- if (MPI_SUCCESS != (mpi_code = MPI_Get_elements(&mpi_stat, MPI_BYTE, &bytes_read)))
+ if(MPI_SUCCESS != (mpi_code = MPI_Get_elements(&mpi_stat, MPI_BYTE, &bytes_read)))
#endif
- HMPI_GOTO_ERROR(FAIL, "MPI_Get_elements failed", mpi_code)
+ HMPI_GOTO_ERROR(FAIL, "MPI_Get_elements failed", mpi_code)
+ } /* end if */
+
+ /* If the rank0-bcast feature was used, broadcast the # of bytes read to
+ * other ranks, which didn't perform any I/O.
+ */
+ /* NOTE: This could be optimized further to be combined with the broadcast
+ * of the data. (QAK - 2019/1/2)
+ */
+ if(rank0_bcast)
+ if(MPI_SUCCESS != MPI_Bcast(&bytes_read, 1, MPI_LONG_LONG, 0, file->comm))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Bcast failed", 0)
/* Get the type's size */
#if MPI_VERSION >= 3
- if (MPI_SUCCESS != (mpi_code = MPI_Type_size_x(buf_type, &type_size)))
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_size_x(buf_type, &type_size)))
#else
- if (MPI_SUCCESS != (mpi_code = MPI_Type_size(buf_type, &type_size)))
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_size(buf_type, &type_size)))
#endif
HMPI_GOTO_ERROR(FAIL, "MPI_Type_size failed", mpi_code)
/* Compute the actual number of bytes requested */
- io_size=type_size*size_i;
+ io_size = type_size * size_i;
/* Check for read failure */
- if (bytes_read<0 || bytes_read>io_size)
+ if(bytes_read < 0 || bytes_read > io_size)
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file read failed")
/*
* This gives us zeroes beyond end of physical MPI file.
*/
- if ((n=(io_size-bytes_read)) > 0)
+ if((n = (io_size - bytes_read)) > 0)
HDmemset((char*)buf+bytes_read, 0, (size_t)n);
done:
#ifdef H5FDmpio_DEBUG
- if (H5FD_mpio_Debug[(int)'t'])
- fprintf(stdout, "Leaving H5FD_mpio_read\n" );
+ if(H5FD_mpio_Debug[(int)'t'])
+ HDfprintf(stdout, "%s: Leaving\n", FUNC);
#endif
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FD__mpio_read() */
+
/*-------------------------------------------------------------------------
- * Function: H5FD_mpio_write
+ * Function: H5FD__mpio_write
*
- * Purpose: Writes SIZE bytes of data to FILE beginning at address ADDR
- * from buffer BUF according to data transfer properties in
- * DXPL_ID using potentially complex file and buffer types to
- * effect the transfer.
+ * Purpose: Writes SIZE bytes of data to FILE beginning at address ADDR
+ * from buffer BUF according to data transfer properties in
+ * DXPL_ID using potentially complex file and buffer types to
+ * effect the transfer.
*
- * MPI is able to coalesce requests from different processes
- * (collective and independent).
+ * MPI is able to coalesce requests from different processes
+ * (collective and independent).
*
- * Return: Success: Zero. USE_TYPES and OLD_USE_TYPES in the
- * access params are altered.
+ * Return: Success: SUCCEED. USE_TYPES and OLD_USE_TYPES in the
+ * access params are altered.
+ * Failure: FAIL. USE_TYPES and OLD_USE_TYPES in the
+ * access params may be altered.
*
- * Failure: -1, USE_TYPES and OLD_USE_TYPES in the
- * access params may be altered.
- *
- * Programmer: Unknown
+ * Programmer: Robert Kim Yates
* January 30, 1998
*
- * Modifications:
- * rky, 1998-08-28
- * If the file->allsame flag is set, we assume that all the
- * procs in the relevant MPI communicator will write identical
- * data at identical offsets in the file, so only proc 0 will
- * write, and all other procs will wait for p0 to finish. This
- * is useful for writing metadata, for example. Note that we
- * don't _check_ that the data is identical. Also, the mechanism
- * we use to eliminate the redundant writes is by requiring a
- * call to H5FD_mpio_tas_allsame before the write, which is
- * rather klugey. Would it be better to pass a parameter to
- * low-level writes like H5F_block_write and H5F_low_write,
- * instead? Or...??? Also, when I created this mechanism I
- * wanted to minimize the difference in behavior between the old
- * way of doing things (i.e., all procs write) and the new way,
- * so the writes are eliminated at the very lowest level, here
- * in H5FD_mpio_write. It may be better to rethink that, and
- * short-circuit the writes at a higher level (e.g., at the
- * points in the code where H5FD_mpio_tas_allsame is called).
- *
- *
- * Robb Matzke, 1998-02-18
- * Added the ACCESS_PARMS argument.
- *
- * rky, 1998-04-10
- * Call independent or collective MPI write, based on
- * ACCESS_PARMS.
- *
- * rky, 1998-04-24
- * Removed redundant write from H5FD_mpio_write.
- *
- * Albert Cheng, 1998-06-01
- * Added XFER_MODE to control independent or collective MPI
- * write.
- *
- * rky, 1998-08-16
- * Use BTYPE, FTYPE, and DISP from access parms. The guts of
- * H5FD_mpio_read and H5FD_mpio_write should be replaced by a
- * single dual-purpose routine.
- *
- * rky, 1998-08-28
- * Added ALLSAME parameter to make all but proc 0 skip the
- * actual write.
- *
- * Robb Matzke, 1999-04-21
- * Changed XFER_MODE to XFER_PARMS for all H5FD_*_write()
- * callbacks.
- *
- * Robb Matzke, 1999-07-28
- * The ADDR argument is passed by value.
- *
- * Robb Matzke, 1999-08-06
- * Modified to work with the virtual file layer.
- *
- * Albert Cheng, 1999-12-19
- * When only-p0-write-allsame-data, p0 Bcasts the
- * ret_value to other processes. This prevents
- * a racing condition (that other processes try to
- * read the file before p0 finishes writing) and also
- * allows all processes to report the same ret_value.
- *
- * Kim Yates, Pat Weidhaas, 2000-09-26
- * Move block of coding where only p0 writes after the
- * MPI_File_set_view call.
- *
- * Quincey Koziol, 2002-05-10
- * Instead of always writing metadata from process 0, spread the
- * burden among all the processes by using a round-robin rotation
- * scheme.
- *
- * Quincey Koziol, 2002-05-10
- * Removed allsame code, keying off the type parameter instead.
- *
- * Quincey Koziol, 2002-05-14
- * Only call MPI_Get_count if we can use MPI_BYTE for the MPI type
- * for the I/O transfer. Someday we might include code to decode
- * the MPI type used for more complicated transfers and call
- * MPI_Get_count all the time.
- *
- * Quincey Koziol - 2002/06/17
- * Removed 'disp' parameter from H5FD_mpio_setup routine and use
- * the address of the dataset in MPI_File_set_view() calls, as
- * necessary.
- *
- * Quincey Koziol - 2002/06/24
- * Removed "lazy" MPI_File_set_view() calls, since they would fail
- * if the first I/O was a collective I/O using MPI derived types
- * and the next I/O was an independent I/O.
- *
- * Quincey Koziol - 2002/07/18
- * Added "block_before_meta_write" dataset transfer flag, which
- * is set during writes from a metadata cache flush and indicates
- * that all the processes must sync up before (one of them)
- * writing metadata.
- *
- * Quincey Koziol - 2003/10/22-31
- * Restructured code massively, straightening out logic and finally
- * getting the bytes_written stuff working.
- *
*-------------------------------------------------------------------------
*/
static herr_t
-H5FD_mpio_write(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id,
+H5FD__mpio_write(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id,
haddr_t addr, size_t size, const void *buf)
{
- H5FD_mpio_t *file = (H5FD_mpio_t*)_file;
- MPI_Offset mpi_off;
- MPI_Status mpi_stat; /* Status from I/O operation */
- MPI_Datatype buf_type = MPI_BYTE; /* MPI description of the selection in memory */
- int mpi_code; /* MPI return code */
+ H5FD_mpio_t *file = (H5FD_mpio_t*)_file;
+ MPI_Offset mpi_off;
+ MPI_Status mpi_stat; /* Status from I/O operation */
+ MPI_Datatype buf_type = MPI_BYTE; /* MPI description of the selection in memory */
+ int mpi_code; /* MPI return code */
#if MPI_VERSION >= 3
- MPI_Count bytes_written;
+ MPI_Count bytes_written;
MPI_Count type_size; /* MPI datatype used for I/O's size */
MPI_Count io_size; /* Actual number of bytes requested */
#else
@@ -1716,16 +1366,19 @@ H5FD_mpio_write(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id,
int io_size; /* Actual number of bytes requested */
#endif
int size_i;
- hbool_t use_view_this_time = FALSE;
+ hbool_t use_view_this_time = FALSE;
+ hbool_t derived_type = FALSE;
H5FD_mpio_xfer_t xfer_mode; /* I/O transfer mode */
- herr_t ret_value = SUCCEED;
+ herr_t ret_value = SUCCEED;
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
#ifdef H5FDmpio_DEBUG
- if (H5FD_mpio_Debug[(int)'t'])
- fprintf(stdout, "Entering H5FD_mpio_write\n" );
+ if(H5FD_mpio_Debug[(int)'t'])
+ HDfprintf(stdout, "%s: Entering\n", FUNC);
#endif
+
+ /* Sanity checks */
HDassert(file);
HDassert(H5FD_MPIO==file->pub.driver_id);
HDassert(buf);
@@ -1740,12 +1393,10 @@ H5FD_mpio_write(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id,
if(H5FD_mpi_haddr_to_MPIOff(addr, &mpi_off) < 0)
HGOTO_ERROR(H5E_INTERNAL, H5E_BADRANGE, FAIL, "can't convert from haddr to MPI off")
size_i = (int)size;
- if((hsize_t)size_i != size)
- HGOTO_ERROR(H5E_INTERNAL, H5E_BADRANGE, FAIL, "can't convert from size to size_i")
#ifdef H5FDmpio_DEBUG
if(H5FD_mpio_Debug[(int)'w'])
- fprintf(stdout, "in H5FD_mpio_write mpi_off=%ld size_i=%d\n", (long)mpi_off, size_i);
+ HDfprintf(stdout, "%s: mpi_off = %ld size_i = %d\n", FUNC, (long)mpi_off, size_i);
#endif
/* Get the transfer mode from the API context */
@@ -1759,7 +1410,7 @@ H5FD_mpio_write(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id,
* could mean "use MPI_BYTE" by convention).
*/
if(xfer_mode == H5FD_MPIO_COLLECTIVE) {
- MPI_Datatype file_type;
+ MPI_Datatype file_type;
/* Remember that views are used */
use_view_this_time = TRUE;
@@ -1779,14 +1430,28 @@ H5FD_mpio_write(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id,
*/
mpi_off = 0;
} /* end if */
+ else if(size != (hsize_t)size_i) {
+ /* If HERE, then we need to work around the integer size limit
+ * of 2GB. The input size_t size variable cannot fit into an integer,
+ * but we can get around that limitation by creating a different datatype
+ * and then setting the integer size (or element count) to 1 when using
+ * the derived_type.
+ */
+
+ if (H5_mpio_create_large_type(size, 0, MPI_BYTE, &buf_type) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, FAIL, "can't create MPI-I/O datatype")
+
+ derived_type = TRUE;
+ size_i = 1;
+ }
/* Write the data. */
if(use_view_this_time) {
H5FD_mpio_collective_opt_t coll_opt_mode;
#ifdef H5FDmpio_DEBUG
- if(H5FD_mpio_Debug[(int)'t'])
- fprintf(stdout, "H5FD_mpio_write: using MPIO collective mode\n");
+ if(H5FD_mpio_Debug[(int)'w'])
+ HDfprintf(stdout, "%s: using MPIO collective mode\n", FUNC);
#endif
/* Get the collective_opt property to check whether the application wants to do IO individually. */
@@ -1795,8 +1460,8 @@ H5FD_mpio_write(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id,
if(coll_opt_mode == H5FD_MPIO_COLLECTIVE_IO) {
#ifdef H5FDmpio_DEBUG
- if(H5FD_mpio_Debug[(int)'t'])
- fprintf(stdout, "H5FD_mpio_write: doing MPI collective IO\n");
+ if(H5FD_mpio_Debug[(int)'w'])
+ HDfprintf(stdout, "%s: doing MPI collective IO\n", FUNC);
#endif
if(MPI_SUCCESS != (mpi_code = MPI_File_write_at_all(file->f, mpi_off, buf, size_i, buf_type, &mpi_stat)))
HMPI_GOTO_ERROR(FAIL, "MPI_File_write_at_all failed", mpi_code)
@@ -1805,8 +1470,8 @@ H5FD_mpio_write(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id,
if(type != H5FD_MEM_DRAW)
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "Metadata Coll opt property should be collective at this point")
#ifdef H5FDmpio_DEBUG
- if(H5FD_mpio_Debug[(int)'t'])
- fprintf(stdout, "H5FD_mpio_write: doing MPI independent IO\n");
+ if(H5FD_mpio_Debug[(int)'w'])
+ HDfprintf(stdout, "%s: doing MPI independent IO\n", FUNC);
#endif
if(MPI_SUCCESS != (mpi_code = MPI_File_write_at(file->f, mpi_off, buf, size_i, buf_type, &mpi_stat)))
HMPI_GOTO_ERROR(FAIL, "MPI_File_write_at failed", mpi_code)
@@ -1815,10 +1480,10 @@ H5FD_mpio_write(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id,
/* Reset the file view when we used MPI derived types */
if(MPI_SUCCESS != (mpi_code = MPI_File_set_view(file->f, (MPI_Offset)0, MPI_BYTE, MPI_BYTE, H5FD_mpi_native_g, file->info)))
HMPI_GOTO_ERROR(FAIL, "MPI_File_set_view failed", mpi_code)
- } else {
+ } /* end if */
+ else
if(MPI_SUCCESS != (mpi_code = MPI_File_write_at(file->f, mpi_off, buf, size_i, buf_type, &mpi_stat)))
HMPI_GOTO_ERROR(FAIL, "MPI_File_write_at failed", mpi_code)
- }
/* How many bytes were actually written? */
#if MPI_VERSION >= 3
@@ -1840,7 +1505,7 @@ H5FD_mpio_write(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id,
io_size = type_size * size_i;
/* Check for write failure */
- if(bytes_written != io_size)
+ if(bytes_written != io_size || bytes_written < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed")
/* Each process will keep track of its perceived EOF value locally, and
@@ -1851,27 +1516,28 @@ H5FD_mpio_write(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id,
* potentially be wrong.) */
file->eof = HADDR_UNDEF;
- if(bytes_written && ((bytes_written + addr) > file->local_eof))
- file->local_eof = addr + bytes_written;
+ if(bytes_written && (((haddr_t)bytes_written + addr) > file->local_eof))
+ file->local_eof = addr + (haddr_t)bytes_written;
done:
+ if(derived_type) {
+ MPI_Type_free(&buf_type);
+ }
#ifdef H5FDmpio_DEBUG
if(H5FD_mpio_Debug[(int)'t'])
- fprintf(stdout, "proc %d: Leaving H5FD_mpio_write with ret_value=%d\n",
- file->mpi_rank, ret_value );
+ HDfprintf(stdout, "%s: Leaving, proc %d: ret_value = %d\n", FUNC, file->mpi_rank, ret_value );
#endif
+
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FD_mpio_write() */
+} /* end H5FD__mpio_write() */
/*-------------------------------------------------------------------------
- * Function: H5FD_mpio_flush
+ * Function: H5FD__mpio_flush
*
* Purpose: Makes sure that all data is on disk. This is collective.
*
- * Return: Success: Non-negative
- *
- * Failure: Negative
+ * Return: SUCCEED/FAIL
*
* Programmer: Robb Matzke
* January 30, 1998
@@ -1879,18 +1545,20 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5FD_mpio_flush(H5FD_t *_file, hid_t H5_ATTR_UNUSED dxpl_id, hbool_t closing)
+H5FD__mpio_flush(H5FD_t *_file, hid_t H5_ATTR_UNUSED dxpl_id, hbool_t closing)
{
- H5FD_mpio_t *file = (H5FD_mpio_t*)_file;
- int mpi_code; /* mpi return code */
- herr_t ret_value = SUCCEED;
+ H5FD_mpio_t *file = (H5FD_mpio_t*)_file;
+ int mpi_code; /* mpi return code */
+ herr_t ret_value = SUCCEED;
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
#ifdef H5FDmpio_DEBUG
if(H5FD_mpio_Debug[(int)'t'])
- HDfprintf(stdout, "Entering %s\n", FUNC);
+ HDfprintf(stdout, "%s: Entering\n", FUNC);
#endif
+
+ /* Sanity checks */
HDassert(file);
HDassert(H5FD_MPIO == file->pub.driver_id);
@@ -1902,15 +1570,15 @@ H5FD_mpio_flush(H5FD_t *_file, hid_t H5_ATTR_UNUSED dxpl_id, hbool_t closing)
done:
#ifdef H5FDmpio_DEBUG
if(H5FD_mpio_Debug[(int)'t'])
- HDfprintf(stdout, "Leaving %s\n", FUNC);
+ HDfprintf(stdout, "%s: Leaving\n", FUNC);
#endif
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FD_mpio_flush() */
+} /* end H5FD__mpio_flush() */
/*-------------------------------------------------------------------------
- * Function: H5FD_mpio_truncate
+ * Function: H5FD__mpio_truncate
*
* Purpose: Make certain the file's size matches it's allocated size
*
@@ -1924,37 +1592,27 @@ done:
* only call MPI_File_set_size() if this value disagrees
* with the current eoa.
*
- * Return: Success: Non-negative
- * Failure: Negative
+ * Return: SUCCEED/FAIL
*
* Programmer: Quincey Koziol
* January 31, 2008
*
- * Changes: Heavily reworked to avoid unnecessary MPI_File_set_size()
- * calls. The hope is that these calls are superfluous in the
- * typical case, allowing us to avoid truncates most of the
- * time.
- *
- * The basic idea is to query the file system to get the
- * current eof, and only truncate if the file systems
- * conception of the eof disagrees with our eoa.
- *
- * JRM -- 10/27/17
- *
*-------------------------------------------------------------------------
*/
static herr_t
-H5FD_mpio_truncate(H5FD_t *_file, hid_t H5_ATTR_UNUSED dxpl_id, hbool_t H5_ATTR_UNUSED closing)
+H5FD__mpio_truncate(H5FD_t *_file, hid_t H5_ATTR_UNUSED dxpl_id, hbool_t H5_ATTR_UNUSED closing)
{
- H5FD_mpio_t *file = (H5FD_mpio_t*)_file;
- herr_t ret_value = SUCCEED;
+ H5FD_mpio_t *file = (H5FD_mpio_t*)_file;
+ herr_t ret_value = SUCCEED;
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
#ifdef H5FDmpio_DEBUG
if(H5FD_mpio_Debug[(int)'t'])
- HDfprintf(stdout, "Entering %s\n", FUNC);
+ HDfprintf(stdout, "%s: Entering\n", FUNC);
#endif
+
+ /* Sanity checks */
HDassert(file);
HDassert(H5FD_MPIO == file->pub.driver_id);
@@ -2020,99 +1678,125 @@ H5FD_mpio_truncate(H5FD_t *_file, hid_t H5_ATTR_UNUSED dxpl_id, hbool_t H5_ATTR_
done:
#ifdef H5FDmpio_DEBUG
if(H5FD_mpio_Debug[(int)'t'])
- HDfprintf(stdout, "Leaving %s\n", FUNC);
+ HDfprintf(stdout, "%s: Leaving\n", FUNC);
#endif
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FD_mpio_truncate() */
+} /* end H5FD__mpio_truncate() */
/*-------------------------------------------------------------------------
- * Function: H5FD_mpio_mpi_rank
+ * Function: H5FD__mpio_mpi_rank
*
- * Purpose: Returns the MPI rank for a process
+ * Purpose: Returns the MPI rank for a process
*
- * Return: Success: non-negative
- * Failure: negative
+ * Return: Success: non-negative
+ * Failure: negative
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* Thursday, May 16, 2002
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
static int
-H5FD_mpio_mpi_rank(const H5FD_t *_file)
+H5FD__mpio_mpi_rank(const H5FD_t *_file)
{
- const H5FD_mpio_t *file = (const H5FD_mpio_t*)_file;
+ const H5FD_mpio_t *file = (const H5FD_mpio_t*)_file;
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
+ /* Sanity checks */
HDassert(file);
- HDassert(H5FD_MPIO==file->pub.driver_id);
+ HDassert(H5FD_MPIO == file->pub.driver_id);
FUNC_LEAVE_NOAPI(file->mpi_rank)
-} /* end H5FD_mpio_mpi_rank() */
+} /* end H5FD__mpio_mpi_rank() */
/*-------------------------------------------------------------------------
- * Function: H5FD_mpio_mpi_size
+ * Function: H5FD__mpio_mpi_size
*
- * Purpose: Returns the number of MPI processes
+ * Purpose: Returns the number of MPI processes
*
- * Return: Success: non-negative
- * Failure: negative
+ * Return: Success: non-negative
+ * Failure: negative
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* Thursday, May 16, 2002
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
static int
-H5FD_mpio_mpi_size(const H5FD_t *_file)
+H5FD__mpio_mpi_size(const H5FD_t *_file)
{
- const H5FD_mpio_t *file = (const H5FD_mpio_t*)_file;
+ const H5FD_mpio_t *file = (const H5FD_mpio_t*)_file;
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
+ /* Sanity checks */
HDassert(file);
- HDassert(H5FD_MPIO==file->pub.driver_id);
+ HDassert(H5FD_MPIO == file->pub.driver_id);
FUNC_LEAVE_NOAPI(file->mpi_size)
-} /* end H5FD_mpio_mpi_size() */
+} /* end H5FD__mpio_mpi_size() */
/*-------------------------------------------------------------------------
- * Function: H5FD_mpio_communicator
- *
- * Purpose: Returns the MPI communicator for the file.
+ * Function: H5FD__mpio_communicator
*
- * Return: Success: The communicator
+ * Purpose: Returns the MPI communicator for the file.
*
- * Failure: NULL
+ * Return: Success: The communicator
+ * Failure: Can't fail
*
- * Programmer: Robb Matzke
+ * Programmer: Robb Matzke
* Monday, August 9, 1999
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
static MPI_Comm
-H5FD_mpio_communicator(const H5FD_t *_file)
+H5FD__mpio_communicator(const H5FD_t *_file)
{
- const H5FD_mpio_t *file = (const H5FD_mpio_t*)_file;
+ const H5FD_mpio_t *file = (const H5FD_mpio_t*)_file;
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
+ /* Sanity checks */
HDassert(file);
- HDassert(H5FD_MPIO==file->pub.driver_id);
+ HDassert(H5FD_MPIO == file->pub.driver_id);
FUNC_LEAVE_NOAPI(file->comm)
-} /* end H5FD_mpio_communicator() */
+} /* end H5FD__mpio_communicator() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD__mpio_get_info
+ *
+ * Purpose: Returns the file info of MPIO file driver.
+ *
+ * Returns: Non-negative if succeed or negative if fails.
+ *
+ * Programmer: John Mainzer
+ * April 4, 2017
+ *
+ *-------------------------------------------------------------------------
+*/
+static herr_t
+H5FD__mpio_get_info(H5FD_t *_file, void **mpi_info)
+{
+ H5FD_mpio_t *file = (H5FD_mpio_t *)_file;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ if(!mpi_info)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "mpi info not valid")
+
+ *mpi_info = &(file->info);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5FD__mpio_get_info() */
#endif /* H5_HAVE_PARALLEL */
diff --git a/src/H5FDmulti.c b/src/H5FDmulti.c
index aa1b118..800869d 100644
--- a/src/H5FDmulti.c
+++ b/src/H5FDmulti.c
@@ -26,11 +26,6 @@
#include <stdlib.h>
#include <string.h>
-/* Disable certain warnings in PC-Lint: */
-/*lint --emacro( {534, 830}, H5P_DEFAULT, H5P_FILE_ACCESS, H5P_DATASET_XFER) */
-/*lint --emacro( {534, 830}, H5FD_MULTI) */
-/*lint -esym( 534, H5Eclear2, H5Epush2) */
-
#include "hdf5.h"
@@ -211,16 +206,15 @@ my_strdup(const char *s)
/*-------------------------------------------------------------------------
- * Function: H5FD_multi_init
- *
- * Purpose: Initialize this driver by registering the driver with the
- * library.
+ * Function: H5FD_multi_init
*
- * Return: Success: The driver ID for the multi driver.
+ * Purpose: Initialize this driver by registering the driver with the
+ * library.
*
- * Failure: Negative
+ * Return: Success: The driver ID for the multi driver
+ * Failure: H5I_INVALID_HID
*
- * Programmer: Robb Matzke
+ * Programmer: Robb Matzke
* Wednesday, August 4, 1999
*
*-------------------------------------------------------------------------
@@ -231,11 +225,11 @@ H5FD_multi_init(void)
/* Clear the error stack */
H5Eclear2(H5E_DEFAULT);
- if(H5I_VFL!=H5Iget_type(H5FD_MULTI_g))
+ if(H5I_VFL != H5Iget_type(H5FD_MULTI_g))
H5FD_MULTI_g = H5FDregister(&H5FD_multi_g);
return H5FD_MULTI_g;
-}
+} /* end H5FD_multi_init() */
/*---------------------------------------------------------------------------
@@ -497,6 +491,7 @@ H5Pset_fapl_multi(hid_t fapl_id, const H5FD_mem_t *memb_map,
* Initialize driver specific information. No need to copy it into the FA
* struct since all members will be copied by H5Pset_driver().
*/
+ memset(&fa, 0, sizeof(H5FD_multi_fapl_t));
memcpy(fa.memb_map, memb_map, H5FD_MEM_NTYPES*sizeof(H5FD_mem_t));
memcpy(fa.memb_fapl, memb_fapl, H5FD_MEM_NTYPES*sizeof(hid_t));
memcpy(fa.memb_name, memb_name, H5FD_MEM_NTYPES*sizeof(char*));
@@ -776,7 +771,7 @@ H5FD_multi_sb_decode(H5FD_t *_file, const char *name, const unsigned char *buf)
buf += nseen*2*8;
if (H5Tconvert(H5T_STD_U64LE, H5T_NATIVE_HADDR, nseen*2, x, NULL, H5P_DEFAULT)<0)
H5Epush_ret(func, H5E_ERR_CLS, H5E_DATATYPE, H5E_CANTCONVERT, "can't convert superblock info", -1)
- ap = (haddr_t*)x;
+ ap = (haddr_t*)((void *)x); /* Extra (void *) cast to quiet "cast to create alignment" warning - 2019/07/05, QAK */
UNIQUE_MEMBERS(map, mt) {
memb_addr[_unmapped] = *ap++;
memb_eoa[_unmapped] = *ap++;
@@ -892,7 +887,7 @@ static void *
H5FD_multi_fapl_copy(const void *_old_fa)
{
const H5FD_multi_fapl_t *old_fa = (const H5FD_multi_fapl_t*)_old_fa;
- H5FD_multi_fapl_t *new_fa = (H5FD_multi_fapl_t *)malloc(sizeof(H5FD_multi_fapl_t));
+ H5FD_multi_fapl_t *new_fa = (H5FD_multi_fapl_t *)calloc(1, sizeof(H5FD_multi_fapl_t));
int nerrors = 0;
static const char *func="H5FD_multi_fapl_copy"; /* Function Name for error reporting */
@@ -986,8 +981,7 @@ H5FD_multi_fapl_free(void *_fa)
*-------------------------------------------------------------------------
*/
static H5FD_t *
-H5FD_multi_open(const char *name, unsigned flags, hid_t fapl_id,
- haddr_t maxaddr)
+H5FD_multi_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr)
{
H5FD_multi_t *file=NULL;
hid_t close_fapl=-1;
@@ -1001,7 +995,7 @@ H5FD_multi_open(const char *name, unsigned flags, hid_t fapl_id,
/* Check arguments */
if (!name || !*name)
H5Epush_ret(func, H5E_ERR_CLS, H5E_ARGS, H5E_BADVALUE, "invalid file name", NULL)
- if (0==maxaddr || HADDR_UNDEF==maxaddr)
+ if (0 == maxaddr || HADDR_UNDEF == maxaddr)
H5Epush_ret(func, H5E_ERR_CLS, H5E_ARGS, H5E_BADRANGE, "bogus maxaddr", NULL)
/*
@@ -1012,41 +1006,41 @@ H5FD_multi_open(const char *name, unsigned flags, hid_t fapl_id,
*/
if(NULL == (file = (H5FD_multi_t *)calloc((size_t)1, sizeof(H5FD_multi_t))))
H5Epush_ret(func, H5E_ERR_CLS, H5E_RESOURCE, H5E_NOSPACE, "memory allocation failed", NULL)
- if(H5P_FILE_ACCESS_DEFAULT==fapl_id || H5FD_MULTI!=H5Pget_driver(fapl_id)) {
+ if(H5P_FILE_ACCESS_DEFAULT == fapl_id || H5FD_MULTI != H5Pget_driver(fapl_id)) {
close_fapl = fapl_id = H5Pcreate(H5P_FILE_ACCESS);
- if(H5Pset_fapl_multi(fapl_id, NULL, NULL, NULL, NULL, TRUE)<0)
+ if(H5Pset_fapl_multi(fapl_id, NULL, NULL, NULL, NULL, TRUE) < 0)
H5Epush_goto(func, H5E_ERR_CLS, H5E_FILE, H5E_CANTSET, "can't set property value", error)
}
fa = (const H5FD_multi_fapl_t *)H5Pget_driver_info(fapl_id);
assert(fa);
ALL_MEMBERS(mt) {
- file->fa.memb_map[mt] = fa->memb_map[mt];
- file->fa.memb_addr[mt] = fa->memb_addr[mt];
- if (fa->memb_fapl[mt]>=0)
- H5Iinc_ref(fa->memb_fapl[mt]);
+ file->fa.memb_map[mt] = fa->memb_map[mt];
+ file->fa.memb_addr[mt] = fa->memb_addr[mt];
+ if (fa->memb_fapl[mt] >= 0)
+ H5Iinc_ref(fa->memb_fapl[mt]);
file->fa.memb_fapl[mt] = fa->memb_fapl[mt];
- if (fa->memb_name[mt])
- file->fa.memb_name[mt] = my_strdup(fa->memb_name[mt]);
- else
- file->fa.memb_name[mt] = NULL;
+ if (fa->memb_name[mt])
+ file->fa.memb_name[mt] = my_strdup(fa->memb_name[mt]);
+ else
+ file->fa.memb_name[mt] = NULL;
} END_MEMBERS;
file->fa.relax = fa->relax;
file->flags = flags;
file->name = my_strdup(name);
- if (close_fapl>=0)
- if(H5Pclose(close_fapl)<0)
+ if (close_fapl >= 0)
+ if(H5Pclose(close_fapl) < 0)
H5Epush_goto(func, H5E_ERR_CLS, H5E_FILE, H5E_CANTCLOSEOBJ, "can't close property list", error)
/* Compute derived properties and open member files */
- if (compute_next(file)<0)
+ if (compute_next(file) < 0)
H5Epush_goto(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "compute_next() failed", error);
- if (open_members(file)<0)
+ if (open_members(file) < 0)
H5Epush_goto(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "open_members() failed", error);
/* We must have opened at least the superblock file */
- if (H5FD_MEM_DEFAULT==(m=file->fa.memb_map[H5FD_MEM_SUPER]))
+ if (H5FD_MEM_DEFAULT == (m = file->fa.memb_map[H5FD_MEM_SUPER]))
m = H5FD_MEM_SUPER;
- if (NULL==file->memb[m])
+ if (NULL == file->memb[m])
goto error;
return (H5FD_t*)file;
@@ -1054,13 +1048,14 @@ H5FD_multi_open(const char *name, unsigned flags, hid_t fapl_id,
error:
/* Cleanup and fail */
if (file) {
- ALL_MEMBERS(mt) {
- if (file->memb[mt]) (void)H5FDclose(file->memb[mt]);
- if (file->fa.memb_fapl[mt]>=0) (void)H5Idec_ref(file->fa.memb_fapl[mt]);
- if (file->fa.memb_name[mt]) free(file->fa.memb_name[mt]);
- } END_MEMBERS;
- if (file->name) free(file->name);
- free(file);
+ ALL_MEMBERS(mt) {
+ if (file->memb[mt]) (void)H5FDclose(file->memb[mt]);
+ if (file->fa.memb_fapl[mt] >= 0) (void)H5Idec_ref(file->fa.memb_fapl[mt]);
+ if (file->fa.memb_name[mt]) free(file->fa.memb_name[mt]);
+ } END_MEMBERS;
+ if (file->name)
+ free(file->name);
+ free(file);
}
return NULL;
}
@@ -1960,38 +1955,48 @@ compute_next(H5FD_multi_t *file)
*
*-------------------------------------------------------------------------
*/
+/* Disable warning for "format not a string literal" here -QAK */
+/*
+ * This pragma only needs to surround the snprintf() call with
+ * tmp in the code below, but early (4.4.7, at least) gcc only
+ * allows diagnostic pragmas to be toggled outside of functions.
+ */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
static int
open_members(H5FD_multi_t *file)
{
- char tmp[H5FD_MULT_MAX_FILE_NAME_LEN];
- int nerrors=0;
+ char tmp[H5FD_MULT_MAX_FILE_NAME_LEN];
+ int nerrors = 0;
static const char *func="(H5FD_multi)open_members"; /* Function Name for error reporting */
/* Clear the error stack */
H5Eclear2(H5E_DEFAULT);
UNIQUE_MEMBERS(file->fa.memb_map, mt) {
- if(file->memb[mt])
+ if(file->memb[mt])
continue; /*already open*/
- assert(file->fa.memb_name[mt]);
+ assert(file->fa.memb_name[mt]);
/* Note: This truncates the user's filename down to only sizeof(tmp)
* characters. -QK & JK, 2013/01/17
*/
- sprintf(tmp, file->fa.memb_name[mt], file->name);
-
- H5E_BEGIN_TRY {
- file->memb[mt] = H5FDopen(tmp, file->flags, file->fa.memb_fapl[mt], HADDR_UNDEF);
- } H5E_END_TRY;
- if(!file->memb[mt]) {
- if(!file->fa.relax || (file->flags & H5F_ACC_RDWR))
- nerrors++;
- }
+ sprintf(tmp, file->fa.memb_name[mt], file->name);
+ tmp[sizeof(tmp) - 1] = '\0';
+
+ H5E_BEGIN_TRY {
+ file->memb[mt] = H5FDopen(tmp, file->flags, file->fa.memb_fapl[mt], HADDR_UNDEF);
+ } H5E_END_TRY;
+ if(!file->memb[mt]) {
+ if(!file->fa.relax || (file->flags & H5F_ACC_RDWR))
+ nerrors++;
+ }
} END_MEMBERS;
if (nerrors)
H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "error opening member files", -1)
return 0;
}
+#pragma GCC diagnostic pop
#ifdef _H5private_H
diff --git a/src/H5FDprivate.h b/src/H5FDprivate.h
index 10217bd..c6a53d6 100644
--- a/src/H5FDprivate.h
+++ b/src/H5FDprivate.h
@@ -203,6 +203,39 @@ typedef struct H5FD_vfd_swmr_md_header {
uint64_t index_length;
} H5FD_vfd_swmr_md_header;
+static inline H5FD_vfd_swmr_idx_entry_t *
+vfd_swmr_pageno_to_mdf_idx_entry(H5FD_vfd_swmr_idx_entry_t *idx,
+ uint32_t nindices, uint64_t target_page)
+{
+ uint32_t top;
+ uint32_t bottom;
+ uint32_t probe;
+
+ if (nindices < 1)
+ return NULL;
+
+ bottom = 0;
+ top = nindices;
+
+ do {
+ probe = (top + bottom) / 2;
+
+ if (idx[probe].hdf5_page_offset < target_page)
+ bottom = probe + 1;
+ else if (idx[probe].hdf5_page_offset > target_page)
+ top = probe;
+ else
+ return &idx[probe]; /* found it */
+ } while (bottom < top);
+ /* Previous interval was [top - 1, top] or [bottom, bottom + 1].
+ * The new interval is [top, top] or [bottom, bottom], respectively.
+ * We probed idx[bottom] in the last step, and idx[top] (if it is
+ * not out of bounds) in an earlier round. So there is nothing
+ * to be found at (top + bottom) / 2.
+ */
+ return NULL;
+}
+
#ifdef H5_HAVE_PARALLEL
/* ======== Temporary data transfer properties ======== */
/* Definitions for memory MPI type property */
@@ -260,14 +293,6 @@ typedef struct {
const void *driver_info; /* Driver info, for open callbacks */
} H5FD_driver_prop_t;
-#ifdef H5_HAVE_PARALLEL
-/* MPIO-specific file access properties */
-typedef struct H5FD_mpio_fapl_t {
- MPI_Comm comm; /*communicator */
- MPI_Info info; /*file information */
-} H5FD_mpio_fapl_t;
-#endif /* H5_HAVE_PARALLEL */
-
/*****************************/
/* Library Private Variables */
@@ -335,9 +360,6 @@ H5_DLL void H5FD_vfd_swmr_set_pb_configured(H5FD_t *_file);
/* General routines */
H5_DLL haddr_t H5FD_mpi_MPIOff_to_haddr(MPI_Offset mpi_off);
H5_DLL herr_t H5FD_mpi_haddr_to_MPIOff(haddr_t addr, MPI_Offset *mpi_off/*out*/);
-H5_DLL herr_t H5FD_mpi_comm_info_dup(MPI_Comm comm, MPI_Info info,
- MPI_Comm *comm_new, MPI_Info *info_new);
-H5_DLL herr_t H5FD_mpi_comm_info_free(MPI_Comm *comm, MPI_Info *info);
#ifdef NOT_YET
H5_DLL herr_t H5FD_mpio_wait_for_left_neighbor(H5FD_t *file);
H5_DLL herr_t H5FD_mpio_signal_right_neighbor(H5FD_t *file);
diff --git a/src/H5FDros3.c b/src/H5FDros3.c
new file mode 100644
index 0000000..75fcfd7
--- /dev/null
+++ b/src/H5FDros3.c
@@ -0,0 +1,1833 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Read-Only S3 Virtual File Driver (VFD)
+ *
+ * Programmer: Jacob Smith <jake.smith@hdfgroup.org>
+ * 2017-10-13
+ *
+ * Purpose:
+ *
+ * Provide read-only access to files hosted on Amazon's S3 service.
+ * Relies on "s3comms" utility layer to implement the AWS REST API.
+ */
+
+/* This source code file is part of the H5FD driver module */
+#include "H5FDdrvr_module.h"
+
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5FDprivate.h" /* File drivers */
+#include "H5FDros3.h" /* ros3 file driver */
+#include "H5FLprivate.h" /* Free Lists */
+#include "H5Iprivate.h" /* IDs */
+#include "H5MMprivate.h" /* Memory management */
+#include "H5FDs3comms.h" /* S3 Communications */
+
+#ifdef H5_HAVE_ROS3_VFD
+
+/* toggle function call prints: 1 turns on
+ */
+#define ROS3_DEBUG 0
+
+/* toggle stats collection and reporting
+ */
+#define ROS3_STATS 0
+
+/* The driver identification number, initialized at runtime
+ */
+static hid_t H5FD_ROS3_g = 0;
+
+#if ROS3_STATS
+
+/* arbitrarily large value, such that any reasonable size read will be "less"
+ * than this value and set a true minimum
+ * not 0 because that may be a valid recorded minimum in degenerate cases
+ */
+#define ROS3_STATS_STARTING_MIN 0xfffffffful
+
+/* Configuration definitions for stats collection and breakdown
+ *
+ * 2^10 = 1024
+ * Reads up to 1024 bytes (1 kB) fall in bin 0
+ * 2^(10+(1*16)) = 2^26 = 64MB
+ * Reads of 64MB or greater fall in "overflow" bin[BIN_COUNT]
+ */
+#define ROS3_STATS_BASE 2
+#define ROS3_STATS_INTERVAL 1
+#define ROS3_STATS_START_POWER 10
+#define ROS3_STATS_BIN_COUNT 16 /* MUST BE GREATER THAN 0 */
+
+
+/*
+ * Calculate `BASE ^ (START_POWER + (INTERVAL * bin_i))`
+ * Stores result at `(unsigned long long *) out_ptr`.
+ * Used in computing boundaries between stats bins.
+ */
+#define ROS3_STATS_POW(bin_i, out_ptr) { \
+ unsigned long long donotshadowresult = 1; \
+ unsigned donotshadowindex = 0; \
+ for (donotshadowindex = 0; \
+ donotshadowindex < (((bin_i) * ROS3_STATS_INTERVAL) + \
+ ROS3_STATS_START_POWER); \
+ donotshadowindex++) \
+ { \
+ donotshadowresult *= ROS3_STATS_BASE; \
+ } \
+ *(out_ptr) = donotshadowresult; \
+}
+
+/* array to hold pre-computed boundaries for stats bins
+ */
+static unsigned long long ros3_stats_boundaries[ROS3_STATS_BIN_COUNT];
+
+/***************************************************************************
+ *
+ * Structure: ros3_statsbin
+ *
+ * Purpose:
+ *
+ * Structure for storing per-file ros3 VFD usage statistics.
+ *
+ *
+ *
+ * `count` (unsigned long long)
+ *
+ * Number of reads with size in this bin's range.
+ *
+ * `bytes` (unsigned long long)
+ *
+ * Total number of bytes read through this bin.
+ *
+ * `min` (unsigned long long)
+ *
+ * Smallest read size in this bin.
+ *
+ * `max` (unsigned long long)
+ *
+ * Largest read size in this bin.
+ *
+ *
+ *
+ * Programmer: Jacob Smith
+ *
+ ***************************************************************************/
+typedef struct {
+ unsigned long long count;
+ unsigned long long bytes;
+ unsigned long long min;
+ unsigned long long max;
+} ros3_statsbin;
+
+#endif /* ROS3_STATS */
+
+/***************************************************************************
+ *
+ * Structure: H5FD_ros3_t
+ *
+ * Purpose:
+ *
+ * H5FD_ros3_t is a structure used to store all information needed to
+ * maintain R/O access to a single HDF5 file that has been stored as a
+ * S3 object. This structure is created when such a file is "opened" and
+ * discarded when it is "closed".
+ *
+ * Presents an S3 object as a file to the HDF5 library.
+ *
+ *
+ *
+ * `pub` (H5FD_t)
+ *
+ * Instance of H5FD_t which contains all fields common to all VFDs.
+ * It must be the first item in this structure, since at higher levels,
+ * this structure will be treated as an instance of H5FD_t.
+ *
+ * `fa` (H5FD_ros3_fapl_t)
+ *
+ * Instance of `H5FD_ros3_fapl_t` containing the S3 configuration data
+ * needed to "open" the HDF5 file.
+ *
+ * `eoa` (haddr_t)
+ *
+ * End of addressed space in file. After open, it should always
+ * equal the file size.
+ *
+ * `s3r_handle` (s3r_t *)
+ *
+ * Instance of S3 Request handle associated with the target resource.
+ * Responsible for communicating with remote host and presenting file
+ * contents as indistinguishable from a file on the local filesystem.
+ *
+ * *** present only if ROS3_SATS is flagged to enable stats collection ***
+ *
+ * `meta` (ros3_statsbin[])
+ * `raw` (ros3_statsbin[])
+ *
+ * Only present if ros3 stats collection is enabled.
+ *
+ * Arrays of `ros3_statsbin` structures to record raw- and metadata reads.
+ *
+ * Records count and size of reads performed by the VFD, and is used to
+ * print formatted usage statistics to stdout upon VFD shutdown.
+ *
+ * Reads of each raw- and metadata type are recorded in an individual bin
+ * determined by the size of the read. The last bin of each type is
+ * reserved for "big" reads, with no defined upper bound.
+ *
+ * *** end ROS3_STATS ***
+ *
+ *
+ *
+ * Programmer: Jacob Smith
+ *
+ ***************************************************************************/
+typedef struct H5FD_ros3_t {
+ H5FD_t pub;
+ H5FD_ros3_fapl_t fa;
+ haddr_t eoa;
+ s3r_t *s3r_handle;
+#if ROS3_STATS
+ ros3_statsbin meta[ROS3_STATS_BIN_COUNT + 1];
+ ros3_statsbin raw[ROS3_STATS_BIN_COUNT + 1];
+#endif
+} H5FD_ros3_t;
+
+/*
+ * These macros check for overflow of various quantities. These macros
+ * assume that HDoff_t is signed and haddr_t and size_t are unsigned.
+ *
+ * ADDR_OVERFLOW: Checks whether a file address of type `haddr_t'
+ * is too large to be represented by the second argument
+ * of the file seek function.
+ * Only included if it may be used -- ROS3 VFD is enabled.
+ *
+ */
+#define MAXADDR (((haddr_t)1<<(8*sizeof(HDoff_t)-1))-1)
+#define ADDR_OVERFLOW(A) (HADDR_UNDEF==(A) || ((A) & ~(haddr_t)MAXADDR))
+
+/* Prototypes */
+static herr_t H5FD_ros3_term(void);
+static void *H5FD_ros3_fapl_get(H5FD_t *_file);
+static void *H5FD_ros3_fapl_copy(const void *_old_fa);
+static herr_t H5FD_ros3_fapl_free(void *_fa);
+static H5FD_t *H5FD_ros3_open(const char *name, unsigned flags, hid_t fapl_id,
+ haddr_t maxaddr);
+static herr_t H5FD_ros3_close(H5FD_t *_file);
+static int H5FD_ros3_cmp(const H5FD_t *_f1, const H5FD_t *_f2);
+static herr_t H5FD_ros3_query(const H5FD_t *_f1, unsigned long *flags);
+static haddr_t H5FD_ros3_get_eoa(const H5FD_t *_file, H5FD_mem_t type);
+static herr_t H5FD_ros3_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t addr);
+static haddr_t H5FD_ros3_get_eof(const H5FD_t *_file, H5FD_mem_t type);
+static herr_t H5FD_ros3_get_handle(H5FD_t *_file, hid_t fapl,
+ void** file_handle);
+static herr_t H5FD_ros3_read(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id,
+ haddr_t addr, size_t size, void *buf);
+static herr_t H5FD_ros3_write(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id,
+ haddr_t addr, size_t size, const void *buf);
+static herr_t H5FD_ros3_truncate(H5FD_t *_file, hid_t dxpl_id,
+ hbool_t closing);
+static herr_t H5FD_ros3_lock(H5FD_t *_file, hbool_t rw);
+static herr_t H5FD_ros3_unlock(H5FD_t *_file);
+static herr_t H5FD_ros3_validate_config(const H5FD_ros3_fapl_t * fa);
+
+static const H5FD_class_t H5FD_ros3_g = {
+ "ros3", /* name */
+ MAXADDR, /* maxaddr */
+ H5F_CLOSE_WEAK, /* fc_degree */
+ H5FD_ros3_term, /* terminate */
+ NULL, /* sb_size */
+ NULL, /* sb_encode */
+ NULL, /* sb_decode */
+ sizeof(H5FD_ros3_fapl_t), /* fapl_size */
+ H5FD_ros3_fapl_get, /* fapl_get */
+ H5FD_ros3_fapl_copy, /* fapl_copy */
+ H5FD_ros3_fapl_free, /* fapl_free */
+ 0, /* dxpl_size */
+ NULL, /* dxpl_copy */
+ NULL, /* dxpl_free */
+ H5FD_ros3_open, /* open */
+ H5FD_ros3_close, /* close */
+ H5FD_ros3_cmp, /* cmp */
+ H5FD_ros3_query, /* query */
+ NULL, /* get_type_map */
+ NULL, /* alloc */
+ NULL, /* free */
+ H5FD_ros3_get_eoa, /* get_eoa */
+ H5FD_ros3_set_eoa, /* set_eoa */
+ H5FD_ros3_get_eof, /* get_eof */
+ H5FD_ros3_get_handle, /* get_handle */
+ H5FD_ros3_read, /* read */
+ H5FD_ros3_write, /* write */
+ NULL, /* flush */
+ H5FD_ros3_truncate, /* truncate */
+ H5FD_ros3_lock, /* lock */
+ H5FD_ros3_unlock, /* unlock */
+ H5FD_FLMAP_DICHOTOMY /* fl_map */
+};
+
+/* Declare a free list to manage the H5FD_ros3_t struct */
+H5FL_DEFINE_STATIC(H5FD_ros3_t);
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD__init_package
+ *
+ * Purpose: Initializes any interface-specific data or routines.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Jacob Smith 2017
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD__init_package(void)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ if (H5FD_ros3_init() < 0) {
+ HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL,
+ "unable to initialize ros3 VFD")
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* end H5FD__init_package() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_ros3_init
+ *
+ * Purpose: Initialize this driver by registering the driver with the
+ * library.
+ *
+ * Return: Success: The driver ID for the ros3 driver.
+ * Failure: Negative
+ *
+ * Programmer: Jacob Smith 2017
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5FD_ros3_init(void)
+{
+ hid_t ret_value = H5I_INVALID_HID;
+ unsigned int bin_i;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+#if ROS3_DEBUG
+ HDfprintf(stdout, "H5FD_ros3_init() called.\n");
+#endif
+
+ if (H5I_VFL != H5I_get_type(H5FD_ROS3_g))
+ H5FD_ROS3_g = H5FD_register(&H5FD_ros3_g, sizeof(H5FD_class_t), FALSE);
+
+#if ROS3_STATS
+ /* pre-compute statsbin boundaries
+ */
+ for (bin_i = 0; bin_i < ROS3_STATS_BIN_COUNT; bin_i++) {
+ unsigned long long value = 0;
+ ROS3_STATS_POW(bin_i, &value)
+ ros3_stats_boundaries[bin_i] = value;
+ }
+#endif
+
+ /* Set return value */
+ ret_value = H5FD_ROS3_g;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* end H5FD_ros3_init() */
+
+
+/*---------------------------------------------------------------------------
+ * Function: H5FD_ros3_term
+ *
+ * Purpose: Shut down the VFD
+ *
+ * Returns: SUCCEED (Can't fail)
+ *
+ * Programmer: Jacob Smith 2017
+ *
+ *---------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_ros3_term(void)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+#if ROS3_DEBUG
+ HDfprintf(stdout, "H5FD_ros3_term() called.\n");
+#endif
+
+ /* Reset VFL ID */
+ H5FD_ROS3_g = 0;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+
+} /* end H5FD_ros3_term() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Pset_fapl_ros3
+ *
+ * Purpose: Modify the file access property list to use the H5FD_ROS3
+ * driver defined in this source file. All driver specfic
+ * properties are passed in as a pointer to a suitably
+ * initialized instance of H5FD_ros3_fapl_t
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: John Mainzer
+ * 9/10/17
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Pset_fapl_ros3(hid_t fapl_id,
+ H5FD_ros3_fapl_t *fa)
+{
+ H5P_genplist_t *plist = NULL; /* Property list pointer */
+ herr_t ret_value = FAIL;
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE2("e", "i*x", fapl_id, fa);
+
+ HDassert(fa != NULL);
+
+#if ROS3_DEBUG
+ HDfprintf(stdout, "H5Pset_fapl_ros3() called.\n");
+#endif
+
+ plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS);
+ if (plist == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, \
+ "not a file access property list")
+ }
+
+ if (FAIL == H5FD_ros3_validate_config(fa)) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid ros3 config")
+ }
+
+ ret_value = H5P_set_driver(plist, H5FD_ROS3, (void *)fa);
+
+done:
+ FUNC_LEAVE_API(ret_value)
+
+} /* end H5Pset_fapl_ros3() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_ros3_validate_config()
+ *
+ * Purpose: Test to see if the supplied instance of H5FD_ros3_fapl_t
+ * contains internally consistant data. Return SUCCEED if so,
+ * and FAIL otherwise.
+ *
+ * Note the difference between internally consistant and
+ * correct. As we will have to try to access the target
+ * object to determine whether the supplied data is correct,
+ * we will settle for internal consistancy at this point
+ *
+ * Return: SUCCEED if instance of H5FD_ros3_fapl_t contains internally
+ * consistant data, FAIL otherwise.
+ *
+ * Programmer: Jacob Smith
+ * 9/10/17
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_ros3_validate_config(const H5FD_ros3_fapl_t * fa)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ HDassert(fa != NULL);
+
+ if ( fa->version != H5FD_CURR_ROS3_FAPL_T_VERSION ) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "Unknown H5FD_ros3_fapl_t version");
+ }
+
+ /* if set to authenticate, region and id cannot be empty strings
+ */
+ if (fa->authenticate == TRUE) {
+ if ((fa->aws_region[0] == '\0') ||
+ (fa->secret_id[0] == '\0'))
+ {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "Inconsistent authentication information");
+ }
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* end H5FD_ros3_validate_config() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Pget_fapl_ros3
+ *
+ * Purpose: Returns information about the ros3 file access property
+ * list though the function arguments.
+ *
+ * Return: Success: Non-negative
+ *
+ * Failure: Negative
+ *
+ * Programmer: John Mainzer
+ * 9/10/17
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Pget_fapl_ros3(hid_t fapl_id,
+ H5FD_ros3_fapl_t *fa_out)
+{
+ const H5FD_ros3_fapl_t *fa = NULL;
+ H5P_genplist_t *plist = NULL;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE2("e", "i*x", fapl_id, fa_out);
+
+#if ROS3_DEBUG
+ HDfprintf(stdout, "H5Pget_fapl_ros3() called.\n");
+#endif
+
+ if (fa_out == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "fa_out is NULL")
+ }
+
+ plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS);
+ if (plist == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access list")
+ }
+
+ if (H5FD_ROS3 != H5P_peek_driver(plist)) {
+ HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "incorrect VFL driver")
+ }
+
+ fa = (const H5FD_ros3_fapl_t *)H5P_peek_driver_info(plist);
+ if (fa == NULL) {
+ HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "bad VFL driver info")
+ }
+
+ /* Copy the ros3 fapl data out */
+ HDmemcpy(fa_out, fa, sizeof(H5FD_ros3_fapl_t));
+
+done:
+ FUNC_LEAVE_API(ret_value)
+
+} /* end H5Pget_fapl_ros3() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_ros3_fapl_get
+ *
+ * Purpose: Gets a file access property list which could be used to
+ * create an identical file.
+ *
+ * Return: Success: Ptr to new file access property list value.
+ *
+ * Failure: NULL
+ *
+ * Programmer: John Mainzer
+ * 9/8/17
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5FD_ros3_fapl_get(H5FD_t *_file)
+{
+ H5FD_ros3_t *file = (H5FD_ros3_t*)_file;
+ H5FD_ros3_fapl_t *fa = NULL;
+ void *ret_value = NULL;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ fa = (H5FD_ros3_fapl_t *)H5MM_calloc(sizeof(H5FD_ros3_fapl_t));
+ if (fa == NULL) {
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL,
+ "memory allocation failed")
+ }
+
+ /* Copy the fields of the structure */
+ HDmemcpy(fa, &(file->fa), sizeof(H5FD_ros3_fapl_t));
+
+ /* Set return value */
+ ret_value = fa;
+
+done:
+ if (ret_value == NULL) {
+ if (fa != NULL) {
+ H5MM_xfree(fa);
+ }
+ }
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* end H5FD_ros3_fapl_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_ros3_fapl_copy
+ *
+ * Purpose: Copies the ros3-specific file access properties.
+ *
+ * Return: Success: Ptr to a new property list
+ *
+ * Failure: NULL
+ *
+ * Programmer: John Mainzer
+ * 9/8/17
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5FD_ros3_fapl_copy(const void *_old_fa)
+{
+ const H5FD_ros3_fapl_t *old_fa = (const H5FD_ros3_fapl_t*)_old_fa;
+ H5FD_ros3_fapl_t *new_fa = NULL;
+ void *ret_value = NULL;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ new_fa = (H5FD_ros3_fapl_t *)H5MM_malloc(sizeof(H5FD_ros3_fapl_t));
+ if (new_fa == NULL) {
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL,
+ "memory allocation failed");
+ }
+
+ HDmemcpy(new_fa, old_fa, sizeof(H5FD_ros3_fapl_t));
+ ret_value = new_fa;
+
+done:
+ if (ret_value == NULL) {
+ if (new_fa != NULL) {
+ H5MM_xfree(new_fa);
+ }
+ }
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* end H5FD_ros3_fapl_copy() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_ros3_fapl_free
+ *
+ * Purpose: Frees the ros3-specific file access properties.
+ *
+ * Return: SUCCEED (cannot fail)
+ *
+ * Programmer: John Mainzer
+ * 9/8/17
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_ros3_fapl_free(void *_fa)
+{
+ H5FD_ros3_fapl_t *fa = (H5FD_ros3_fapl_t*)_fa;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ HDassert(fa != NULL); /* sanity check */
+
+ H5MM_xfree(fa);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+
+} /* end H5FD_ros3_fapl_free() */
+
+#if ROS3_STATS
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: ros3_reset_stats()
+ *
+ * Purpose:
+ *
+ * Reset the stats collection elements in this virtual file structure.
+ *
+ * Clears any set data in stats bins; initializes/zeroes values.
+ *
+ * Return:
+ *
+ * - SUCCESS: `SUCCEED`
+ * - FAILURE: `FAIL`
+ * - Occurs if the file is invalid somehow
+ *
+ * Programmer: Jacob Smith
+ * 2017-12-08
+ *
+ *----------------------------------------------------------------------------
+ */
+static herr_t
+ros3_reset_stats(H5FD_ros3_t *file)
+{
+ unsigned i = 0;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+#if ROS3_DEBUG
+ HDprintf("ros3_reset_stats() called\n");
+#endif
+
+ if (file == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "file was null");
+ }
+
+ for (i = 0; i <= ROS3_STATS_BIN_COUNT; i++) {
+ file->raw[i].bytes = 0;
+ file->raw[i].count = 0;
+ file->raw[i].min = (unsigned long long)ROS3_STATS_STARTING_MIN;
+ file->raw[i].max = 0;
+
+ file->meta[i].bytes = 0;
+ file->meta[i].count = 0;
+ file->meta[i].min = (unsigned long long)ROS3_STATS_STARTING_MIN;
+ file->meta[i].max = 0;
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+
+} /* end ros3_reset_stats() */
+
+#endif /* ROS3_STATS */
+
+
+/*-------------------------------------------------------------------------
+ *
+ * Function: H5FD_ros3_open()
+ *
+ * Purpose:
+ *
+ * Create and/or opens a file as an HDF5 file.
+ *
+ * Any flag except H5F_ACC_RDONLY will cause an error.
+ *
+ * Name (as received from `H5FD_open()`) must conform to web url:
+ * NAME :: HTTP "://" DOMAIN [PORT] ["/" [URI] [QUERY] ]
+ * HTTP :: "http" [ "s" ]
+ * DOMAIN :: e.g., "mybucket.host.org"
+ * PORT :: ":" <number> (e.g., ":9000" )
+ * URI :: <string> (e.g., "path/to/resource.hd5" )
+ * QUERY :: "?" <string> (e.g., "arg1=param1&arg2=param2")
+ *
+ * Return:
+ *
+ * Success: A pointer to a new file data structure.
+ * The public fields will be initialized by the caller, which is
+ * always H5FD_open().
+ *
+ * Failure: NULL
+ *
+ * Programmer: Jacob Smith
+ * 2017-11-02
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5FD_t *
+H5FD_ros3_open(
+ const char *url,
+ unsigned flags,
+ hid_t fapl_id,
+ haddr_t maxaddr)
+{
+ H5FD_ros3_t *file = NULL;
+ struct tm *now = NULL;
+ char iso8601now[ISO8601_SIZE];
+ unsigned char signing_key[SHA256_DIGEST_LENGTH];
+ s3r_t *handle = NULL;
+ H5FD_ros3_fapl_t fa;
+ H5FD_t *ret_value = NULL;
+
+
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+#if ROS3_DEBUG
+ HDfprintf(stdout, "H5FD_ros3_open() called.\n");
+#endif
+
+ /* Sanity check on file offsets */
+ HDcompile_assert(sizeof(HDoff_t) >= sizeof(size_t));
+
+ /* Check arguments */
+ if (!url || !*url)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid file name")
+ if (0 == maxaddr || HADDR_UNDEF == maxaddr)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, NULL, "bogus maxaddr")
+ if (ADDR_OVERFLOW(maxaddr))
+ HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, NULL, "bogus maxaddr")
+ if (flags != H5F_ACC_RDONLY)
+ HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, NULL,
+ "only Read-Only access allowed")
+
+ if (FAIL == H5Pget_fapl_ros3(fapl_id, &fa)) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "can't get property list")
+ }
+
+ if (CURLE_OK != curl_global_init(CURL_GLOBAL_DEFAULT)) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL,
+ "unable to initialize curl global (placeholder flags)")
+ }
+
+ /* open file; procedure depends on whether or not the fapl instructs to
+ * authenticate requests or not.
+ */
+ if (fa.authenticate == TRUE) {
+ /* compute signing key (part of AWS/S3 REST API)
+ * can be re-used by user/key for 7 days after creation.
+ * find way to re-use/share
+ */
+ now = gmnow();
+ HDassert( now != NULL );
+ if (ISO8601NOW(iso8601now, now) != (ISO8601_SIZE - 1)) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL,
+ "problem while writing iso8601 timestamp")
+ }
+ if (FAIL == H5FD_s3comms_signing_key(signing_key,
+ (const char *)fa.secret_key,
+ (const char *)fa.aws_region,
+ (const char *)iso8601now) )
+ {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL,
+ "problem while computing signing key")
+ }
+
+ handle = H5FD_s3comms_s3r_open(
+ url,
+ (const char *)fa.aws_region,
+ (const char *)fa.secret_id,
+ (const unsigned char *)signing_key);
+ } else {
+ handle = H5FD_s3comms_s3r_open(url, NULL, NULL, NULL);
+ } /* if/else should authenticate */
+
+ if (handle == NULL) {
+ /* If we want to check CURL's say on the matter in a controlled
+ * fashion, this is the place to do it, but would need to make a
+ * few minor changes to s3comms `s3r_t` and `s3r_read()`.
+ */
+ HGOTO_ERROR(H5E_VFL, H5E_CANTOPENFILE, NULL, "could not open");
+ }
+
+ /* create new file struct
+ */
+ file = H5FL_CALLOC(H5FD_ros3_t);
+ if (file == NULL) {
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL,
+ "unable to allocate file struct")
+ }
+
+ file->s3r_handle = handle;
+ HDmemcpy(&(file->fa), &fa, sizeof(H5FD_ros3_fapl_t));
+
+#if ROS3_STATS
+ if (FAIL == ros3_reset_stats(file)) {
+ HGOTO_ERROR(H5E_INTERNAL, H5E_UNINITIALIZED, NULL,
+ "unable to reset file statistics")
+ }
+#endif /* ROS3_STATS */
+
+ ret_value = (H5FD_t*)file;
+
+done:
+ if (ret_value == NULL) {
+ if (handle != NULL) {
+ if (FAIL == H5FD_s3comms_s3r_close(handle)) {
+ HDONE_ERROR(H5E_VFL, H5E_CANTCLOSEFILE, NULL,
+ "unable to close s3 file handle")
+ }
+ }
+ if (file != NULL) {
+ file = H5FL_FREE(H5FD_ros3_t, file);
+ }
+ curl_global_cleanup(); /* early cleanup because open failed */
+ } /* end if null return value (error) */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* end H5FD_ros3_open() */
+
+#if ROS3_STATS
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: ros3_fprint_stats()
+ *
+ * Purpose:
+ *
+ * Tabulate and pretty-print statistics for this virtual file.
+ *
+ * Should be called upon file close.
+ *
+ * Shows number of reads and bytes read, broken down by
+ * "raw" (H5FD_MEM_DRAW)
+ * or "meta" (any other flag)
+ *
+ * Prints filename and listing of total number of reads and bytes read,
+ * both as a grand total and separate meta- and rawdata reads.
+ *
+ * If any reads were done, prints out two tables:
+ *
+ * 1. overview of raw- and metadata reads
+ * - min (smallest size read)
+ * - average of size read
+ * - k,M,G suffixes by powers of 1024 (2^10)
+ * - max (largest size read)
+ * 2. tabulation of "bins", sepraring reads into exponentially-larger
+ * ranges of size.
+ * - columns for number of reads, total bytes, and average size, with
+ * separate sub-colums for raw- and metadata reads.
+ * - each row represents one bin, identified by the top of its range
+ *
+ * Bin ranges can be modified with pound-defines at the top of this file.
+ *
+ * Bins without any reads in their bounds are not printed.
+ *
+ * An "overflow" bin is also present, to catch "big" reads.
+ *
+ * Output for all bins (and range ceiling and average size report)
+ * is divied by powers of 1024. By corollary, four digits before the decimal
+ * is valid.
+ *
+ * - 41080 bytes is represented by 40.177k, not 41.080k
+ * - 1004.831M represents approx. 1052642000 bytes
+ *
+ * Return:
+ *
+ * - SUCCESS: `SUCCEED`
+ * - FAILURE: `FAIL`
+ * - occurs if the file passed in is invalid
+ * - TODO: if stream is invalid? how can we check this?
+ *
+ * Programmer: Jacob Smith
+ *
+ *----------------------------------------------------------------------------
+ */
+static herr_t
+ros3_fprint_stats(FILE *stream,
+ const H5FD_ros3_t *file)
+{
+ herr_t ret_value = SUCCEED;
+ parsed_url_t *purl = NULL;
+ unsigned i = 0;
+ unsigned long count_meta = 0;
+ unsigned long count_raw = 0;
+ double average_meta = 0.0;
+ double average_raw = 0.0;
+ unsigned long long min_meta = (unsigned long long)ROS3_STATS_STARTING_MIN;
+ unsigned long long min_raw = (unsigned long long)ROS3_STATS_STARTING_MIN;
+ unsigned long long max_meta = 0;
+ unsigned long long max_raw = 0;
+ unsigned long long bytes_raw = 0;
+ unsigned long long bytes_meta = 0;
+ double re_dub = 0.0; /* re-usable double variable */
+ unsigned suffix_i = 0;
+ const char suffixes[] = { ' ', 'K', 'M', 'G', 'T', 'P' };
+
+
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ if (stream == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "file stream cannot be null" );
+ }
+ if (file == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "file cannot be null");
+ }
+ if (file->s3r_handle == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "s3 request handle cannot be null");
+ }
+ if (file->s3r_handle->purl == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "parsed url structure cannot be null");
+ }
+ purl = file->s3r_handle->purl;
+
+ /******************
+ * PRINT FILENAME *
+ ******************/
+
+ HDfprintf(stream, "stats for %s://%s", purl->scheme, purl->host);
+ if (purl->port != NULL && purl->port[0] != '\0')
+ HDfprintf(stream, ":%s", purl->port);
+ if (purl->query != NULL && purl->query[0] != '\0') {
+ if (purl->path != NULL && purl->path[0] != '\0')
+ HDfprintf(stream, "/%s", purl->path);
+ else
+ HDfprintf(stream, "/");
+ HDfprintf(stream, "?%s", purl->query);
+ } else if (purl->path != NULL && purl->path[0] != '\0') {
+ HDfprintf(stream, "/%s", purl->path);
+ }
+ HDfprintf(stream, "\n");
+
+ /*******************
+ * AGGREGATE STATS *
+ *******************/
+
+ for (i = 0; i <= ROS3_STATS_BIN_COUNT; i++) {
+ const ros3_statsbin *r = &file->raw[i];
+ const ros3_statsbin *m = &file->meta[i];
+
+ if (m->min < min_meta) min_meta = m->min;
+ if (r->min < min_raw) min_raw = r->min;
+ if (m->max > max_meta) max_meta = m->max;
+ if (r->max > max_raw) max_raw = r->max;
+
+ count_raw += r->count;
+ count_meta += m->count;
+ bytes_raw += r->bytes;
+ bytes_meta += m->bytes;
+ }
+ if (count_raw > 0)
+ average_raw = (double)bytes_raw / (double)count_raw;
+ if (count_meta > 0)
+ average_meta = (double)bytes_meta / (double)count_meta;
+
+ /******************
+ * PRINT OVERVIEW *
+ ******************/
+
+ HDfprintf(stream, "TOTAL READS: %llu (%llu meta, %llu raw)\n",
+ count_raw + count_meta, count_meta, count_raw);
+ HDfprintf(stream, "TOTAL BYTES: %llu (%llu meta, %llu raw)\n",
+ bytes_raw + bytes_meta, bytes_meta, bytes_raw);
+
+ if (count_raw + count_meta == 0)
+ goto done;
+
+ /*************************
+ * PRINT AGGREGATE STATS *
+ *************************/
+
+ HDfprintf(stream, "SIZES meta raw\n");
+ HDfprintf(stream, " min ");
+ if (count_meta == 0) {
+ HDfprintf(stream, " 0.000 ");
+ } else {
+ re_dub = (double)min_meta;
+ for (suffix_i = 0; re_dub >= 1024.0; suffix_i++)
+ re_dub /= 1024.0;
+ HDassert(suffix_i < sizeof(suffixes));
+ HDfprintf(stream, "%8.3lf%c ", re_dub, suffixes[suffix_i]);
+ }
+
+ if (count_raw == 0) {
+ HDfprintf(stream, " 0.000 \n");
+ } else {
+ re_dub = (double)min_raw;
+ for (suffix_i = 0; re_dub >= 1024.0; suffix_i++)
+ re_dub /= 1024.0;
+ HDassert(suffix_i < sizeof(suffixes));
+ HDfprintf(stream, "%8.3lf%c\n", re_dub, suffixes[suffix_i]);
+ }
+
+ HDfprintf(stream, " avg ");
+ re_dub = (double)average_meta;
+ for (suffix_i = 0; re_dub >= 1024.0; suffix_i++)
+ re_dub /= 1024.0;
+ HDassert(suffix_i < sizeof(suffixes));
+ HDfprintf(stream, "%8.3lf%c ", re_dub, suffixes[suffix_i]);
+
+ re_dub = (double)average_raw;
+ for (suffix_i = 0; re_dub >= 1024.0; suffix_i++)
+ re_dub /= 1024.0;
+ HDassert(suffix_i < sizeof(suffixes));
+ HDfprintf(stream, "%8.3lf%c\n", re_dub, suffixes[suffix_i]);
+
+ HDfprintf(stream, " max ");
+ re_dub = (double)max_meta;
+ for (suffix_i = 0; re_dub >= 1024.0; suffix_i++)
+ re_dub /= 1024.0;
+ HDassert(suffix_i < sizeof(suffixes));
+ HDfprintf(stream, "%8.3lf%c ", re_dub, suffixes[suffix_i]);
+
+ re_dub = (double)max_raw;
+ for (suffix_i = 0; re_dub >= 1024.0; suffix_i++)
+ re_dub /= 1024.0;
+ HDassert(suffix_i < sizeof(suffixes));
+ HDfprintf(stream, "%8.3lf%c\n", re_dub, suffixes[suffix_i]);
+
+ /******************************
+ * PRINT INDIVIDUAL BIN STATS *
+ ******************************/
+
+ HDfprintf(stream,
+ "BINS # of reads total bytes average size\n");
+ HDfprintf(stream,
+ " up-to meta raw meta raw meta raw\n");
+
+ for (i = 0; i <= ROS3_STATS_BIN_COUNT; i++) {
+ const ros3_statsbin *m;
+ const ros3_statsbin *r;
+ unsigned long long range_end = 0;
+ char bm_suffix = ' '; /* bytes-meta */
+ double bm_val = 0.0;
+ char br_suffix = ' '; /* bytes-raw */
+ double br_val = 0.0;
+ char am_suffix = ' '; /* average-meta */
+ double am_val = 0.0;
+ char ar_suffix = ' '; /* average-raw */
+ double ar_val = 0.0;
+
+ m = &file->meta[i];
+ r = &file->raw[i];
+ if (r->count == 0 && m->count == 0)
+ continue;
+
+ range_end = ros3_stats_boundaries[i];
+
+ if (i == ROS3_STATS_BIN_COUNT) {
+ range_end = ros3_stats_boundaries[i-1];
+ HDfprintf(stream, ">");
+ } else {
+ HDfprintf(stream, " ");
+ }
+
+ bm_val = (double)m->bytes;
+ for (suffix_i = 0; bm_val >= 1024.0; suffix_i++)
+ bm_val /= 1024.0;
+ HDassert(suffix_i < sizeof(suffixes));
+ bm_suffix = suffixes[suffix_i];
+
+ br_val = (double)r->bytes;
+ for (suffix_i = 0; br_val >= 1024.0; suffix_i++)
+ br_val /= 1024.0;
+ HDassert(suffix_i < sizeof(suffixes));
+ br_suffix = suffixes[suffix_i];
+
+ if (m->count > 0)
+ am_val = (double)(m->bytes) / (double)(m->count);
+ for (suffix_i = 0; am_val >= 1024.0; suffix_i++)
+ am_val /= 1024.0;
+ HDassert(suffix_i < sizeof(suffixes));
+ am_suffix = suffixes[suffix_i];
+
+ if (r->count > 0)
+ ar_val = (double)(r->bytes) / (double)(r->count);
+ for (suffix_i = 0; ar_val >= 1024.0; suffix_i++)
+ ar_val /= 1024.0;
+ HDassert(suffix_i < sizeof(suffixes));
+ ar_suffix = suffixes[suffix_i];
+
+ re_dub = (double)range_end;
+ for (suffix_i = 0; re_dub >= 1024.0; suffix_i++)
+ re_dub /= 1024.0;
+ HDassert(suffix_i < sizeof(suffixes));
+
+ HDfprintf(stream,
+ " %8.3f%c %7d %7d %8.3f%c %8.3f%c %8.3f%c %8.3f%c\n",
+ re_dub, suffixes[suffix_i], /* bin ceiling */
+ m->count, /* metadata reads */
+ r->count, /* rawdata reads */
+ bm_val, bm_suffix, /* metadata bytes */
+ br_val, br_suffix, /* rawdata bytes */
+ am_val, am_suffix, /* metadata average */
+ ar_val, ar_suffix); /* rawdata average */
+
+ fflush(stream);
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+
+} /* ros3_fprint_stats */
+#endif /* ROS3_STATS */
+
+
+/*-------------------------------------------------------------------------
+ *
+ * Function: H5FD_ros3_close()
+ *
+ * Purpose:
+ *
+ * Close an HDF5 file.
+ *
+ * Return:
+ *
+ * SUCCEED/FAIL
+ *
+ * Programmer: Jacob Smith
+ * 2017-11-02
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_ros3_close(H5FD_t H5_ATTR_UNUSED *_file)
+{
+ H5FD_ros3_t *file = (H5FD_ros3_t *)_file;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+#if ROS3_DEBUG
+ HDfprintf(stdout, "H5FD_ros3_close() called.\n");
+#endif
+
+ /* Sanity checks
+ */
+ HDassert(file != NULL);
+ HDassert(file->s3r_handle != NULL);
+
+ /* Close the underlying request handle
+ */
+ if (FAIL == H5FD_s3comms_s3r_close(file->s3r_handle)) {
+ HGOTO_ERROR(H5E_VFL, H5E_CANTCLOSEFILE, FAIL,
+ "unable to close S3 request handle")
+ }
+
+#if ROS3_STATS
+ /* TODO: mechanism to re-target stats printout */
+ if (ros3_fprint_stats(stdout, file) == FAIL) {
+ HGOTO_ERROR(H5E_INTERNAL, H5E_ERROR, FAIL,
+ "problem while writing file statistics")
+ }
+#endif /* ROS3_STATS */
+
+ /* Release the file info
+ */
+ file = H5FL_FREE(H5FD_ros3_t, file);
+
+done:
+ curl_global_cleanup(); /* cleanup to answer init on open */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* end H5FD_ros3_close() */
+
+
+/*-------------------------------------------------------------------------
+ *
+ * Function: H5FD_ros3_cmp()
+ *
+ * Purpose:
+ *
+ * Compares two files belonging to this driver using an arbitrary
+ * (but consistent) ordering:
+ *
+ * + url scheme
+ * + url host
+ * + url port
+ * + url path
+ * + url query
+ * + fapl aws_region
+ * + fapl secret_id
+ * + fapl secret_key
+ *
+ * tl;dr -> check URL, check crentials
+ *
+ * Return:
+ *
+ * - Equivalent: 0
+ * - Not Equivalent: -1
+ *
+ * Programmer: Jacob Smith
+ * 2017-11-06
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+H5FD_ros3_cmp(
+ const H5FD_t *_f1,
+ const H5FD_t *_f2)
+{
+ const H5FD_ros3_t *f1 = (const H5FD_ros3_t *)_f1;
+ const H5FD_ros3_t *f2 = (const H5FD_ros3_t *)_f2;
+ const parsed_url_t *purl1 = NULL;
+ const parsed_url_t *purl2 = NULL;
+ int ret_value = 0;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+#if ROS3_DEBUG
+ HDfprintf(stdout, "H5FD_ros3_cmp() called.\n");
+#endif
+
+ HDassert(f1->s3r_handle != NULL);
+ HDassert(f2->s3r_handle != NULL);
+
+ purl1 = (const parsed_url_t *)f1->s3r_handle->purl;
+ purl2 = (const parsed_url_t *)f2->s3r_handle->purl;
+ HDassert(purl1 != NULL);
+ HDassert(purl2 != NULL);
+ HDassert(purl1->scheme != NULL);
+ HDassert(purl2->scheme != NULL);
+ HDassert(purl1->host != NULL);
+ HDassert(purl2->host != NULL);
+
+ /* URL: SCHEME */
+ if (HDstrcmp(purl1->scheme, purl2->scheme)) {
+ HGOTO_DONE(-1);
+ }
+
+ /* URL: HOST */
+ if (HDstrcmp(purl1->host, purl2->host)) {
+ HGOTO_DONE(-1);
+ }
+
+ /* URL: PORT */
+ if (purl1->port && purl2->port) {
+ if (HDstrcmp(purl1->port, purl2->port)) {
+ HGOTO_DONE(-1);
+ }
+ }
+ else
+ if (purl1->port) {
+ HGOTO_DONE(-1);
+ }
+ else
+ if (purl2->port) {
+ HGOTO_DONE(-1);
+ }
+
+ /* URL: PATH */
+ if (purl1->path && purl2->path) {
+ if (HDstrcmp(purl1->path, purl2->path)) {
+ HGOTO_DONE(-1);
+ }
+ }
+ else
+ if (purl1->path && !purl2->path) {
+ HGOTO_DONE(-1);
+ }
+ else
+ if (purl2->path && !purl1->path) {
+ HGOTO_DONE(-1);
+ }
+
+ /* URL: QUERY */
+ if (purl1->query && purl2->query) {
+ if (HDstrcmp(purl1->query, purl2->query)) {
+ HGOTO_DONE(-1);
+ }
+ }
+ else
+ if (purl1->query && !purl2->query) {
+ HGOTO_DONE(-1);
+ }
+ else
+ if (purl2->query && !purl1->query) {
+ HGOTO_DONE(-1);
+ }
+
+ /* FAPL: AWS_REGION */
+ if (f1->fa.aws_region[0] != '\0' && f1->fa.aws_region[0] != '\0') {
+ if (HDstrcmp(f1->fa.aws_region, f2->fa.aws_region)) {
+ HGOTO_DONE(-1);
+ }
+ }
+ else
+ if (f1->fa.aws_region[0] != '\0') {
+ HGOTO_DONE(-1);
+ }
+ else
+ if (f2->fa.aws_region[0] != '\0') {
+ HGOTO_DONE(-1);
+ }
+
+ /* FAPL: SECRET_ID */
+ if (f1->fa.secret_id[0] != '\0' && f1->fa.secret_id[0] != '\0') {
+ if (HDstrcmp(f1->fa.secret_id, f2->fa.secret_id)) {
+ HGOTO_DONE(-1);
+ }
+ }
+ else
+ if (f1->fa.secret_id[0] != '\0') {
+ HGOTO_DONE(-1);
+ }
+ else
+ if (f2->fa.secret_id[0] != '\0') {
+ HGOTO_DONE(-1);
+ }
+
+ /* FAPL: SECRET_KEY */
+ if (f1->fa.secret_key[0] != '\0' && f1->fa.secret_key[0] != '\0') {
+ if (HDstrcmp(f1->fa.secret_key, f2->fa.secret_key)) {
+ HGOTO_DONE(-1);
+ }
+ }
+ else
+ if (f1->fa.secret_key[0] != '\0') {
+ HGOTO_DONE(-1);
+ }
+ else
+ if (f2->fa.secret_key[0] != '\0') {
+ HGOTO_DONE(-1);
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5FD_ros3_cmp() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_ros3_query
+ *
+ * Purpose: Set the flags that this VFL driver is capable of supporting.
+ * (listed in H5FDpublic.h)
+ *
+ * Note that since the ROS3 VFD is read only, most flags
+ * are irrelevant.
+ *
+ * The term "set" is highly misleading...
+ * stores/copies the supported flags in the out-pointer `flags`.
+ *
+ * Return: SUCCEED (Can't fail)
+ *
+ * Programmer: John Mainzer
+ * 9/11/17
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_ros3_query(const H5FD_t H5_ATTR_UNUSED *_file,
+ unsigned long *flags /* out */)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+#if ROS3_DEBUG
+ HDfprintf(stdout, "H5FD_ros3_query() called.\n");
+#endif
+
+ /* Set the VFL feature flags that this driver supports */
+ if (flags) {
+ *flags = 0;
+ /* OK to perform data sieving for faster raw data reads & writes */
+ *flags |= H5FD_FEAT_DATA_SIEVE;
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+
+} /* H5FD_ros3_query() */
+
+
+/*-------------------------------------------------------------------------
+ *
+ * Function: H5FD_ros3_get_eoa()
+ *
+ * Purpose:
+ *
+ * Gets the end-of-address marker for the file. The EOA marker
+ * is the first address past the last byte allocated in the
+ * format address space.
+ *
+ * Return:
+ *
+ * The end-of-address marker.
+ *
+ * Programmer: Jacob Smith
+ * 2017-11-02
+ *
+ *-------------------------------------------------------------------------
+ */
+static haddr_t
+H5FD_ros3_get_eoa(const H5FD_t *_file,
+ H5FD_mem_t H5_ATTR_UNUSED type)
+{
+ const H5FD_ros3_t *file = (const H5FD_ros3_t *)_file;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+#if ROS3_DEBUG
+ HDfprintf(stdout, "H5FD_ros3_get_eoa() called.\n");
+#endif
+
+ FUNC_LEAVE_NOAPI(file->eoa)
+
+} /* end H5FD_ros3_get_eoa() */
+
+
+/*-------------------------------------------------------------------------
+ *
+ * Function: H5FD_ros3_set_eoa()
+ *
+ * Purpose:
+ *
+ * Set the end-of-address marker for the file.
+ *
+ * Return:
+ *
+ * SUCCEED (can't fail)
+ *
+ * Programmer: Jacob Smith
+ * 2017-11-03
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_ros3_set_eoa(H5FD_t *_file,
+ H5FD_mem_t H5_ATTR_UNUSED type,
+ haddr_t addr)
+{
+ H5FD_ros3_t *file = (H5FD_ros3_t *)_file;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+#if ROS3_DEBUG
+ HDfprintf(stdout, "H5FD_ros3_set_eoa() called.\n");
+#endif
+
+ file->eoa = addr;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+
+} /* H5FD_ros3_set_eoa() */
+
+
+/*-------------------------------------------------------------------------
+ *
+ * Function: H5FD_ros3_get_eof()
+ *
+ * Purpose:
+ *
+ * Returns the end-of-file marker.
+ *
+ * Return:
+ *
+ * EOF: the first address past the end of the "file", either the
+ * filesystem file or the HDF5 file.
+ *
+ * Programmer: Jacob Smith
+ * 2017-11-02
+ *
+ *-------------------------------------------------------------------------
+ */
+static haddr_t
+H5FD_ros3_get_eof(const H5FD_t *_file,
+ H5FD_mem_t H5_ATTR_UNUSED type)
+{
+ const H5FD_ros3_t *file = (const H5FD_ros3_t *)_file;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+#if ROS3_DEBUG
+ HDfprintf(stdout, "H5FD_ros3_get_eof() called.\n");
+#endif
+
+ FUNC_LEAVE_NOAPI(H5FD_s3comms_s3r_get_filesize(file->s3r_handle))
+
+} /* end H5FD_ros3_get_eof() */
+
+
+/*-------------------------------------------------------------------------
+ *
+ * Function: H5FD_ros3_get_handle()
+ *
+ * Purpose:
+ *
+ * Returns the S3 Request handle (s3r_t) of ros3 file driver.
+ *
+ * Returns:
+ *
+ * SUCCEED/FAIL
+ *
+ * Programmer: Jacob Smith
+ * 2017-11-02
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_ros3_get_handle(H5FD_t *_file,
+ hid_t H5_ATTR_UNUSED fapl,
+ void **file_handle)
+{
+ H5FD_ros3_t *file = (H5FD_ros3_t *)_file;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+#if ROS3_DEBUG
+ HDfprintf(stdout, "H5FD_ros3_get_handle() called.\n");
+#endif
+
+ if (!file_handle) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file handle not valid")
+ }
+
+ *file_handle = file->s3r_handle;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* end H5FD_ros3_get_handle() */
+
+
+/*-------------------------------------------------------------------------
+ *
+ * Function: H5FD_ros3_read()
+ *
+ * Purpose
+ *
+ * Reads SIZE bytes of data from FILE beginning at address ADDR
+ * into buffer BUF according to data transfer properties in DXPL_ID.
+ *
+ * Return:
+ *
+ * Success: `SUCCEED`
+ * - Result is stored in caller-supplied buffer BUF.
+ * Failure: `FAIL`
+ * - Unable to complete read.
+ * - Contents of buffer `buf` are undefined.
+ *
+ * Programmer: Jacob Smith
+ * 2017-11-??
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_ros3_read(H5FD_t *_file,
+ H5FD_mem_t H5_ATTR_UNUSED type,
+ hid_t H5_ATTR_UNUSED dxpl_id,
+ haddr_t addr, /* start offset */
+ size_t size, /* length of read */
+ void *buf) /* out */
+{
+ H5FD_ros3_t *file = (H5FD_ros3_t *)_file;
+ size_t filesize = 0;
+ herr_t ret_value = SUCCEED;
+#if ROS3_STATS
+ /* working variables for storing stats */
+ ros3_statsbin *bin = NULL;
+ unsigned bin_i = 0;
+#endif /* ROS3_STATS */
+
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+#if ROS3_DEBUG
+ HDfprintf(stdout, "H5FD_ros3_read() called.\n");
+#endif
+
+ HDassert(file != NULL);
+ HDassert(file->s3r_handle != NULL);
+ HDassert(buf != NULL);
+
+ filesize = H5FD_s3comms_s3r_get_filesize(file->s3r_handle);
+
+ if ((addr > filesize) || ((addr + size) > filesize)) {
+ HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, FAIL, "range exceeds file address")
+ }
+
+ if (H5FD_s3comms_s3r_read(file->s3r_handle, addr, size, buf) == FAIL) {
+ HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "unable to execute read")
+ }
+
+#if ROS3_STATS
+
+ /* Find which "bin" this read fits in. Can be "overflow" bin.
+ */
+ for (bin_i = 0; bin_i < ROS3_STATS_BIN_COUNT; bin_i++) {
+ if ((unsigned long long)size < ros3_stats_boundaries[bin_i]) {
+ break;
+ }
+ }
+ bin = (type == H5FD_MEM_DRAW)
+ ? &file->raw[bin_i]
+ : &file->meta[bin_i];
+
+ /* Store collected stats in appropriate bin
+ */
+ if (bin->count == 0) {
+ bin->min = size;
+ bin->max = size;
+ }
+ else {
+ if (size < bin->min) {
+ bin->min = size;
+ }
+ if (size > bin->max) {
+ bin->max = size;
+ }
+ }
+ bin->count++;
+ bin->bytes += (unsigned long long)size;
+
+#endif /* ROS3_STATS */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* end H5FD_ros3_read() */
+
+
+/*-------------------------------------------------------------------------
+ *
+ * Function: H5FD_ros3_write()
+ *
+ * Purpose:
+ *
+ * Write bytes to file.
+ * UNSUPPORTED IN READ-ONLY ROS3 VFD.
+ *
+ * Return:
+ *
+ * FAIL (Not possible with Read-Only S3 file.)
+ *
+ * Programmer: Jacob Smith
+ * 2017-10-23
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_ros3_write(H5FD_t H5_ATTR_UNUSED *_file,
+ H5FD_mem_t H5_ATTR_UNUSED type,
+ hid_t H5_ATTR_UNUSED dxpl_id,
+ haddr_t H5_ATTR_UNUSED addr,
+ size_t H5_ATTR_UNUSED size,
+ const void H5_ATTR_UNUSED *buf)
+{
+ herr_t ret_value = FAIL;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+#if ROS3_DEBUG
+ HDfprintf(stdout, "H5FD_ros3_write() called.\n");
+#endif
+
+ HGOTO_ERROR(H5E_VFL, H5E_UNSUPPORTED, FAIL,
+ "cannot write to read-only file.")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5FD_ros3_write() */
+
+
+/*-------------------------------------------------------------------------
+ *
+ * Function: H5FD_ros3_truncate()
+ *
+ * Purpose:
+ *
+ * Makes sure that the true file size is the same (or larger)
+ * than the end-of-address.
+ *
+ * NOT POSSIBLE ON READ-ONLY S3 FILES.
+ *
+ * Return:
+ *
+ * FAIL (Not possible on Read-Only S3 files.)
+ *
+ * Programmer: Jacob Smith
+ * 2017-10-23
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_ros3_truncate(H5FD_t H5_ATTR_UNUSED *_file,
+ hid_t H5_ATTR_UNUSED dxpl_id,
+ hbool_t H5_ATTR_UNUSED closing)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+#if ROS3_DEBUG
+ HDfprintf(stdout, "H5FD_ros3_truncate() called.\n");
+#endif
+
+ HGOTO_ERROR(H5E_VFL, H5E_UNSUPPORTED, FAIL,
+ "cannot truncate read-only file.")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* end H5FD_ros3_truncate() */
+
+
+/*-------------------------------------------------------------------------
+ *
+ * Function: H5FD_ros3_lock()
+ *
+ * Purpose:
+ *
+ * Place an advisory lock on a file.
+ * No effect on Read-Only S3 file.
+ *
+ * Suggestion: remove lock/unlock from class
+ * > would result in error at H5FD_[un]lock() (H5FD.c)
+ *
+ * Return:
+ *
+ * SUCCEED (No-op always succeeds)
+ *
+ * Programmer: Jacob Smith
+ * 2017-11-03
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_ros3_lock(H5FD_t H5_ATTR_UNUSED *_file,
+ hbool_t H5_ATTR_UNUSED rw)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_LEAVE_NOAPI(SUCCEED)
+
+} /* end H5FD_ros3_lock() */
+
+
+/*-------------------------------------------------------------------------
+ *
+ * Function: H5FD_ros3_unlock()
+ *
+ * Purpose:
+ *
+ * Remove the existing lock on the file.
+ * No effect on Read-Only S3 file.
+ *
+ * Return:
+ *
+ * SUCCEED (No-op always succeeds)
+ *
+ * Programmer: Jacob Smith
+ * 2017-11-03
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_ros3_unlock(H5FD_t H5_ATTR_UNUSED *_file)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_LEAVE_NOAPI(SUCCEED)
+
+} /* end H5FD_ros3_unlock() */
+
+#endif /* H5_HAVE_ROS3_VFD */
+
diff --git a/src/H5FDros3.h b/src/H5FDros3.h
new file mode 100644
index 0000000..457326e
--- /dev/null
+++ b/src/H5FDros3.h
@@ -0,0 +1,105 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Read-Only S3 Virtual File Driver (VFD)
+ *
+ * Programmer: John Mainzer
+ * 2017-10-10
+ *
+ * Purpose: The public header file for the ros3 driver.
+ */
+#ifndef H5FDros3_H
+#define H5FDros3_H
+
+#ifdef H5_HAVE_ROS3_VFD
+#define H5FD_ROS3 (H5FD_ros3_init())
+#else
+#define H5FD_ROS3 (H5I_INVALID_HID)
+#endif /* H5_HAVE_ROS3_VFD */
+
+#ifdef H5_HAVE_ROS3_VFD
+
+/****************************************************************************
+ *
+ * Structure: H5FD_ros3_fapl_t
+ *
+ * Purpose:
+ *
+ * H5FD_ros3_fapl_t is a public structure that is used to pass S3
+ * authentication data to the appropriate S3 VFD via the FAPL. A pointer
+ * to an instance of this structure is a parameter to H5Pset_fapl_ros3()
+ * and H5Pget_fapl_ros3().
+ *
+ *
+ *
+ * `version` (int32_t)
+ *
+ * Version number of the H5FD_ros3_fapl_t structure. Any instance passed
+ * to the above calls must have a recognized version number, or an error
+ * will be flagged.
+ *
+ * This field should be set to H5FD_CURR_ROS3_FAPL_T_VERSION.
+ *
+ * `authenticate` (hbool_t)
+ *
+ * Flag TRUE or FALSE whether or not requests are to be authenticated
+ * with the AWS4 algorithm.
+ * If TRUE, `aws_region`, `secret_id`, and `secret_key` must be populated.
+ * If FALSE, those three components are unused.
+ *
+ * `aws_region` (char[])
+ *
+ * String: name of the AWS "region" of the host, e.g. "us-east-1".
+ *
+ * `secret_id` (char[])
+ *
+ * String: "Access ID" for the resource.
+ *
+ * `secret_key` (char[])
+ *
+ * String: "Secret Access Key" associated with the ID and resource.
+ *
+ ****************************************************************************/
+
+#define H5FD_CURR_ROS3_FAPL_T_VERSION 1
+
+#define H5FD_ROS3_MAX_REGION_LEN 32
+#define H5FD_ROS3_MAX_SECRET_ID_LEN 128
+#define H5FD_ROS3_MAX_SECRET_KEY_LEN 128
+
+typedef struct H5FD_ros3_fapl_t {
+ int32_t version;
+ hbool_t authenticate;
+ char aws_region[H5FD_ROS3_MAX_REGION_LEN + 1];
+ char secret_id[H5FD_ROS3_MAX_SECRET_ID_LEN + 1];
+ char secret_key[H5FD_ROS3_MAX_SECRET_KEY_LEN + 1];
+} H5FD_ros3_fapl_t;
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+H5_DLL hid_t H5FD_ros3_init(void);
+H5_DLL herr_t H5Pget_fapl_ros3(hid_t fapl_id, H5FD_ros3_fapl_t *fa_out);
+H5_DLL herr_t H5Pset_fapl_ros3(hid_t fapl_id, H5FD_ros3_fapl_t *fa);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* H5_HAVE_ROS3_VFD */
+
+#endif /* ifndef H5FDros3_H */
+
+
diff --git a/src/H5FDs3comms.c b/src/H5FDs3comms.c
new file mode 100644
index 0000000..f08e9d5
--- /dev/null
+++ b/src/H5FDs3comms.c
@@ -0,0 +1,3593 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*****************************************************************************
+ * Read-Only S3 Virtual File Driver (VFD)
+ *
+ * Source for S3 Communications module
+ *
+ * ***NOT A FILE DRIVER***
+ *
+ * Provide functions and structures required for interfacing with Amazon
+ * Simple Storage Service (S3).
+ *
+ * Provide S3 object access as if it were a local file.
+ *
+ * Connect to remote host, send and receive HTTP requests and responses
+ * as part of the AWS REST API, authenticating requests as appropriate.
+ *
+ * Programmer: Jacob Smith
+ * 2017-11-30
+ *
+ *****************************************************************************/
+
+/****************/
+/* Module Setup */
+/****************/
+
+/***********/
+/* Headers */
+/***********/
+
+#include "H5private.h" /* generic functions */
+#include "H5Eprivate.h" /* error handling */
+#include "H5MMprivate.h" /* memory management */
+#include "H5FDs3comms.h" /* S3 Communications */
+
+/****************/
+/* Local Macros */
+/****************/
+
+#ifdef H5_HAVE_ROS3_VFD
+
+/* toggle debugging (enable with 1)
+ */
+#define S3COMMS_DEBUG 0
+
+/* manipulate verbosity of CURL output
+ * operates separately from S3COMMS_DEBUG
+ *
+ * 0 -> no explicit curl output
+ * 1 -> on error, print failure info to stderr
+ * 2 -> in addition to above, print information for all performs; sets all
+ * curl handles with CURLOPT_VERBOSE
+ */
+#define S3COMMS_CURL_VERBOSITY 0
+
+/* size to allocate for "bytes=<first_byte>[-<last_byte>]" HTTP Range value
+ */
+#define S3COMMS_MAX_RANGE_STRING_SIZE 128
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+/********************/
+/* Local Structures */
+/********************/
+
+/* struct s3r_datastruct
+ * Structure passed to curl write callback
+ * pointer to data region and record of bytes written (offset)
+ */
+struct s3r_datastruct {
+ unsigned long magic;
+ char *data;
+ size_t size;
+};
+#define S3COMMS_CALLBACK_DATASTRUCT_MAGIC 0x28c2b2ul
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+size_t curlwritecallback(char *ptr,
+ size_t size,
+ size_t nmemb,
+ void *userdata);
+
+herr_t H5FD_s3comms_s3r_getsize(s3r_t *handle);
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/*************/
+/* Functions */
+/*************/
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: curlwritecallback()
+ *
+ * Purpose:
+ *
+ * Function called by CURL to write received data.
+ *
+ * Writes bytes to `userdata`.
+ *
+ * Internally manages number of bytes processed.
+ *
+ * Return:
+ *
+ * - Number of bytes processed.
+ * - Should equal number of bytes passed to callback.
+ * - Failure will result in curl error: CURLE_WRITE_ERROR.
+ *
+ * Programmer: Jacob Smith
+ * 2017-08-17
+ *
+ *----------------------------------------------------------------------------
+ */
+size_t
+curlwritecallback(char *ptr,
+ size_t size,
+ size_t nmemb,
+ void *userdata)
+{
+ struct s3r_datastruct *sds = (struct s3r_datastruct *)userdata;
+ size_t product = (size * nmemb);
+ size_t written = 0;
+
+ if (sds->magic != S3COMMS_CALLBACK_DATASTRUCT_MAGIC) {
+ return written;
+ }
+
+ if (size > 0) {
+ HDmemcpy(&(sds->data[sds->size]), ptr, product);
+ sds->size += product;
+ written = product;
+ }
+
+ return written;
+
+} /* end curlwritecallback() */
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: H5FD_s3comms_hrb_node_set()
+ *
+ * Purpose:
+ *
+ * Create, insert, modify, and remove elements in a field node list.
+ *
+ * `name` cannot be null; will return FAIL and list will be unaltered.
+ *
+ * Entries are accessed via the lowercase representation of their name:
+ * "Host", "host", and "hOSt" would all access the same node,
+ * but name's case is relevant in HTTP request output.
+ *
+ * List pointer `L` must always point to either of :
+ * - header node with lowest alphabetical order (by lowername)
+ * - NULL, if list is empty
+ *
+ * Types of operations:
+ *
+ * - CREATE
+ * - If `L` is NULL and `name` and `value` are not NULL,
+ * a new node is created at `L`, starting a list.
+ * - MODIFY
+ * - If a node is found with a matching lowercase name and `value`
+ * is not NULL, the existing name, value, and cat values are released
+ * and replaced with the new data.
+ * - No modifications are made to the list pointers.
+ * - REMOVE
+ * - If `value` is NULL, will attempt to remove node with matching
+ * lowercase name.
+ * - If no match found, returns FAIL and list is not modified.
+ * - When removing a node, all its resources is released.
+ * - If removing the last node in the list, list pointer is set to NULL.
+ * - INSERT
+ * - If no nodes exists with matching lowercase name and `value`
+ * is not NULL, a new node is created, inserted into list
+ * alphabetically by lowercase name.
+ *
+ * Return:
+ *
+ * - SUCCESS: `SUCCEED`
+ * - List was successfully modified
+ * - FAILURE: `FAIL`
+ * - Unable to perform operation
+ * - Forbidden (attempting to remove absent node, e.g.)
+ * - Internal error
+ *
+ * Programmer: Jacob Smith
+ * 2017-09-22
+ *
+ *----------------------------------------------------------------------------
+ */
+herr_t
+H5FD_s3comms_hrb_node_set(
+ hrb_node_t **L,
+ const char *name,
+ const char *value)
+{
+ size_t i = 0;
+ char *valuecpy = NULL;
+ char *namecpy = NULL;
+ size_t namelen = 0;
+ char *lowername = NULL;
+ char *nvcat = NULL;
+ hrb_node_t *node_ptr = NULL;
+ hrb_node_t *new_node = NULL;
+ hbool_t is_looking = TRUE;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+#if S3COMMS_DEBUG
+ HDfprintf(stdout, "called H5FD_s3comms_hrb_node_set.\n");
+ HDprintf("NAME: %s\n", name);
+ HDprintf("VALUE: %s\n", value);
+ HDprintf("LIST:\n->");
+ for (node_ptr = (*L); node_ptr != NULL; node_ptr = node_ptr->next) {
+ HDfprintf(stdout, "{%s}\n->", node_ptr->cat);
+ }
+ HDprintf("(null)\n");
+ fflush(stdout);
+ node_ptr = NULL;
+#endif
+
+ if (name == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "unable to operate on null name.\n");
+ }
+ namelen = HDstrlen(name);
+
+ /***********************
+ * PREPARE ALL STRINGS *
+ **********************/
+
+ /* copy and lowercase name
+ */
+ lowername = (char *)H5MM_malloc(sizeof(char) * (namelen + 1));
+ if (lowername == NULL) {
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
+ "cannot make space for lowercase name copy.\n");
+ }
+ for (i = 0; i < namelen; i++) {
+ lowername[i] = (char)tolower((int)name[i]);
+ }
+ lowername[namelen] = 0;
+
+ /* If value supplied, copy name, value, and concatenated "name: value".
+ * If NULL, we will be removing a node or doing nothing, so no need for
+ * copies
+ */
+ if (value != NULL) {
+ int ret = 0;
+ size_t valuelen = HDstrlen(value);
+ size_t catlen = namelen + valuelen + 2; /* +2 from ": " */
+ size_t catwrite = catlen + 3; /* 3 not 1 to quiet compiler warning */
+
+
+ namecpy = (char *)H5MM_malloc(sizeof(char) * (namelen + 1));
+ if (namecpy == NULL) {
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
+ "cannot make space for name copy.\n");
+ }
+ HDmemcpy(namecpy, name, (namelen + 1));
+
+ valuecpy = (char *)H5MM_malloc(sizeof(char) * (valuelen + 1));
+ if (valuecpy == NULL) {
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
+ "cannot make space for value copy.\n");
+ }
+ HDmemcpy(valuecpy, value, (valuelen + 1));
+
+ nvcat = (char *)H5MM_malloc(sizeof(char) * catwrite);
+ if (nvcat == NULL) {
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
+ "cannot make space for concatenated string.\n");
+ }
+ ret = HDsnprintf(nvcat, catwrite, "%s: %s", name, value);
+ if (ret < 0 || (size_t)ret > catlen) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "cannot concatenate `%s: %s", name, value);
+ }
+ HDassert( catlen == HDstrlen(nvcat) );
+
+ /* create new_node, should we need it
+ */
+ new_node = (hrb_node_t *)H5MM_malloc(sizeof(hrb_node_t));
+ if (new_node == NULL) {
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
+ "cannot make space for new set.\n");
+ }
+
+ new_node->magic = S3COMMS_HRB_NODE_MAGIC;
+ new_node->name = NULL;
+ new_node->value = NULL;
+ new_node->cat = NULL;
+ new_node->lowername = NULL;
+ new_node->next = NULL;
+ }
+
+ /***************
+ * ACT ON LIST *
+ ***************/
+
+ if (*L == NULL) {
+ if (value == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "trying to remove node from empty list");
+ }
+ else {
+#if S3COMMS_DEBUG
+HDprintf("CREATE NEW\n"); fflush(stdout);
+#endif
+ /*******************
+ * CREATE NEW LIST *
+ *******************/
+
+ new_node->cat = nvcat;
+ new_node->name = namecpy;
+ new_node->lowername = lowername;
+ new_node->value = valuecpy;
+
+ *L = new_node;
+ goto done; /* bypass further seeking */
+ }
+ }
+
+ /* sanity-check pointer passed in
+ */
+ HDassert( (*L) != NULL );
+ HDassert( (*L)->magic == S3COMMS_HRB_NODE_MAGIC );
+ node_ptr = (*L);
+
+ /* Check whether to modify/remove first node in list
+ */
+ if (strcmp(lowername, node_ptr->lowername) == 0) {
+
+ is_looking = FALSE;
+
+ if (value == NULL) {
+#if S3COMMS_DEBUG
+HDprintf("REMOVE HEAD\n"); fflush(stdout);
+#endif
+ /***************
+ * REMOVE HEAD *
+ ***************/
+
+ *L = node_ptr->next;
+
+#if S3COMMS_DEBUG
+HDprintf("FREEING CAT (node)\n"); fflush(stdout);
+#endif
+ H5MM_xfree(node_ptr->cat);
+#if S3COMMS_DEBUG
+HDprintf("FREEING LOWERNAME (node)\n"); fflush(stdout);
+#endif
+ H5MM_xfree(node_ptr->lowername);
+#if S3COMMS_DEBUG
+HDprintf("FREEING NAME (node)\n"); fflush(stdout);
+#endif
+ H5MM_xfree(node_ptr->name);
+#if S3COMMS_DEBUG
+HDprintf("FREEING VALUE (node)\n"); fflush(stdout);
+#endif
+ H5MM_xfree(node_ptr->value);
+#if S3COMMS_DEBUG
+HDprintf("MAGIC OK? %s\n",
+ (node_ptr->magic == S3COMMS_HRB_NODE_MAGIC) ? "YES" : "NO");
+fflush(stdout);
+#endif
+ HDassert( node_ptr->magic == S3COMMS_HRB_NODE_MAGIC );
+ node_ptr->magic += 1ul;
+#if S3COMMS_DEBUG
+HDprintf("FREEING POINTER\n"); fflush(stdout);
+#endif
+ H5MM_xfree(node_ptr);
+
+#if S3COMMS_DEBUG
+HDprintf("FREEING WORKING LOWERNAME\n"); fflush(stdout);
+#endif
+ H5MM_xfree(lowername); lowername = NULL;
+ }
+ else {
+#if S3COMMS_DEBUG
+HDprintf("MODIFY HEAD\n"); fflush(stdout);
+#endif
+ /***************
+ * MODIFY HEAD *
+ ***************/
+
+ H5MM_xfree(node_ptr->cat);
+ H5MM_xfree(node_ptr->name);
+ H5MM_xfree(node_ptr->value);
+
+ node_ptr->name = namecpy;
+ node_ptr->value = valuecpy;
+ node_ptr->cat = nvcat;
+
+ H5MM_xfree(lowername);
+ lowername = NULL;
+ new_node->magic += 1ul;
+ H5MM_xfree(new_node);
+ new_node = NULL;
+ }
+ }
+ else
+ if (strcmp(lowername, node_ptr->lowername) < 0) {
+
+ is_looking = FALSE;
+
+ if (value == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "trying to remove a node 'before' head");
+ }
+ else {
+#if S3COMMS_DEBUG
+HDprintf("PREPEND NEW HEAD\n"); fflush(stdout);
+#endif
+ /*******************
+ * INSERT NEW HEAD *
+ *******************/
+
+ new_node->name = namecpy;
+ new_node->value = valuecpy;
+ new_node->lowername = lowername;
+ new_node->cat = nvcat;
+ new_node->next = node_ptr;
+ *L = new_node;
+ }
+ }
+
+ /***************
+ * SEARCH LIST *
+ ***************/
+
+ while (is_looking) {
+ if (node_ptr->next == NULL) {
+
+ is_looking = FALSE;
+
+ if (value == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "trying to remove absent node");
+ }
+ else {
+#if S3COMMS_DEBUG
+HDprintf("APPEND A NODE\n"); fflush(stdout);
+#endif
+ /*******************
+ * APPEND NEW NODE *
+ *******************/
+
+ HDassert( strcmp(lowername, node_ptr->lowername) > 0 );
+ new_node->name = namecpy;
+ new_node->value = valuecpy;
+ new_node->lowername = lowername;
+ new_node->cat = nvcat;
+ node_ptr->next = new_node;
+ }
+ }
+ else
+ if (strcmp(lowername, node_ptr->next->lowername) < 0) {
+
+ is_looking = FALSE;
+
+ if (value == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "trying to remove absent node");
+ }
+ else {
+#if S3COMMS_DEBUG
+HDprintf("INSERT A NODE\n"); fflush(stdout);
+#endif
+ /*******************
+ * INSERT NEW NODE *
+ *******************/
+
+ HDassert( strcmp(lowername, node_ptr->lowername) > 0 );
+ new_node->name = namecpy;
+ new_node->value = valuecpy;
+ new_node->lowername = lowername;
+ new_node->cat = nvcat;
+ new_node->next = node_ptr->next;
+ node_ptr->next = new_node;
+ }
+ }
+ else
+ if (strcmp(lowername, node_ptr->next->lowername) == 0) {
+
+ is_looking = FALSE;
+
+ if (value == NULL) {
+ /*****************
+ * REMOVE A NODE *
+ *****************/
+
+ hrb_node_t *tmp = node_ptr->next;
+ node_ptr->next = tmp->next;
+
+#if S3COMMS_DEBUG
+HDprintf("REMOVE A NODE\n"); fflush(stdout);
+#endif
+ H5MM_xfree(tmp->cat);
+ H5MM_xfree(tmp->lowername);
+ H5MM_xfree(tmp->name);
+ H5MM_xfree(tmp->value);
+
+ HDassert( tmp->magic == S3COMMS_HRB_NODE_MAGIC );
+ tmp->magic += 1ul;
+ H5MM_xfree(tmp);
+
+ H5MM_xfree(lowername);
+ lowername = NULL;
+ }
+ else {
+#if S3COMMS_DEBUG
+HDprintf("MODIFY A NODE\n"); fflush(stdout);
+#endif
+ /*****************
+ * MODIFY A NODE *
+ *****************/
+
+ node_ptr = node_ptr->next;
+ H5MM_xfree(node_ptr->name);
+ H5MM_xfree(node_ptr->value);
+ H5MM_xfree(node_ptr->cat);
+
+ HDassert( new_node->magic == S3COMMS_HRB_NODE_MAGIC );
+ new_node->magic += 1ul;
+ H5MM_xfree(new_node);
+ H5MM_xfree(lowername);
+ new_node = NULL;
+ lowername = NULL;
+
+ node_ptr->name = namecpy;
+ node_ptr->value = valuecpy;
+ node_ptr->cat = nvcat;
+ }
+ }
+ else {
+ /****************
+ * KEEP LOOKING *
+ ****************/
+
+ node_ptr = node_ptr->next;
+ }
+ } /* end while is_looking */
+
+done:
+ if (ret_value == FAIL) {
+ /* clean up
+ */
+ if (nvcat != NULL) { H5MM_xfree(nvcat); }
+ if (namecpy != NULL) { H5MM_xfree(namecpy); }
+ if (lowername != NULL) { H5MM_xfree(lowername); }
+ if (valuecpy != NULL) { H5MM_xfree(valuecpy); }
+ if (new_node != NULL) {
+ HDassert( new_node->magic == S3COMMS_HRB_NODE_MAGIC );
+ new_node->magic += 1ul;
+ H5MM_xfree(new_node);
+ }
+ }
+
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5FD_s3comms_hrb_node_set() */
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: H5FD_s3comms_hrb_destroy()
+ *
+ * Purpose:
+ *
+ * Destroy and free resources _directly_ associated with an HTTP Buffer.
+ *
+ * Takes a pointer to pointer to the buffer structure.
+ * This allows for the pointer itself to be NULLed from within the call.
+ *
+ * If buffer or buffer pointer is NULL, there is no effect.
+ *
+ * Headers list at `first_header` is not touched.
+ *
+ * - Programmer should re-use or destroy `first_header` pointer
+ * (hrb_node_t *) as suits their purposes.
+ * - Recommend fetching prior to destroy()
+ * e.g., `reuse_node = hrb_to_die->first_header; destroy(hrb_to_die);`
+ * or maintaining an external reference.
+ * - Destroy node/list separately as appropriate
+ * - Failure to account for this will result in a memory leak.
+ *
+ * Return:
+ *
+ * - SUCCESS: `SUCCEED`
+ * - successfully released buffer resources
+ * - if `buf` is NULL or `*buf` is NULL, no effect
+ * - FAILURE: `FAIL`
+ * - `buf->magic != S3COMMS_HRB_MAGIC`
+ *
+ * Programmer: Jacob Smith
+ * 2017-07-21
+ *
+ *----------------------------------------------------------------------------
+ */
+herr_t
+H5FD_s3comms_hrb_destroy(hrb_t **_buf)
+{
+ hrb_t *buf = NULL;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+#if S3COMMS_DEBUG
+ HDfprintf(stdout, "called H5FD_s3comms_hrb_destroy.\n");
+#endif
+
+ if (_buf != NULL && *_buf != NULL) {
+ buf = *_buf;
+ if (buf->magic != S3COMMS_HRB_MAGIC) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "pointer's magic does not match.\n");
+ }
+
+ H5MM_xfree(buf->verb);
+ H5MM_xfree(buf->version);
+ H5MM_xfree(buf->resource);
+ buf->magic += 1ul;
+ H5MM_xfree(buf);
+ *_buf = NULL;
+ } /* end if `_buf` has some value */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_s3comms_hrb_destroy() */
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: H5FD_s3comms_hrb_init_request()
+ *
+ * Purpose:
+ *
+ * Create a new HTTP Request Buffer
+ *
+ * All non-null arguments should be null-terminated strings.
+ *
+ * If `verb` is NULL, defaults to "GET".
+ * If `http_version` is NULL, defaults to "HTTP/1.1".
+ *
+ * `resource` cannot be NULL; should be string beginning with slash
+ * character ('/').
+ *
+ * All strings are copied into the structure, making them safe from
+ * modification in source strings.
+ *
+ * Return:
+ *
+ * - SUCCESS: pointer to new `hrb_t`
+ * - FAILURE: `NULL`
+ *
+ * Programmer: Jacob Smith
+ * 2017-07-21
+ *
+ *----------------------------------------------------------------------------
+ */
+hrb_t *
+H5FD_s3comms_hrb_init_request(const char *_verb,
+ const char *_resource,
+ const char *_http_version)
+{
+ hrb_t *request = NULL;
+ char *res = NULL;
+ size_t reslen = 0;
+ hrb_t *ret_value = NULL;
+ char *verb = NULL;
+ size_t verblen = 0;
+ char *vrsn = NULL;
+ size_t vrsnlen = 0;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+#if S3COMMS_DEBUG
+ HDfprintf(stdout, "called H5FD_s3comms_hrb_init_request.\n");
+#endif
+
+ if (_resource == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL,
+ "resource string cannot be null.\n");
+ }
+
+ /* populate valid NULLs with defaults
+ */
+ if (_verb == NULL) {
+ _verb = "GET";
+ }
+
+ if (_http_version == NULL) {
+ _http_version = "HTTP/1.1";
+ }
+
+ /* malloc space for and prepare structure
+ */
+ request = (hrb_t *)H5MM_malloc(sizeof(hrb_t));
+ if (request == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTALLOC, NULL,
+ "no space for request structure");
+ }
+ request->magic = S3COMMS_HRB_MAGIC;
+ request->body = NULL;
+ request->body_len = 0;
+ request->first_header = NULL;
+
+
+
+ /* malloc and copy strings for the structure
+ */
+ reslen = HDstrlen(_resource);
+
+ if (_resource[0] == '/') {
+ res = (char *)H5MM_malloc(sizeof(char) * (reslen+1));
+ if (res == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTALLOC, NULL,
+ "no space for resource string");
+ }
+ HDmemcpy(res, _resource, (reslen+1));
+ }
+ else {
+ res = (char *)H5MM_malloc(sizeof(char) * (reslen+2));
+ if (res == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTALLOC, NULL,
+ "no space for resource string");
+ }
+ *res = '/';
+ HDmemcpy((&res[1]), _resource, (reslen+1));
+ HDassert( (reslen+1) == HDstrlen(res) );
+ } /* end if (else resource string not starting with '/') */
+
+ verblen = HDstrlen(_verb) + 1;
+ verb = (char *)H5MM_malloc(sizeof(char) * verblen);
+ if (verb == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL,
+ "no space for verb string");
+ }
+ HDstrncpy(verb, _verb, verblen);
+
+ vrsnlen = HDstrlen(_http_version) + 1;
+ vrsn = (char *)H5MM_malloc(sizeof(char) * vrsnlen);
+ if (vrsn == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL,
+ "no space for http-version string");
+ }
+ HDstrncpy(vrsn, _http_version, vrsnlen);
+
+
+
+ /* place new copies into structure
+ */
+ request->resource = res;
+ request->verb = verb;
+ request->version = vrsn;
+
+ ret_value = request;
+
+done:
+ /* if there is an error, clean up after ourselves
+ */
+ if (ret_value == NULL) {
+ if (request != NULL) H5MM_xfree(request);
+ if (vrsn != NULL) H5MM_xfree(vrsn);
+ if (verb != NULL) H5MM_xfree(verb);
+ if (res != NULL) H5MM_xfree(res);
+ }
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_s3comms_hrb_init_request() */
+
+
+/****************************************************************************
+ * S3R FUNCTIONS
+ ****************************************************************************/
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: H5FD_s3comms_s3r_close()
+ *
+ * Purpose:
+ *
+ * Close communications through given S3 Request Handle (`s3r_t`)
+ * and clean up associated resources.
+ *
+ * Return:
+ *
+ * - SUCCESS: `SUCCEED`
+ * - FAILURE: `FAIL`
+ * - fails if handle is null or has invalid magic number
+ *
+ *
+ * Programmer: Jacob Smith
+ * 2017-08-31
+ *
+ *----------------------------------------------------------------------------
+ */
+herr_t
+H5FD_s3comms_s3r_close(s3r_t *handle)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+#if S3COMMS_DEBUG
+ HDfprintf(stdout, "called H5FD_s3comms_s3r_close.\n");
+#endif
+
+ if (handle == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "handle cannot be null.\n");
+ }
+ if (handle->magic != S3COMMS_S3R_MAGIC) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "handle has invalid magic.\n");
+ }
+
+ curl_easy_cleanup(handle->curlhandle);
+
+ H5MM_xfree(handle->secret_id);
+ H5MM_xfree(handle->region);
+ H5MM_xfree(handle->signing_key);
+
+ HDassert( handle->httpverb != NULL );
+ H5MM_xfree(handle->httpverb);
+
+ if (FAIL == H5FD_s3comms_free_purl(handle->purl)) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "unable to release parsed url structure")
+ }
+
+ H5MM_xfree(handle);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5FD_s3comms_s3r_close */
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: H5FD_s3comms_s3r_get_filesize()
+ *
+ * Purpose:
+ *
+ * Retrieve the filesize of an open request handle.
+ *
+ * Wrapper "getter" to hide implementation details.
+ *
+ *
+ * Return:
+ *
+ * - SUCCESS: size of file, in bytes, if handle is valid.
+ * - FAILURE: 0, if handle is NULL or undefined.
+ *
+ * Programmer: Jacob Smith 2017-01-14
+ *
+ *----------------------------------------------------------------------------
+ */
+size_t
+H5FD_s3comms_s3r_get_filesize(s3r_t *handle)
+{
+ size_t ret_value = 0;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ if (handle != NULL) {
+ ret_value = handle->filesize;
+ }
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5FD_s3comms_s3r_get_filesize */
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: H5FD_s3comms_s3r_getsize()
+ *
+ * Purpose:
+ *
+ * Get the number of bytes of handle's target resource.
+ *
+ * Sets handle and curlhandle with to enact an HTTP HEAD request on file,
+ * and parses received headers to extract "Content-Length" from response
+ * headers, storing file size at `handle->filesize`.
+ *
+ * Critical step in opening (initiating) an `s3r_t` handle.
+ *
+ * Wraps `s3r_read()`.
+ * Sets curlhandle to write headers to a temporary buffer (using extant
+ * write callback) and provides no buffer for body.
+ *
+ * Upon exit, unsets HTTP HEAD settings from curl handle, returning to
+ * initial state. In event of error, curl handle state is undefined and is
+ * not to be trusted.
+ *
+ * Return:
+ *
+ * - SUCCESS: `SUCCEED`
+ * - FAILURE: `FAIL`
+ *
+ * Programmer: Jacob Smith
+ * 2017-08-23
+ *
+ *----------------------------------------------------------------------------
+ */
+herr_t
+H5FD_s3comms_s3r_getsize(s3r_t *handle)
+{
+ uintmax_t content_length = 0;
+ CURL *curlh = NULL;
+ char *end = NULL;
+ char *headerresponse = NULL;
+ struct s3r_datastruct sds = {
+ S3COMMS_CALLBACK_DATASTRUCT_MAGIC,
+ NULL,
+ 0 };
+ char *start = NULL;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+#if S3COMMS_DEBUG
+ HDfprintf(stdout, "called H5FD_s3comms_s3r_getsize.\n");
+#endif
+
+ if (handle == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "handle cannot be null.\n");
+ }
+ if (handle->magic != S3COMMS_S3R_MAGIC) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "handle has invalid magic.\n");
+ }
+ if (handle->curlhandle == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "handle has bad (null) curlhandle.\n")
+ }
+
+ /********************
+ * PREPARE FOR HEAD *
+ ********************/
+
+ curlh = handle->curlhandle;
+
+ if ( CURLE_OK !=
+ curl_easy_setopt(curlh,
+ CURLOPT_NOBODY,
+ 1L) )
+ {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "error while setting CURL option (CURLOPT_NOBODY). "
+ "(placeholder flags)");
+ }
+
+ if ( CURLE_OK !=
+ curl_easy_setopt(curlh,
+ CURLOPT_HEADERDATA,
+ &sds) )
+ {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "error while setting CURL option (CURLOPT_HEADERDATA). "
+ "(placeholder flags)");
+ }
+
+ HDassert( handle->httpverb == NULL );
+ handle->httpverb = (char *)H5MM_malloc(sizeof(char) * 16);
+ if (handle->httpverb == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTALLOC, FAIL,
+ "unable to allocate space for S3 request HTTP verb");
+ }
+ HDmemcpy(handle->httpverb, "HEAD", 5);
+
+ headerresponse = (char *)H5MM_malloc(sizeof(char) * CURL_MAX_HTTP_HEADER);
+ if (headerresponse == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTALLOC, FAIL,
+ "unable to allocate space for curl header response");
+ }
+ sds.data = headerresponse;
+
+ /*******************
+ * PERFORM REQUEST *
+ *******************/
+
+ /* these parameters fetch the entire file,
+ * but, with a NULL destination and NOBODY and HEADERDATA supplied above,
+ * only http metadata will be sent by server and recorded by s3comms
+ */
+ if (FAIL ==
+ H5FD_s3comms_s3r_read(handle, 0, 0, NULL) )
+ {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "problem in reading during getsize.\n");
+ }
+
+ if (sds.size > CURL_MAX_HTTP_HEADER) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "HTTP metadata buffer overrun\n");
+ } else if (sds.size == 0) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "No HTTP metadata\n");
+#if S3COMMS_DEBUG
+ } else {
+ HDfprintf(stderr, "GETSIZE: OK\n");
+#endif
+ }
+
+
+ /******************
+ * PARSE RESPONSE *
+ ******************/
+
+ start = strstr(headerresponse,
+ "\r\nContent-Length: ");
+ if (start == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "could not find \"Content-Length\" in response.\n");
+ }
+
+ /* move "start" to beginning of value in line; find end of line
+ */
+ start = start + HDstrlen("\r\nContent-Length: ");
+ end = strstr(start, "\r\n");
+ if (end == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "could not find end of content length line");
+ }
+
+ /* place null terminator at end of numbers
+ */
+ *end = '\0';
+
+ content_length = strtoumax((const char *)start,
+ NULL,
+ 0);
+
+ if (UINTMAX_MAX > SIZE_MAX && content_length > SIZE_MAX) {
+ HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, FAIL, "content_length overflows size_t\n");
+ }
+
+ if (content_length == 0 ||
+ errno == ERANGE) /* errno set by strtoumax*/
+ {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "could not convert found \"Content-Length\" response (\"%s\")",
+ start); /* range is null-terminated, remember */
+ }
+
+ handle->filesize = (size_t)content_length;
+
+ /**********************
+ * UNDO HEAD SETTINGS *
+ **********************/
+
+ if ( CURLE_OK !=
+ curl_easy_setopt(curlh,
+ CURLOPT_NOBODY,
+ NULL) )
+ {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "error while setting CURL option (CURLOPT_NOBODY). "
+ "(placeholder flags)");
+ }
+
+ if ( CURLE_OK !=
+ curl_easy_setopt(curlh,
+ CURLOPT_HEADERDATA,
+ NULL) )
+ {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "error while setting CURL option (CURLOPT_HEADERDATA). "
+ "(placeholder flags)");
+ }
+
+done:
+ H5MM_xfree(headerresponse);
+ sds.magic += 1; /* set to bad magic */
+
+ FUNC_LEAVE_NOAPI(ret_value);
+
+} /* H5FD_s3comms_s3r_getsize */
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: H5FD_s3comms_s3r_open()
+ *
+ * Purpose:
+ *
+ * Logically 'open' a file hosted on S3.
+ *
+ * - create new Request Handle
+ * - copy supplied url
+ * - copy authentication info if supplied
+ * - create CURL handle
+ * - fetch size of file
+ * - connect with server and execute HEAD request
+ * - return request handle ready for reads
+ *
+ * To use 'default' port to connect, `port` should be 0.
+ *
+ * To prevent AWS4 authentication, pass null pointer to `region`, `id`,
+ * and `signing_key`.
+ *
+ * Uses `H5FD_s3comms_parse_url()` to validate and parse url input.
+ *
+ * Return:
+ *
+ * - SUCCESS: Pointer to new request handle.
+ * - FAILURE: NULL
+ * - occurs if:
+ * - authentication strings are inconsistent
+ * - must _all_ be null, or have at least `region` and `id`
+ * - url is NULL (no filename)
+ * - unable to parse url (malformed?)
+ * - error while performing `getsize()`
+ *
+ * Programmer: Jacob Smith
+ * 2017-09-01
+ *
+ *----------------------------------------------------------------------------
+ */
+s3r_t *
+H5FD_s3comms_s3r_open(const char *url,
+ const char *region,
+ const char *id,
+ const unsigned char *signing_key)
+{
+ size_t tmplen = 0;
+ CURL *curlh = NULL;
+ s3r_t *handle = NULL;
+ parsed_url_t *purl = NULL;
+ s3r_t *ret_value = NULL;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+#if S3COMMS_DEBUG
+ HDfprintf(stdout, "called H5FD_s3comms_s3r_open.\n");
+#endif
+
+
+
+ if (url == NULL || url[0] == '\0') {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL,
+ "url cannot be null.\n");
+ }
+
+ if (FAIL == H5FD_s3comms_parse_url(url, &purl)) {
+ /* probably a malformed url, but could be internal error */
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTCREATE, NULL,
+ "unable to create parsed url structure");
+ }
+ HDassert( purl != NULL ); /* if above passes, this must be true */
+ HDassert( purl->magic == S3COMMS_PARSED_URL_MAGIC );
+
+ handle = (s3r_t *)H5MM_malloc(sizeof(s3r_t));
+ if (handle == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTALLOC, NULL,
+ "could not malloc space for handle.\n");
+ }
+
+ handle->magic = S3COMMS_S3R_MAGIC;
+ handle->purl = purl;
+ handle->filesize = 0;
+ handle->region = NULL;
+ handle->secret_id = NULL;
+ handle->signing_key = NULL;
+ handle->httpverb = NULL;
+
+ /*************************************
+ * RECORD AUTHENTICATION INFORMATION *
+ *************************************/
+
+ if ((region != NULL && *region != '\0') ||
+ (id != NULL && *id != '\0') ||
+ (signing_key != NULL && *signing_key != '\0'))
+ {
+ /* if one exists, all three must exist
+ */
+ if (region == NULL || region[0] == '\0') {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL,
+ "region cannot be null.\n");
+ }
+ if (id == NULL || id[0] == '\0') {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL,
+ "secret id cannot be null.\n");
+ }
+ if (signing_key == NULL || signing_key[0] == '\0') {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL,
+ "signing key cannot be null.\n");
+ }
+
+ /* copy strings
+ */
+ tmplen = HDstrlen(region) + 1;
+ handle->region = (char *)H5MM_malloc(sizeof(char) * tmplen);
+ if (handle->region == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL,
+ "could not malloc space for handle region copy.\n");
+ }
+ HDmemcpy(handle->region, region, tmplen);
+
+ tmplen = HDstrlen(id) + 1;
+ handle->secret_id = (char *)H5MM_malloc(sizeof(char) * tmplen);
+ if (handle->secret_id == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL,
+ "could not malloc space for handle ID copy.\n");
+ }
+ HDmemcpy(handle->secret_id, id, tmplen);
+
+ tmplen = SHA256_DIGEST_LENGTH;
+ handle->signing_key =
+ (unsigned char *)H5MM_malloc(sizeof(unsigned char) * tmplen);
+ if (handle->signing_key == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL,
+ "could not malloc space for handle key copy.\n");
+ }
+ HDmemcpy(handle->signing_key, signing_key, tmplen);
+ } /* if authentication information provided */
+
+ /************************
+ * INITIATE CURL HANDLE *
+ ************************/
+
+ curlh = curl_easy_init();
+
+ if (curlh == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL,
+ "problem creating curl easy handle!\n");
+ }
+
+ if ( CURLE_OK !=
+ curl_easy_setopt(curlh,
+ CURLOPT_HTTPGET,
+ 1L) )
+ {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL,
+ "error while setting CURL option (CURLOPT_HTTPGET). "
+ "(placeholder flags)");
+ }
+
+ if ( CURLE_OK !=
+ curl_easy_setopt(curlh,
+ CURLOPT_HTTP_VERSION,
+ CURL_HTTP_VERSION_1_1) )
+ {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL,
+ "error while setting CURL option (CURLOPT_HTTP_VERSION). "
+ "(placeholder flags)");
+ }
+
+ if ( CURLE_OK !=
+ curl_easy_setopt(curlh,
+ CURLOPT_FAILONERROR,
+ 1L) )
+ {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL,
+ "error while setting CURL option (CURLOPT_FAILONERROR). "
+ "(placeholder flags)");
+ }
+
+ if ( CURLE_OK !=
+ curl_easy_setopt(curlh,
+ CURLOPT_WRITEFUNCTION,
+ curlwritecallback) )
+ {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL,
+ "error while setting CURL option (CURLOPT_WRITEFUNCTION). "
+ "(placeholder flags)");
+ }
+
+ if ( CURLE_OK !=
+ curl_easy_setopt(curlh,
+ CURLOPT_URL,
+ url) )
+ {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL,
+ "error while setting CURL option (CURLOPT_URL). "
+ "(placeholder flags)");
+ }
+
+#if S3COMMS_CURL_VERBOSITY > 1
+ /* CURL will print (to stdout) information for each operation
+ */
+ curl_easy_setopt(curlh, CURLOPT_VERBOSE, 1L);
+#endif
+
+ handle->curlhandle = curlh;
+
+ /*******************
+ * OPEN CONNECTION *
+ * * * * * * * * * *
+ * GET FILE SIZE *
+ *******************/
+
+ if (FAIL ==
+ H5FD_s3comms_s3r_getsize(handle) )
+ {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL,
+ "problem in H5FD_s3comms_s3r_getsize.\n");
+ }
+
+ /*********************
+ * FINAL PREPARATION *
+ *********************/
+
+ HDassert( handle->httpverb != NULL );
+ HDmemcpy(handle->httpverb, "GET", 4);
+
+ ret_value = handle;
+
+done:
+ if (ret_value == NULL) {
+ if (curlh != NULL) {
+ curl_easy_cleanup(curlh);
+ }
+ if (FAIL == H5FD_s3comms_free_purl(purl)) {
+ HDONE_ERROR(H5E_ARGS, H5E_BADVALUE, NULL,
+ "unable to free parsed url structure")
+ }
+ if (handle != NULL) {
+ H5MM_xfree(handle->region);
+ H5MM_xfree(handle->secret_id);
+ H5MM_xfree(handle->signing_key);
+ if (handle->httpverb != NULL) {
+ H5MM_xfree(handle->httpverb);
+ }
+ H5MM_xfree(handle);
+ }
+ }
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5FD_s3comms_s3r_open */
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: H5FD_s3comms_s3r_read()
+ *
+ * Purpose:
+ *
+ * Read file pointed to by request handle, writing specified
+ * `offset` .. `offset + len` bytes to buffer `dest`.
+ *
+ * If `len` is 0, reads entirety of file starting at `offset`.
+ * If `offset` and `len` are both 0, reads entire file.
+ *
+ * If `offset` or `offset+len` is greater than the file size, read is
+ * aborted and returns `FAIL`.
+ *
+ * Uses configured "curl easy handle" to perform request.
+ *
+ * In event of error, buffer should remain unaltered.
+ *
+ * If handle is set to authorize a request, creates a new (temporary)
+ * HTTP Request object (hrb_t) for generating requisite headers,
+ * which is then translated to a `curl slist` and set in the curl handle
+ * for the request.
+ *
+ * `dest` _may_ be NULL, but no body data will be recorded.
+ *
+ * - In general practice, NULL should never be passed in as `dest`.
+ * - NULL `dest` passed in by internal function `s3r_getsize()`, in
+ * conjunction with CURLOPT_NOBODY to preempt transmission of file data
+ * from server.
+ *
+ * Return:
+ *
+ * - SUCCESS: `SUCCEED`
+ * - FAILURE: `FAIL`
+ *
+ * Programmer: Jacob Smith
+ * 2017-08-22
+ *
+ *----------------------------------------------------------------------------
+ */
+herr_t
+H5FD_s3comms_s3r_read(s3r_t *handle,
+ haddr_t offset,
+ size_t len,
+ void *dest)
+{
+ CURL *curlh = NULL;
+ CURLcode p_status = CURLE_OK;
+ struct curl_slist *curlheaders = NULL;
+ hrb_node_t *headers = NULL;
+ hrb_node_t *node = NULL;
+ struct tm *now = NULL;
+ char *rangebytesstr = NULL;
+ hrb_t *request = NULL;
+ int ret = 0; /* working variable to check */
+ /* return value of HDsnprintf */
+ struct s3r_datastruct *sds = NULL;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+#if S3COMMS_DEBUG
+ HDfprintf(stdout, "called H5FD_s3comms_s3r_read.\n");
+#endif
+
+ /**************************************
+ * ABSOLUTELY NECESSARY SANITY-CHECKS *
+ **************************************/
+
+ if (handle == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "handle cannot be null.\n");
+ }
+ if (handle->magic != S3COMMS_S3R_MAGIC) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "handle has invalid magic.\n");
+ }
+ if (handle->curlhandle == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "handle has bad (null) curlhandle.\n")
+ }
+ if (handle->purl == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "handle has bad (null) url.\n")
+ }
+ HDassert( handle->purl->magic == S3COMMS_PARSED_URL_MAGIC );
+ if (offset > handle->filesize || (len + offset) > handle->filesize) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "unable to read past EoF")
+ }
+
+ curlh = handle->curlhandle;
+
+ /*********************
+ * PREPARE WRITEDATA *
+ *********************/
+
+ if (dest != NULL) {
+ sds = (struct s3r_datastruct *)H5MM_malloc(
+ sizeof(struct s3r_datastruct));
+ if (sds == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTALLOC, FAIL,
+ "could not malloc destination datastructure.\n");
+ }
+
+ sds->magic = S3COMMS_CALLBACK_DATASTRUCT_MAGIC;
+ sds->data = (char *)dest;
+ sds->size = 0;
+ if (CURLE_OK !=
+ curl_easy_setopt(curlh,
+ CURLOPT_WRITEDATA,
+ sds) )
+ {
+ HGOTO_ERROR(H5E_ARGS, H5E_UNINITIALIZED, FAIL,
+ "error while setting CURL option (CURLOPT_WRITEDATA). "
+ "(placeholder flags)");
+ }
+ }
+
+ /*********************
+ * FORMAT HTTP RANGE *
+ *********************/
+
+ if (len > 0) {
+ rangebytesstr = (char *)H5MM_malloc(sizeof(char) * \
+ (S3COMMS_MAX_RANGE_STRING_SIZE+1) );
+ if (rangebytesstr == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTALLOC, FAIL,
+ "could not malloc range format string.\n");
+ }
+ ret = HDsnprintf(rangebytesstr,
+ (S3COMMS_MAX_RANGE_STRING_SIZE),
+ "bytes="H5_PRINTF_HADDR_FMT"-"H5_PRINTF_HADDR_FMT,
+ offset,
+ offset + len - 1);
+ if (ret <= 0 || ret >= S3COMMS_MAX_RANGE_STRING_SIZE)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "unable to format HTTP Range value");
+ } else if (offset > 0) {
+ rangebytesstr = (char *)H5MM_malloc(sizeof(char) * \
+ (S3COMMS_MAX_RANGE_STRING_SIZE+1));
+ if (rangebytesstr == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTALLOC, FAIL,
+ "could not malloc range format string.\n");
+ }
+ ret = HDsnprintf(rangebytesstr,
+ (S3COMMS_MAX_RANGE_STRING_SIZE),
+ "bytes="H5_PRINTF_HADDR_FMT"-",
+ offset);
+ if (ret <= 0 || ret >= S3COMMS_MAX_RANGE_STRING_SIZE)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "unable to format HTTP Range value");
+ }
+
+ /*******************
+ * COMPILE REQUEST *
+ *******************/
+
+ if (handle->signing_key == NULL) {
+ /* Do not authenticate.
+ */
+ if (rangebytesstr != NULL) {
+ /* Pass in range directly
+ */
+ char *bytesrange_ptr = NULL; /* pointer past "bytes=" portion */
+
+ bytesrange_ptr = strchr(rangebytesstr, '=');
+ HDassert( bytesrange_ptr != NULL );
+ bytesrange_ptr++; /* move to first char past '=' */
+ HDassert( *bytesrange_ptr != '\0' );
+
+ if (CURLE_OK !=
+ curl_easy_setopt(curlh,
+ CURLOPT_RANGE,
+ bytesrange_ptr) )
+ {
+ HGOTO_ERROR(H5E_VFL, H5E_UNINITIALIZED, FAIL,
+ "error while setting CURL option (CURLOPT_RANGE). ");
+ }
+ }
+ } else {
+ /* authenticate request
+ */
+ char authorization[512+1];
+ /* 512 := approximate max length...
+ * 67 <len("AWS4-HMAC-SHA256 Credential=///s3/aws4_request,"
+ * "SignedHeaders=,Signature=")>
+ * + 8 <yyyyMMDD>
+ * + 64 <hex(sha256())>
+ * + 128 <max? len(secret_id)>
+ * + 20 <max? len(region)>
+ * + 128 <max? len(signed_headers)>
+ */
+ char buffer1[512+1]; /* -> Canonical Request -> Signature */
+ char buffer2[256+1]; /* -> String To Sign -> Credential */
+ char iso8601now[ISO8601_SIZE];
+ char signed_headers[48+1];
+ /* should be large enough for nominal listing:
+ * "host;range;x-amz-content-sha256;x-amz-date"
+ * + '\0', with "range;" possibly absent
+ */
+
+ /* zero start of strings */
+ authorization[0] = 0;
+ buffer1[0] = 0;
+ buffer2[0] = 0;
+ iso8601now[0] = 0;
+ signed_headers[0] = 0;
+
+ /**** VERIFY INFORMATION EXISTS ****/
+
+ if (handle->region == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "handle must have non-null region.\n");
+ }
+ if (handle->secret_id == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "handle must have non-null secret_id.\n");
+ }
+ if (handle->signing_key == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "handle must have non-null signing_key.\n");
+ }
+ if (handle->httpverb == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "handle must have non-null httpverb.\n");
+ }
+ if (handle->purl->host == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "handle must have non-null host.\n");
+ }
+ if (handle->purl->path == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "handle must have non-null resource.\n");
+ }
+
+ /**** CREATE HTTP REQUEST STRUCTURE (hrb_t) ****/
+
+ request = H5FD_s3comms_hrb_init_request(
+ (const char *)handle->httpverb,
+ (const char *)handle->purl->path,
+ "HTTP/1.1");
+ if (request == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "could not allocate hrb_t request.\n");
+ }
+ HDassert( request->magic == S3COMMS_HRB_MAGIC );
+
+ now = gmnow();
+ if (ISO8601NOW(iso8601now, now) != (ISO8601_SIZE - 1)) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "could not format ISO8601 time.\n");
+ }
+
+ if (FAIL ==
+ H5FD_s3comms_hrb_node_set(
+ &headers,
+ "x-amz-date",
+ (const char *)iso8601now) )
+ {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "unable to set x-amz-date header")
+ }
+ if (headers == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "problem building headers list. "
+ "(placeholder flags)\n");
+ }
+ HDassert( headers->magic == S3COMMS_HRB_NODE_MAGIC );
+
+ if (FAIL ==
+ H5FD_s3comms_hrb_node_set(
+ &headers,
+ "x-amz-content-sha256",
+ (const char *)EMPTY_SHA256) )
+ {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "unable to set x-amz-content-sha256 header")
+ }
+ if (headers == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "problem building headers list. "
+ "(placeholder flags)\n");
+ }
+ HDassert( headers->magic == S3COMMS_HRB_NODE_MAGIC );
+
+ if (rangebytesstr != NULL) {
+ if (FAIL ==
+ H5FD_s3comms_hrb_node_set(
+ &headers,
+ "Range",
+ (const char *)rangebytesstr) )
+ {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "unable to set range header")
+ }
+ if (headers == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "problem building headers list. "
+ "(placeholder flags)\n");
+ }
+ HDassert( headers->magic == S3COMMS_HRB_NODE_MAGIC );
+ }
+
+ if (FAIL ==
+ H5FD_s3comms_hrb_node_set(
+ &headers,
+ "Host",
+ (const char *)handle->purl->host) )
+ {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "unable to set host header")
+ }
+ if (headers == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "problem building headers list. "
+ "(placeholder flags)\n");
+ }
+ HDassert( headers->magic == S3COMMS_HRB_NODE_MAGIC );
+
+ request->first_header = headers;
+
+ /**** COMPUTE AUTHORIZATION ****/
+
+ if (FAIL == /* buffer1 -> canonical request */
+ H5FD_s3comms_aws_canonical_request(
+ buffer1,
+ 512,
+ signed_headers,
+ 48,
+ request) )
+ {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "(placeholder flags)\n");
+ }
+ if ( FAIL == /* buffer2->string-to-sign */
+ H5FD_s3comms_tostringtosign(buffer2,
+ buffer1,
+ iso8601now,
+ handle->region) )
+ {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "(placeholder flags)\n");
+ }
+ if (FAIL == /* buffer1 -> signature */
+ H5FD_s3comms_HMAC_SHA256(handle->signing_key,
+ SHA256_DIGEST_LENGTH,
+ buffer2,
+ HDstrlen(buffer2),
+ buffer1) )
+ {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "(placeholder flags)\n");
+ }
+
+ iso8601now[8] = 0; /* trim to yyyyMMDD */
+ ret = S3COMMS_FORMAT_CREDENTIAL(buffer2,
+ handle->secret_id,
+ iso8601now,
+ handle->region,
+ "s3");
+ if (ret == 0 || ret >= S3COMMS_MAX_CREDENTIAL_SIZE)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "unable to format aws4 credential string");
+
+ ret = HDsnprintf(
+ authorization,
+ 512,
+ "AWS4-HMAC-SHA256 Credential=%s,SignedHeaders=%s,Signature=%s",
+ buffer2,
+ signed_headers,
+ buffer1);
+ if (ret <= 0 || ret >= 512) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "unable to format aws4 authorization string");
+ }
+
+ /* append authorization header to http request buffer
+ */
+ if (H5FD_s3comms_hrb_node_set(
+ &headers,
+ "Authorization",
+ (const char *)authorization)
+ == FAIL)
+ {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "unable to set Authorization header")
+ }
+ if (headers == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "problem building headers list. "
+ "(placeholder flags)\n");
+ }
+
+ /* update hrb's "first header" pointer
+ */
+ request->first_header = headers;
+
+ /**** SET CURLHANDLE HTTP HEADERS FROM GENERATED DATA ****/
+
+ node = request->first_header;
+ while (node != NULL) {
+ HDassert( node->magic == S3COMMS_HRB_NODE_MAGIC );
+ curlheaders = curl_slist_append(curlheaders,
+ (const char *)node->cat);
+ if (curlheaders == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "could not append header to curl slist. "
+ "(placeholder flags)\n");
+ }
+ node = node->next;
+ }
+
+ /* sanity-check
+ */
+ if (curlheaders == NULL) {
+ /* above loop was probably never run */
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "curlheaders was never populated.\n");
+ }
+
+ /* finally, set http headers in curl handle
+ */
+ if (curl_easy_setopt(
+ curlh,
+ CURLOPT_HTTPHEADER,
+ curlheaders)
+ != CURLE_OK)
+ {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "error while setting CURL option "
+ "(CURLOPT_HTTPHEADER). (placeholder flags)");
+ }
+
+ } /* end if should authenticate (info provided) */
+
+ /*******************
+ * PERFORM REQUEST *
+ *******************/
+
+#if S3COMMS_CURL_VERBOSITY > 0
+ /* In event of error, print detailed information to stderr
+ * This is not the default behavior.
+ */
+ {
+ long int httpcode = 0;
+ char curlerrbuf[CURL_ERROR_SIZE];
+ curlerrbuf[0] = '\0';
+
+ if (CURLE_OK !=
+ curl_easy_setopt(curlh, CURLOPT_ERRORBUFFER, curlerrbuf) )
+ {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "problem setting error buffer")
+ }
+
+ p_status = curl_easy_perform(curlh);
+
+ if (p_status != CURLE_OK) {
+ if (CURLE_OK !=
+ curl_easy_getinfo(curlh, CURLINFO_RESPONSE_CODE, &httpcode) )
+ {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "problem getting response code")
+ }
+ HDfprintf(stderr, "CURL ERROR CODE: %d\nHTTP CODE: %d\n",
+ p_status, httpcode);
+ HDfprintf(stderr, "%s\n", curl_easy_strerror(p_status));
+ HGOTO_ERROR(H5E_VFL, H5E_CANTOPENFILE, FAIL,
+ "problem while performing request.\n");
+ }
+ if (CURLE_OK !=
+ curl_easy_setopt(curlh, CURLOPT_ERRORBUFFER, NULL) )
+ {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "problem unsetting error buffer")
+ }
+ } /* verbose error reporting */
+#else
+ p_status = curl_easy_perform(curlh);
+
+ if (p_status != CURLE_OK) {
+ HGOTO_ERROR(H5E_VFL, H5E_CANTOPENFILE, FAIL,
+ "curl cannot perform request\n")
+ }
+#endif
+
+#if S3COMMS_DEBUG
+ if (dest != NULL) {
+ HDfprintf(stderr, "len: %d\n", (int)len);
+ HDfprintf(stderr, "CHECKING FOR BUFFER OVERFLOW\n");
+ if (sds == NULL) {
+ HDfprintf(stderr, "sds is NULL!\n");
+ }
+ else {
+ HDfprintf(stderr, "sds: 0x%lx\n", (long long)sds);
+ HDfprintf(stderr, "sds->size: %d\n", (int)sds->size);
+ if (len > sds->size) {
+ HDfprintf(stderr, "buffer overwrite\n");
+ }
+ }
+ }
+ else {
+ HDfprintf(stderr, "performed on entire file\n");
+ }
+#endif
+
+done:
+ /* clean any malloc'd resources
+ */
+ if (curlheaders != NULL) {
+ curl_slist_free_all(curlheaders);
+ curlheaders = NULL;
+ }
+ if (rangebytesstr != NULL) {
+ H5MM_xfree(rangebytesstr);
+ rangebytesstr = NULL;
+ }
+ if (sds != NULL) {
+ H5MM_xfree(sds);
+ sds = NULL;
+ }
+ if (request != NULL) {
+ while (headers != NULL)
+ if (FAIL ==
+ H5FD_s3comms_hrb_node_set(&headers, headers->name, NULL))
+ {
+ HDONE_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "cannot release header node")
+ }
+ HDassert( NULL == headers );
+ if (FAIL == H5FD_s3comms_hrb_destroy(&request)) {
+ HDONE_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "cannot release header request structure")
+ }
+ HDassert( NULL == request );
+ }
+
+ if (curlh != NULL) {
+ /* clear any Range */
+ if (CURLE_OK != curl_easy_setopt(curlh, CURLOPT_RANGE, NULL) ) {
+ HDONE_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "cannot unset CURLOPT_RANGE")
+ }
+
+ /* clear headers */
+ if (CURLE_OK != curl_easy_setopt(curlh, CURLOPT_HTTPHEADER, NULL) ) {
+ HDONE_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "cannot unset CURLOPT_HTTPHEADER")
+ }
+ }
+
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* H5FD_s3comms_s3r_read */
+
+
+/****************************************************************************
+ * MISCELLANEOUS FUNCTIONS
+ ****************************************************************************/
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: gmnow()
+ *
+ * Purpose:
+ *
+ * Get the output of `time.h`'s `gmtime()` call while minimizing setup
+ * clutter where important.
+ *
+ * Return:
+ *
+ * Pointer to resulting `struct tm`,as created by gmtime(time_t * T).
+ *
+ * Programmer: Jacob Smith
+ * 2017-07-12
+ *
+ *----------------------------------------------------------------------------
+ */
+struct tm *
+gmnow(void)
+{
+ time_t now;
+ time_t *now_ptr = &now;
+ struct tm *ret_value = NULL;
+
+ /* Doctor assert, checks against error in time() */
+ if ( (time_t)(-1) != time(now_ptr) ) {
+ ret_value = gmtime(now_ptr);
+ }
+
+ HDassert( ret_value != NULL );
+
+ return ret_value;
+} /* end gmnow() */
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: H5FD_s3comms_aws_canonical_request()
+ *
+ * Purpose:
+ *
+ * Compose AWS "Canonical Request" (and signed headers string)
+ * as defined in the REST API documentation.
+ *
+ * Both destination strings are null-terminated.
+ *
+ * Destination string arguments must be provided with adequate space.
+ *
+ * Canonical Request format:
+ *
+ * <HTTP VERB>"\n"
+ * <resource path>"\n"
+ * <query string>"\n"
+ * <header1>"\n" (`lowercase(name)`":"`trim(value)`)
+ * <header2>"\n"
+ * ... (headers sorted by name)
+ * <header_n>"\n"
+ * "\n"
+ * <signed headers>"\n" (`lowercase(header 1 name)`";"`header 2 name`;...)
+ * <hex-string of sha256sum of body> ("e3b0c4429...", e.g.)
+ *
+ * Return:
+ *
+ * - SUCCESS: `SUCCEED`
+ * - writes canonical request to respective `...dest` strings
+ * - FAILURE: `FAIL`
+ * - one or more input argument was NULL
+ * - internal error
+ *
+ * Programmer: Jacob Smith
+ * 2017-10-04
+ *
+ *----------------------------------------------------------------------------
+ */
+herr_t
+H5FD_s3comms_aws_canonical_request(
+ char *canonical_request_dest,
+ int _cr_size,
+ char *signed_headers_dest,
+ int _sh_size,
+ hrb_t *http_request)
+{
+ hrb_node_t *node = NULL;
+ const char *query_params = ""; /* unused at present */
+ herr_t ret_value = SUCCEED;
+ int ret = 0;
+ size_t cr_size = (size_t)_cr_size;
+ size_t sh_size = (size_t)_sh_size;
+ size_t cr_len = 0; /* working length of canonical request str */
+ size_t sh_len = 0; /* working length of signed headers str */
+ char tmpstr[256+1];
+ tmpstr[256] = 0; /* terminating NULL */
+
+ /* "query params" refers to the optional element in the URL, e.g.
+ * http://bucket.aws.com/myfile.txt?max-keys=2&prefix=J
+ * ^-----------------^
+ *
+ * Not handled/implemented as of 2017-10-xx.
+ * Element introduced as empty placeholder and reminder.
+ * Further research to be done if this is ever relevant for the
+ * VFD use-cases.
+ */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+#if S3COMMS_DEBUG
+ HDfprintf(stdout, "called H5FD_s3comms_aws_canonical_request.\n");
+#endif
+
+ if (http_request == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "hrb object cannot be null.\n");
+ }
+ HDassert( http_request->magic == S3COMMS_HRB_MAGIC );
+
+ if (canonical_request_dest == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "canonical request destination cannot be null.\n");
+ }
+
+ if (signed_headers_dest == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "signed headers destination cannot be null.\n");
+ }
+
+ /* HTTP verb, resource path, and query string lines
+ */
+ cr_len = (HDstrlen(http_request->verb) +
+ HDstrlen(http_request->resource) +
+ HDstrlen(query_params) +
+ (size_t)3); /* three newline chars */
+ if (cr_len >= cr_size) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "not enough space in canonical request");
+ }
+ ret = HDsnprintf( /* TODO: compiler warning */
+ canonical_request_dest,
+ (cr_size-1),
+ "%s\n%s\n%s\n",
+ http_request->verb,
+ http_request->resource,
+ query_params);
+ if (ret < 0 || (size_t)ret >= cr_size) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "unable to compose canonical request first line");
+ }
+
+ /* write in canonical headers, building signed headers concurrently
+ */
+ node = http_request->first_header; /* assumed sorted */
+ while (node != NULL) {
+
+ HDassert(node->magic == S3COMMS_HRB_NODE_MAGIC);
+
+ ret = HDsnprintf(
+ tmpstr,
+ 256,
+ "%s:%s\n",
+ node->lowername,
+ node->value);
+ if (ret < 0 || ret >= 256) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "unable to concatenate HTTP header %s:%s",
+ node->lowername,
+ node->value);
+ }
+ cr_len += HDstrlen(tmpstr);
+ if (cr_len + 1 > cr_size) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "not enough space in canonical request");
+ }
+ strcat(canonical_request_dest, tmpstr);
+
+ ret = HDsnprintf(
+ tmpstr,
+ 256,
+ "%s;",
+ node->lowername);
+ if (ret < 0 || ret >= 256) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "unable to append semicolon to lowername %s",
+ node->lowername);
+ }
+ sh_len += HDstrlen(tmpstr);
+ if (sh_len + 1 > sh_size) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "not enough space in signed headers");
+ }
+ strcat(signed_headers_dest, tmpstr);
+
+ node = node->next;
+ } /* end while node is not NULL */
+
+ /* remove tailing ';' from signed headers sequence
+ */
+ signed_headers_dest[HDstrlen(signed_headers_dest) - 1] = '\0';
+
+ /* append signed headers and payload hash
+ * NOTE: at present, no HTTP body is handled, per the nature of
+ * requests/range-gets
+ */
+ strcat(canonical_request_dest, "\n");
+ strcat(canonical_request_dest, signed_headers_dest);
+ strcat(canonical_request_dest, "\n");
+ strcat(canonical_request_dest, EMPTY_SHA256);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5FD_s3comms_aws_canonical_request() */
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: H5FD_s3comms_bytes_to_hex()
+ *
+ * Purpose:
+ *
+ * Produce human-readable hex string [0-9A-F] from sequence of bytes.
+ *
+ * For each byte (char), writes two-character hexadecimal representation.
+ *
+ * No null-terminator appended.
+ *
+ * Assumes `dest` is allocated to enough size (msg_len * 2).
+ *
+ * Fails if either `dest` or `msg` are null.
+ *
+ * `msg_len` message length of 0 has no effect.
+ *
+ * Return:
+ *
+ * - SUCCESS: `SUCCEED`
+ * - hex string written to `dest` (not null-terminated)
+ * - FAILURE: `FAIL`
+ * - `dest == NULL`
+ * - `msg == NULL`
+ *
+ * Programmer: Jacob Smith
+ * 2017-07-12
+ *
+ *----------------------------------------------------------------------------
+ */
+herr_t
+H5FD_s3comms_bytes_to_hex(
+ char *dest,
+ const unsigned char *msg,
+ size_t msg_len,
+ hbool_t lowercase)
+{
+ size_t i = 0;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+#if S3COMMS_DEBUG
+ HDfprintf(stdout, "called H5FD_s3comms_bytes_to_hex.\n");
+#endif
+
+ if (dest == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "hex destination cannot be null.\n")
+ }
+ if (msg == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "bytes sequence cannot be null.\n")
+ }
+
+ for (i = 0; i < msg_len; i++) {
+ int chars_written = HDsnprintf(&(dest[i * 2]),
+ 3, /* 'X', 'X', '\n' */
+ (lowercase == TRUE) ? "%02x" : "%02X",
+ msg[i]);
+ if (chars_written != 2) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "problem while writing hex chars for %c",
+ msg[i]);
+ }
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+
+} /* end H5FD_s3comms_bytes_to_hex() */
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: H5FD_s3comms_free_purl()
+ *
+ * Purpose:
+ *
+ * Release resources from a parsed_url_t pointer.
+ *
+ * If pointer is null, nothing happens.
+ *
+ * Return:
+ *
+ * `SUCCEED` (never fails)
+ *
+ * Programmer: Jacob Smith
+ * 2017-11-01
+ *
+ *----------------------------------------------------------------------------
+ */
+herr_t
+H5FD_s3comms_free_purl(parsed_url_t *purl)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+#if S3COMMS_DEBUG
+ HDprintf("called H5FD_s3comms_free_purl.\n");
+#endif
+
+ if (purl != NULL) {
+ HDassert( purl->magic == S3COMMS_PARSED_URL_MAGIC );
+ if (purl->scheme != NULL) { H5MM_xfree(purl->scheme); }
+ if (purl->host != NULL) { H5MM_xfree(purl->host); }
+ if (purl->port != NULL) { H5MM_xfree(purl->port); }
+ if (purl->path != NULL) { H5MM_xfree(purl->path); }
+ if (purl->query != NULL) { H5MM_xfree(purl->query); }
+ purl->magic += 1ul;
+ H5MM_xfree(purl);
+ }
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5FD_s3comms_free_purl() */
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: H5FD_s3comms_HMAC_SHA256()
+ *
+ * Purpose:
+ *
+ * Generate Hash-based Message Authentication Checksum using the SHA-256
+ * hashing algorithm.
+ *
+ * Given a key, message, and respective lengths (to accommodate null
+ * characters in either), generate _hex string_ of authentication checksum
+ * and write to `dest`.
+ *
+ * `dest` must be at least `SHA256_DIGEST_LENGTH * 2` characters in size.
+ * Not enforceable by this function.
+ * `dest` will _not_ be null-terminated by this function.
+ *
+ * Return:
+ *
+ * - SUCCESS: `SUCCEED`
+ * - hex string written to `dest` (not null-terminated)
+ * - FAILURE: `FAIL`
+ * - `dest == NULL`
+ * - error while generating hex string output
+ *
+ * Programmer: Jacob Smith
+ * 2017-07-??
+ *
+ *----------------------------------------------------------------------------
+ */
+herr_t
+H5FD_s3comms_HMAC_SHA256(
+ const unsigned char *key,
+ size_t key_len,
+ const char *msg,
+ size_t msg_len,
+ char *dest)
+{
+ unsigned char md[SHA256_DIGEST_LENGTH];
+ unsigned int md_len = SHA256_DIGEST_LENGTH;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+#if S3COMMS_DEBUG
+ HDfprintf(stdout, "called H5FD_s3comms_HMAC_SHA256.\n");
+#endif
+
+ if (dest == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "destination cannot be null.");
+ }
+
+ HMAC(EVP_sha256(),
+ key,
+ (int)key_len,
+ (const unsigned char *)msg,
+ msg_len,
+ md,
+ &md_len);
+
+ if (H5FD_s3comms_bytes_to_hex(
+ dest,
+ (const unsigned char *)md,
+ (size_t)md_len,
+ true)
+ == FAIL)
+ {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "could not convert to hex string.");
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* H5FD_s3comms_HMAC_SHA256 */
+
+
+/*-----------------------------------------------------------------------------
+ *
+ * Function: H5FD__s3comms_load_aws_creds_from_file()
+ *
+ * Purpose:
+ *
+ * Extract AWS configuration information from a target file.
+ *
+ * Given a file and a profile name, e.g. "ros3_vfd_test", attempt to locate
+ * that region in the file. If not found, returns in error and output
+ * pointers are not modified.
+ *
+ * If the profile label is found, attempts to locate and parse configuration
+ * data, stopping at the first line where:
+ * + reached end of file
+ * + line does not start with a recognized setting name
+ *
+ * Following AWS documentation, looks for any of:
+ * + aws_access_key_id
+ * + aws_secret_access_key
+ * + region
+ *
+ * To be valid, the setting must begin the line with one of the keywords,
+ * followed immediately by an equals sign '=', and have some data before
+ * newline at end of line.
+ * + `spam=eggs` would be INVALID because name is unrecognized
+ * + `region = us-east-2` would be INVALID because of spaces
+ * + `region=` would be INVALID because no data.
+ *
+ * Upon successful parsing of a setting line, will store the result in the
+ * corresponding output pointer. If the output pointer is NULL, will skip
+ * any matching setting line while parsing -- useful to prevent overwrite
+ * when reading from multiple files.
+ *
+ * Return:
+ *
+ * + SUCCESS: `SUCCEED`
+ * + no error. settings may or may not have been loaded.
+ * + FAILURE: `FAIL`
+ * + internal error occurred.
+ * + -1 :: unable to format profile label
+ * + -2 :: profile name/label not found in file
+ * + -3 :: some other error
+ *
+ * Programmer: Jacob Smith
+ * 2018-02-27
+ *
+ *-----------------------------------------------------------------------------
+ */
+static herr_t
+H5FD__s3comms_load_aws_creds_from_file(
+ FILE *file,
+ const char *profile_name,
+ char *key_id,
+ char *access_key,
+ char *aws_region)
+{
+ char profile_line[32];
+ char buffer[128];
+ const char *setting_names[] = {
+ "region",
+ "aws_access_key_id",
+ "aws_secret_access_key",
+ };
+ char * const setting_pointers[] = {
+ aws_region,
+ key_id,
+ access_key,
+ };
+ unsigned setting_count = 3;
+ herr_t ret_value = SUCCEED;
+ unsigned buffer_i = 0;
+ unsigned setting_i = 0;
+ int found_setting = 0;
+ char *line_buffer = &(buffer[0]);
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+#if S3COMMS_DEBUG
+ HDfprintf(stdout, "called load_aws_creds_from_file.\n");
+#endif
+
+ /* format target line for start of profile */
+ if (32 < HDsnprintf(profile_line, 32, "[%s]", profile_name)) {
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTCOPY, FAIL,
+ "unable to format profile label")
+ }
+
+ /* look for start of profile */
+ do {
+ /* clear buffer */
+ for (buffer_i=0; buffer_i < 128; buffer_i++) {
+ buffer[buffer_i] = 0;
+ }
+
+ line_buffer = fgets(line_buffer, 128, file);
+ if (line_buffer == NULL) { /* reached end of file */
+ goto done;
+ }
+ } while (strncmp(line_buffer, profile_line, HDstrlen(profile_line)));
+
+ /* extract credentials from lines */
+ do {
+ /* clear buffer */
+ for (buffer_i=0; buffer_i < 128; buffer_i++) {
+ buffer[buffer_i] = 0;
+ }
+
+ /* collect a line from file */
+ line_buffer = fgets(line_buffer, 128, file);
+ if (line_buffer == NULL) {
+ goto done; /* end of file */
+ }
+
+ /* loop over names to see if line looks like assignment */
+ for (setting_i = 0; setting_i < setting_count; setting_i++) {
+ size_t setting_name_len = 0;
+ const char *setting_name = NULL;
+ char line_prefix[128];
+
+ setting_name = setting_names[setting_i];
+ setting_name_len = HDstrlen(setting_name);
+ if (HDsnprintf(line_prefix, 128, "%s=", setting_name) < 0) {
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTCOPY, FAIL,
+ "unable to format line prefix")
+ }
+
+ /* found a matching name? */
+ if (!HDstrncmp(line_buffer, line_prefix, setting_name_len + 1)) {
+ found_setting = 1;
+
+ /* skip NULL destination buffer */
+ if (setting_pointers[setting_i] == NULL) {
+ break;
+ }
+
+ /* advance to end of name in string */
+ do {
+ line_buffer++;
+ } while (*line_buffer != 0 && *line_buffer != '=');
+
+ if (*line_buffer == 0 || *(line_buffer+1) == 0) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "incomplete assignment in file")
+ }
+ line_buffer++; /* was pointing at '='; advance */
+
+ /* copy line buffer into out pointer */
+ if (HDstrncpy(
+ setting_pointers[setting_i],
+ (const char *)line_buffer,
+ HDstrlen(line_buffer))
+ == NULL)
+ {
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTCOPY, FAIL,
+ "unable to copy line into pointer")
+ }
+
+ /* "trim" tailing whitespace by replacing with null terminator*/
+ buffer_i = 0;
+ while (!isspace(setting_pointers[setting_i][buffer_i])) {
+ buffer_i++;
+ }
+ setting_pointers[setting_i][buffer_i] = '\0';
+
+ break; /* have read setting; don't compare with others */
+ } /* end if possible name match */
+ } /* end for each setting name */
+ } while (found_setting);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5FD__s3comms_load_aws_creds_from_file() */
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: H5FD_s3comms_load_aws_profile()
+ *
+ * Purpose :
+ *
+ * Read aws profile elements from standard location on system and store
+ * settings in memory.
+ *
+ * Looks for both `~/.aws/config` and `~/.aws/credentials`, the standard
+ * files for AWS tools. If a file exists (can be opened), looks for the
+ * given profile name and reads the settings into the relevant buffer.
+ *
+ * Any setting duplicated in both files will be set to that from
+ * `credentials`.
+ *
+ * Settings are stored in the supplied buffers as null-terminated strings.
+ *
+ * Return:
+ *
+ * + SUCCESS: `SUCCEED` (0)
+ * + no error occurred and all settings were populated
+ * + FAILURE: `FAIL` (-1)
+ * + internal error occurred
+ * + unable to locate profile
+ * + region, key id, and secret key were not all found and set
+ *
+ * Programmer: Jacob Smith
+ * 2018-02-27
+ *
+ *----------------------------------------------------------------------------
+ */
+herr_t
+H5FD_s3comms_load_aws_profile(const char *profile_name,
+ char *key_id_out,
+ char *secret_access_key_out,
+ char *aws_region_out)
+{
+ herr_t ret_value = SUCCEED;
+ FILE *credfile = NULL;
+ char awspath[117];
+ char filepath[128];
+ int ret = 0;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+#if S3COMMS_DEBUG
+ HDfprintf(stdout, "called H5FD_s3comms_load_aws_profile.\n");
+#endif
+
+#ifdef H5_HAVE_WIN32_API
+ ret = HDsnprintf(awspath, 117, "%s/.aws/", getenv("USERPROFILE")) ;
+#else
+ ret = HDsnprintf(awspath, 117, "%s/.aws/", getenv("HOME")) ;
+#endif
+ if (ret < 0 || (size_t)ret >= 117) {
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTCOPY, FAIL,
+ "unable to format home-aws path")
+ }
+ ret = HDsnprintf(filepath, 128, "%s%s", awspath, "credentials");
+ if (ret < 0 || (size_t)ret >= 128) {
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTCOPY, FAIL,
+ "unable to format credentials path")
+ }
+
+ credfile = fopen(filepath, "r");
+ if (credfile != NULL) {
+ if (H5FD__s3comms_load_aws_creds_from_file(
+ credfile,
+ profile_name,
+ key_id_out,
+ secret_access_key_out,
+ aws_region_out)
+ == FAIL)
+ {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "unable to load from aws credentials")
+ }
+ if (fclose(credfile) == EOF) {
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL,
+ "unable to close credentials file")
+ }
+ credfile = NULL;
+ } /* end if credential file opened */
+
+ ret = HDsnprintf(filepath, 128, "%s%s", awspath, "config");
+ if (ret < 0 || (size_t)ret >= 128) {
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTCOPY, FAIL,
+ "unable to format config path")
+ }
+ credfile = fopen(filepath, "r");
+ if (credfile != NULL) {
+ if (H5FD__s3comms_load_aws_creds_from_file(
+ credfile,
+ profile_name,
+ (*key_id_out == 0) ? key_id_out : NULL,
+ (*secret_access_key_out == 0) ? secret_access_key_out : NULL,
+ (*aws_region_out == 0) ? aws_region_out : NULL)
+ == FAIL)
+ {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "unable to load from aws config")
+ }
+ if (fclose(credfile) == EOF) {
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL,
+ "unable to close config file")
+ }
+ credfile = NULL;
+ } /* end if credential file opened */
+
+ /* fail if not all three settings were loaded */
+ if (*key_id_out == 0 ||
+ *secret_access_key_out == 0 ||
+ *aws_region_out == 0)
+ {
+ ret_value = FAIL;
+ }
+
+done:
+ if (credfile != NULL) {
+ if (fclose(credfile) == EOF) {
+ HDONE_ERROR(H5E_ARGS, H5E_ARGS, FAIL,
+ "problem error-closing aws configuration file")
+ }
+ }
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5FD_s3comms_load_aws_profile() */
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: H5FD_s3comms_nlowercase()
+ *
+ * Purpose:
+ *
+ * From string starting at `s`, write `len` characters to `dest`,
+ * converting all to lowercase.
+ *
+ * Behavior is undefined if `s` is NULL or `len` overruns the allocated
+ * space of either `s` or `dest`.
+ *
+ * Provided as convenience.
+ *
+ * Return:
+ *
+ * - SUCCESS: `SUCCEED`
+ * - upon completion, `dest` is populated
+ * - FAILURE: `FAIL`
+ * - `dest == NULL`
+ *
+ * Programmer: Jacob Smith
+ * 2017-09-18
+ *
+ *----------------------------------------------------------------------------
+ */
+herr_t
+H5FD_s3comms_nlowercase(
+ char *dest,
+ const char *s,
+ size_t len)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+#if S3COMMS_DEBUG
+ HDfprintf(stdout, "called H5FD_s3comms_nlowercase.\n");
+#endif
+
+ if (dest == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "destination cannot be null.\n");
+ }
+
+ if (len > 0) {
+ HDmemcpy(dest, s, len);
+ do {
+ len--;
+ dest[len] = (char)tolower( (int)dest[len] );
+ } while (len > 0);
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5FD_s3comms_nlowercase() */
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: H5FD_s3comms_parse_url()
+ *
+ * Purpose:
+ *
+ * Parse URL-like string and stuff URL components into
+ * `parsed_url` structure, if possible.
+ *
+ * Expects null-terminated string of format:
+ * SCHEME "://" HOST [":" PORT ] ["/" [ PATH ] ] ["?" QUERY]
+ * where SCHEME :: "[a-zA-Z/.-]+"
+ * PORT :: "[0-9]"
+ *
+ * Stores resulting structure in argument pointer `purl`, if successful,
+ * creating and populating new `parsed_url_t` structure pointer.
+ * Empty or absent elements are NULL in new purl structure.
+ *
+ * Return:
+ *
+ * - SUCCESS: `SUCCEED`
+ * - `purl` pointer is populated
+ * - FAILURE: `FAIL`
+ * - unable to parse
+ * - `purl` is unaltered (probably NULL)
+ *
+ * Programmer: Jacob Smith
+ * 2017-10-30
+ *
+ *----------------------------------------------------------------------------
+ */
+herr_t
+H5FD_s3comms_parse_url(
+ const char *str,
+ parsed_url_t **_purl)
+{
+ parsed_url_t *purl = NULL; /* pointer to new structure */
+ const char *tmpstr = NULL; /* working pointer in string */
+ const char *curstr = str; /* "start" pointer in string */
+ long int len = 0; /* substring length */
+ long int urllen = 0; /* length of passed-in url string */
+ unsigned int i = 0;
+ herr_t ret_value = FAIL;
+
+ FUNC_ENTER_NOAPI_NOINIT;
+
+#if S3COMMS_DEBUG
+ HDprintf("called H5FD_s3comms_parse_url.\n");
+#endif
+
+ if (str == NULL || *str == '\0') {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "invalid url string");
+ }
+
+ urllen = (long int)HDstrlen(str);
+
+ purl = (parsed_url_t *)H5MM_malloc(sizeof(parsed_url_t));
+ if (purl == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTALLOC, FAIL,
+ "can't allocate space for parsed_url_t");
+ }
+ purl->magic = S3COMMS_PARSED_URL_MAGIC;
+ purl->scheme = NULL;
+ purl->host = NULL;
+ purl->port = NULL;
+ purl->path = NULL;
+ purl->query = NULL;
+
+ /***************
+ * READ SCHEME *
+ ***************/
+
+ tmpstr = HDstrchr(curstr, ':');
+ if (tmpstr == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "invalid SCHEME construction: probably not URL");
+ }
+ len = tmpstr - curstr;
+ HDassert( (0 <= len) && (len < urllen) );
+
+ /* check for restrictions
+ */
+ for (i = 0; i < len; i++) {
+ /* scheme = [a-zA-Z+-.]+ (terminated by ":") */
+ if (!isalpha(curstr[i]) &&
+ '+' != curstr[i] &&
+ '-' != curstr[i] &&
+ '.' != curstr[i])
+ {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "invalid SCHEME construction");
+ }
+ }
+ /* copy lowercased scheme to structure
+ */
+ purl->scheme = (char *)H5MM_malloc(sizeof(char) * (size_t)(len + 1));
+ if (purl->scheme == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTALLOC, FAIL,
+ "can't allocate space for SCHEME");
+ }
+ (void)HDstrncpy(purl->scheme, curstr, (size_t)len);
+ purl->scheme[len] = '\0';
+ for ( i = 0; i < len; i++ ) {
+ purl->scheme[i] = (char)tolower(purl->scheme[i]);
+ }
+
+ /* Skip "://" */
+ tmpstr += 3;
+ curstr = tmpstr;
+
+ /*************
+ * READ HOST *
+ *************/
+
+ if (*curstr == '[') {
+ /* IPv6 */
+ while (']' != *tmpstr) {
+ if (tmpstr == 0) { /* end of string reached! */
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "reached end of URL: incomplete IPv6 HOST");
+ }
+ tmpstr++;
+ }
+ tmpstr++;
+ } /* end if (IPv6) */
+ else {
+ while (0 != *tmpstr) {
+ if (':' == *tmpstr ||
+ '/' == *tmpstr ||
+ '?' == *tmpstr)
+ {
+ break;
+ }
+ tmpstr++;
+ }
+ } /* end else (IPv4) */
+ len = tmpstr - curstr;
+ if (len == 0) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "HOST substring cannot be empty");
+ }
+ else
+ if (len > urllen) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "problem with length of HOST substring");
+ }
+
+ /* copy host
+ */
+ purl->host = (char *)H5MM_malloc(sizeof(char) * (size_t)(len + 1));
+ if (purl->host == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTALLOC, FAIL,
+ "can't allocate space for HOST");
+ }
+ (void)HDstrncpy(purl->host, curstr, (size_t)len);
+ purl->host[len] = 0;
+
+ /*************
+ * READ PORT *
+ *************/
+
+ if (':' == *tmpstr) {
+ tmpstr += 1; /* advance past ':' */
+ curstr = tmpstr;
+ while ((0 != *tmpstr) && ('/' != *tmpstr) && ('?' != *tmpstr)) {
+ tmpstr++;
+ }
+ len = tmpstr - curstr;
+ if (len == 0) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "PORT element cannot be empty");
+ }
+ else
+ if (len > urllen) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "problem with length of PORT substring");
+ }
+ for (i = 0; i < len; i ++) {
+ if (!isdigit(curstr[i])) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "PORT is not a decimal string");
+ }
+ }
+
+ /* copy port
+ */
+ purl->port = (char *)H5MM_malloc(sizeof(char) * (size_t)(len + 1));
+ if (purl->port == NULL) { /* cannot malloc */
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTALLOC, FAIL,
+ "can't allocate space for PORT");
+ }
+ (void)HDstrncpy(purl->port, curstr, (size_t)len);
+ purl->port[len] = 0;
+ } /* end if PORT element */
+
+ /*************
+ * READ PATH *
+ *************/
+
+ if ('/' == *tmpstr) {
+ /* advance past '/' */
+ tmpstr += 1;
+ curstr = tmpstr;
+
+ /* seek end of PATH
+ */
+ while ((0 != *tmpstr) && ('?' != *tmpstr)) {
+ tmpstr++;
+ }
+ len = tmpstr - curstr;
+ if (len > urllen) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "problem with length of PATH substring");
+ }
+ if (len > 0) {
+ purl->path = (char *)H5MM_malloc(sizeof(char) * (size_t)(len + 1));
+ if (purl->path == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTALLOC, FAIL,
+ "can't allocate space for PATH");
+ } /* cannot malloc path pointer */
+ (void)HDstrncpy(purl->path, curstr, (size_t)len);
+ purl->path[len] = 0;
+ }
+ } /* end if PATH element */
+
+ /**************
+ * READ QUERY *
+ **************/
+
+ if ('?' == *tmpstr) {
+ tmpstr += 1;
+ curstr = tmpstr;
+ while (0 != *tmpstr) {
+ tmpstr++;
+ }
+ len = tmpstr - curstr;
+ if (len == 0) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "QUERY cannot be empty");
+ } else if (len > urllen) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "problem with length of QUERY substring");
+ }
+ purl->query = (char *)H5MM_malloc(sizeof(char) * (size_t)(len + 1));
+ if (purl->query == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTALLOC, FAIL,
+ "can't allocate space for QUERY");
+ } /* cannot malloc path pointer */
+ (void)HDstrncpy(purl->query, curstr, (size_t)len);
+ purl->query[len] = 0;
+ } /* end if QUERY exists */
+
+ *_purl = purl;
+ ret_value = SUCCEED;
+
+done:
+ if (ret_value == FAIL) {
+ H5FD_s3comms_free_purl(purl);
+ }
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5FD_s3comms_parse_url() */
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: H5FD_s3comms_percent_encode_char()
+ *
+ * Purpose:
+ *
+ * "Percent-encode" utf-8 character `c`, e.g.,
+ * '$' -> "%24"
+ * '¢' -> "%C2%A2"
+ *
+ * `c` cannot be null.
+ *
+ * Does not (currently) accept multi-byte characters...
+ * limit to (?) u+00ff, well below upper bound for two-byte utf-8 encoding
+ * (u+0080..u+07ff).
+ *
+ * Writes output to `repr`.
+ * `repr` cannot be null.
+ * Assumes adequate space i `repr`...
+ * >>> char[4] or [7] for most characters,
+ * >>> [13] as theoretical maximum.
+ *
+ * Representation `repr` is null-terminated.
+ *
+ * Stores length of representation (without null terminator) at pointer
+ * `repr_len`.
+ *
+ * Return : SUCCEED/FAIL
+ *
+ * - SUCCESS: `SUCCEED`
+ * - percent-encoded representation written to `repr`
+ * - 'repr' is null-terminated
+ * - FAILURE: `FAIL`
+ * - `c` or `repr` was NULL
+ *
+ * Programmer: Jacob Smith
+ *
+ *----------------------------------------------------------------------------
+ */
+herr_t
+H5FD_s3comms_percent_encode_char(
+ char *repr,
+ const unsigned char c,
+ size_t *repr_len)
+{
+ unsigned int i = 0;
+ int chars_written = 0;
+ herr_t ret_value = SUCCEED;
+#if S3COMMS_DEBUG
+ unsigned char s[2] = {c, 0};
+ unsigned char hex[3] = {0, 0, 0};
+#endif
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+#if S3COMMS_DEBUG
+ HDfprintf(stdout, "called H5FD_s3comms_percent_encode_char.\n");
+#endif
+
+ if (repr == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no destination `repr`.\n")
+ }
+
+#if S3COMMS_DEBUG
+ H5FD_s3comms_bytes_to_hex((char *)hex, s, 1, FALSE);
+ HDfprintf(stdout, " CHAR: \'%s\'\n", s);
+ HDfprintf(stdout, " CHAR-HEX: \"%s\"\n", hex);
+#endif
+
+ if (c <= (unsigned char)0x7f) {
+ /* character represented in a single "byte"
+ * and single percent-code
+ */
+#if S3COMMS_DEBUG
+ HDfprintf(stdout, " SINGLE-BYTE\n");
+#endif
+ *repr_len = 3;
+ chars_written = HDsnprintf(repr, 4, "%%%02X", c);
+ if (chars_written < 0) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "cannot write char %c",
+ c);
+ }
+ } /* end if single-byte unicode char */
+ else {
+ /* multi-byte, multi-percent representation
+ */
+ unsigned int acc = 0; /* byte accumulator */
+ unsigned int k = 0; /* uint character representation */
+ unsigned int stack_size = 0;
+ unsigned char stack[4] = {0, 0, 0, 0};
+#if S3COMMS_DEBUG
+ HDfprintf(stdout, " MULTI-BYTE\n");
+#endif
+ stack_size = 0;
+ k = (unsigned int)c;
+ *repr_len = 0;
+ do {
+ /* push number onto stack in six-bit slices
+ */
+ acc = k;
+ acc >>= 6; /* cull least */
+ acc <<= 6; /* six bits */
+ stack[stack_size++] = (unsigned char)(k - acc);
+ k = acc >> 6;
+ } while (k > 0);
+
+ /* `stack` now has two to four six-bit 'numbers' to be put into
+ * UTF-8 byte fields.
+ */
+
+#if S3COMMS_DEBUG
+ HDfprintf(stdout, " STACK:\n {\n");
+ for (i = 0; i < stack_size; i++) {
+ H5FD_s3comms_bytes_to_hex(
+ (char *)hex,
+ (&stack[i]),
+ 1,
+ FALSE);
+ hex[2] = 0;
+ HDfprintf(stdout, " %s,\n", hex);
+ }
+ HDfprintf(stdout, " }\n");
+#endif
+
+ /****************
+ * leading byte *
+ ****************/
+
+ /* prepend 11[1[1]]0 to first byte */
+ /* 110xxxxx, 1110xxxx, or 11110xxx */
+ acc = 0xC0; /* 0x11000000 */
+ acc += (stack_size > 2) ? 0x20 : 0; /* 0x00100000 */
+ acc += (stack_size > 3) ? 0x10 : 0; /* 0x00010000 */
+ stack_size--;
+ chars_written = HDsnprintf(
+ repr,
+ 4,
+ "%%%02X",
+ (unsigned char)(acc + stack[stack_size]));
+ if (chars_written < 0) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "cannot write char %c",
+ c);
+ }
+ *repr_len += 3;
+
+ /************************
+ * continuation byte(s) *
+ ************************/
+
+ /* 10xxxxxx */
+ for (i = 0; i < stack_size; i++) {
+ chars_written = HDsnprintf(
+ &repr[i*3 + 3],
+ 4,
+ "%%%02X",
+ (unsigned char)(0x80 + stack[stack_size - 1 - i]));
+ if (chars_written < 0) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "cannot write char %c",
+ c);
+ }
+ *repr_len += 3;
+ } /* end for each continuation byte */
+ } /* end else (multi-byte) */
+
+ *(repr + *repr_len) = '\0';
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* H5FD_s3comms_percent_encode_char */
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: H5FD_s3comms_signing_key()
+ *
+ * Purpose:
+ *
+ * Create AWS4 "Signing Key" from secret key, AWS region, and timestamp.
+ *
+ * Sequentially runs HMAC_SHA256 on strings in specified order,
+ * generating re-usable checksum (according to documentation, valid for
+ * 7 days from time given).
+ *
+ * `secret` is `access key id` for targeted service/bucket/resource.
+ *
+ * `iso8601now` must conform to format, yyyyMMDD'T'hhmmss'Z'
+ * e.g. "19690720T201740Z".
+ *
+ * `region` should be one of AWS service region names, e.g. "us-east-1".
+ *
+ * Hard-coded "service" algorithm requirement to "s3".
+ *
+ * Inputs must be null-terminated strings.
+ *
+ * Writes to `md` the raw byte data, length of `SHA256_DIGEST_LENGTH`.
+ * Programmer must ensure that `md` is appropriately allocated.
+ *
+ * Return:
+ *
+ * - SUCCESS: `SUCCEED`
+ * - raw byte data of signing key written to `md`
+ * - FAILURE: `FAIL`
+ * - if any input arguments was NULL
+ *
+ * Programmer: Jacob Smith
+ * 2017-07-13
+ *
+ *----------------------------------------------------------------------------
+ */
+herr_t
+H5FD_s3comms_signing_key(
+ unsigned char *md,
+ const char *secret,
+ const char *region,
+ const char *iso8601now)
+{
+ char *AWS4_secret = NULL;
+ size_t AWS4_secret_len = 0;
+ unsigned char datekey[SHA256_DIGEST_LENGTH];
+ unsigned char dateregionkey[SHA256_DIGEST_LENGTH];
+ unsigned char dateregionservicekey[SHA256_DIGEST_LENGTH];
+ int ret = 0; /* return value of HDsnprintf */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+#if S3COMMS_DEBUG
+ HDfprintf(stdout, "called H5FD_s3comms_signing_key.\n");
+#endif
+
+ if (md == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "Destination `md` cannot be NULL.\n")
+ }
+ if (secret == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "`secret` cannot be NULL.\n")
+ }
+ if (region == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "`region` cannot be NULL.\n")
+ }
+ if (iso8601now == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "`iso8601now` cannot be NULL.\n")
+ }
+
+ AWS4_secret_len = 4 + HDstrlen(secret) + 1;
+ AWS4_secret = (char*)H5MM_malloc(sizeof(char *) * AWS4_secret_len);
+ if (AWS4_secret == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "Could not allocate space.\n")
+ }
+
+ /* prepend "AWS4" to start of the secret key
+ */
+ ret = HDsnprintf(AWS4_secret, AWS4_secret_len,"%s%s", "AWS4", secret);
+ if ((size_t)ret != (AWS4_secret_len - 1)) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "problem writing AWS4+secret `%s`",
+ secret);
+ }
+
+ /* hash_func, key, len(key), msg, len(msg), digest_dest, digest_len_dest
+ * we know digest length, so ignore via NULL
+ */
+ HMAC(EVP_sha256(),
+ (const unsigned char *)AWS4_secret,
+ (int)HDstrlen(AWS4_secret),
+ (const unsigned char*)iso8601now,
+ 8, /* 8 --> length of 8 --> "yyyyMMDD" */
+ datekey,
+ NULL);
+ HMAC(EVP_sha256(),
+ (const unsigned char *)datekey,
+ SHA256_DIGEST_LENGTH,
+ (const unsigned char *)region,
+ HDstrlen(region),
+ dateregionkey,
+ NULL);
+ HMAC(EVP_sha256(),
+ (const unsigned char *)dateregionkey,
+ SHA256_DIGEST_LENGTH,
+ (const unsigned char *)"s3",
+ 2,
+ dateregionservicekey,
+ NULL);
+ HMAC(EVP_sha256(),
+ (const unsigned char *)dateregionservicekey,
+ SHA256_DIGEST_LENGTH,
+ (const unsigned char *)"aws4_request",
+ 12,
+ md,
+ NULL);
+
+done:
+ H5MM_xfree(AWS4_secret);
+
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5FD_s3comms_signing_key() */
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: H5FD_s3comms_tostringtosign()
+ *
+ * Purpose:
+ *
+ * Get AWS "String to Sign" from Canonical Request, timestamp,
+ * and AWS "region".
+ *
+ * Common between single request and "chunked upload",
+ * conforms to:
+ * "AWS4-HMAC-SHA256\n" +
+ * <ISO8601 date format> + "\n" + // yyyyMMDD'T'hhmmss'Z'
+ * <yyyyMMDD> + "/" + <AWS Region> + "/s3/aws4-request\n" +
+ * hex(SHA256(<CANONICAL-REQUEST>))
+ *
+ * Inputs `creq` (canonical request string), `now` (ISO8601 format),
+ * and `region` (s3 region designator string) must all be
+ * null-terminated strings.
+ *
+ * Result is written to `dest` with null-terminator.
+ * It is left to programmer to ensure `dest` has adequate space.
+ *
+ * Return:
+ *
+ * - SUCCESS: `SUCCEED`
+ * - "string to sign" written to `dest` and null-terminated
+ * - FAILURE: `FAIL`
+ * - if any of the inputs are NULL
+ * - if an error is encountered while computing checksum
+ *
+ * Programmer: Jacob Smith
+ * 2017-07-??
+ *
+ *----------------------------------------------------------------------------
+ */
+herr_t
+H5FD_s3comms_tostringtosign(
+ char *dest,
+ const char *req,
+ const char *now,
+ const char *region)
+{
+ unsigned char checksum[SHA256_DIGEST_LENGTH * 2 + 1];
+ size_t d = 0;
+ char day[9];
+ char hexsum[SHA256_DIGEST_LENGTH * 2 + 1];
+ size_t i = 0;
+ int ret = 0; /* HDsnprintf return value */
+ herr_t ret_value = SUCCEED;
+ char tmp[128];
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+#if S3COMMS_DEBUG
+ HDfprintf(stdout, "called H5FD_s3comms_tostringtosign.\n");
+#endif
+
+ if (dest == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "destination buffer cannot be null.\n")
+ }
+ if (req == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "canonical request cannot be null.\n")
+ }
+ if (now == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "Timestring cannot be NULL.\n")
+ }
+ if (region == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "Region cannot be NULL.\n")
+ }
+
+ for (i = 0; i < 128; i++) {
+ tmp[i] = '\0';
+ }
+ for (i = 0; i < SHA256_DIGEST_LENGTH * 2 + 1; i++) {
+ checksum[i] = '\0';
+ hexsum[i] = '\0';
+ }
+ HDstrncpy(day, now, 8);
+ day[8] = '\0';
+ ret = HDsnprintf(tmp, 127, "%s/%s/s3/aws4_request", day, region);
+ if (ret <= 0 || ret >= 127) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "problem adding day and region to string")
+ }
+
+ HDmemcpy((dest + d), "AWS4-HMAC-SHA256\n", 17);
+ d = 17;
+
+ HDmemcpy((dest+d), now, HDstrlen(now));
+ d += HDstrlen(now);
+ dest[d++] = '\n';
+
+ HDmemcpy((dest + d), tmp, HDstrlen(tmp));
+ d += HDstrlen(tmp);
+ dest[d++] = '\n';
+
+ SHA256((const unsigned char *)req,
+ HDstrlen(req),
+ checksum);
+
+ if (H5FD_s3comms_bytes_to_hex(
+ hexsum,
+ (const unsigned char *)checksum,
+ SHA256_DIGEST_LENGTH,
+ true)
+ == FAIL)
+ {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "could not create hex string");
+ }
+
+ for (i = 0; i < SHA256_DIGEST_LENGTH * 2; i++) {
+ dest[d++] = hexsum[i];
+ }
+
+ dest[d] = '\0';
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5ros3_tostringtosign() */
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: H5FD_s3comms_trim()
+ *
+ * Purpose:
+ *
+ * Remove all whitespace characters from start and end of a string `s`
+ * of length `s_len`, writing trimmed string copy to `dest`.
+ * Stores number of characters remaining at `n_written`.
+ *
+ * Destination for trimmed copy `dest` cannot be null.
+ * `dest` must have adequate space allocated for trimmed copy.
+ * If inadequate space, behavior is undefined, possibly resulting
+ * in segfault or overwrite of other data.
+ *
+ * If `s` is NULL or all whitespace, `dest` is untouched and `n_written`
+ * is set to 0.
+ *
+ * Return:
+ *
+ * - SUCCESS: `SUCCEED`
+ * - FAILURE: `FAIL`
+ * - `dest == NULL`
+ *
+ * Programmer: Jacob Smith
+ * 2017-09-18
+ *
+ *----------------------------------------------------------------------------
+ */
+herr_t
+H5FD_s3comms_trim(char *dest,
+ char *s,
+ size_t s_len,
+ size_t *n_written)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+#if S3COMMS_DEBUG
+ HDfprintf(stdout, "called H5FD_s3comms_trim.\n");
+#endif
+
+ if (dest == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "destination cannot be null.")
+ }
+ if (s == NULL) {
+ s_len = 0;
+ }
+
+ if (s_len > 0) {
+ /* Find first non-whitespace character from start;
+ * reduce total length per character.
+ */
+ while ((s_len > 0) &&
+ isspace((unsigned char)s[0]) && s_len > 0)
+ {
+ s++;
+ s_len--;
+ }
+
+ /* Find first non-whitespace character from tail;
+ * reduce length per-character.
+ * If length is 0 already, there is no non-whitespace character.
+ */
+ if (s_len > 0) {
+ do {
+ s_len--;
+ } while( isspace((unsigned char)s[s_len]) );
+ s_len++;
+
+ /* write output into dest
+ */
+ HDmemcpy(dest, s, s_len);
+ }
+ }
+
+ *n_written = s_len;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_s3comms_trim() */
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: H5FD_s3comms_uriencode()
+ *
+ * Purpose:
+ *
+ * URIencode (percent-encode) every byte except "[a-zA-Z0-9]-._~".
+ *
+ * For each character in source string `_s` from `s[0]` to `s[s_len-1]`,
+ * writes to `dest` either the raw character or its percent-encoded
+ * equivalent.
+ *
+ * See `H5FD_s3comms_bytes_to_hex` for information on percent-encoding.
+ *
+ * Space (' ') character encoded as "%20" (not "+")
+ *
+ * Forward-slash ('/') encoded as "%2F" only when `encode_slash == true`.
+ *
+ * Records number of characters written at `n_written`.
+ *
+ * Assumes that `dest` has been allocated with enough space.
+ *
+ * Neither `dest` nor `s` can be NULL.
+ *
+ * `s_len == 0` will have no effect.
+ *
+ * Return:
+ *
+ * - SUCCESS: `SUCCEED`
+ * - FAILURE: `FAIL`
+ * - source strings `s` or destination `dest` are NULL
+ * - error while attempting to percent-encode a character
+ *
+ * Programmer: Jacob Smith
+ * 2017-07-??
+ *
+ *----------------------------------------------------------------------------
+ */
+herr_t
+H5FD_s3comms_uriencode(
+ char *dest,
+ const char *s,
+ size_t s_len,
+ hbool_t encode_slash,
+ size_t *n_written)
+{
+ char c = 0;
+ size_t dest_off = 0;
+ char hex_buffer[13];
+ size_t hex_off = 0;
+ size_t hex_len = 0;
+ herr_t ret_value = SUCCEED;
+ size_t s_off = 0;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+#if S3COMMS_DEBUG
+ HDfprintf(stdout, "H5FD_s3comms_uriencode called.\n");
+#endif
+
+ if (s == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "source string cannot be NULL");
+ }
+ if (dest == NULL) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "destination cannot be NULL");
+ }
+
+ /* Write characters to destination, converting to percent-encoded
+ * "hex-utf-8" strings if necessary.
+ * e.g., '$' -> "%24"
+ */
+ for (s_off = 0; s_off < s_len; s_off++) {
+ c = s[s_off];
+ if (isalnum(c) ||
+ c == '.' ||
+ c == '-' ||
+ c == '_' ||
+ c == '~' ||
+ (c == '/' && encode_slash == FALSE))
+ {
+ dest[dest_off++] = c;
+ }
+ else {
+ hex_off = 0;
+ if (H5FD_s3comms_percent_encode_char(
+ hex_buffer,
+ (const unsigned char)c,
+ &hex_len)
+ == FAIL)
+ {
+ hex_buffer[0] = c;
+ hex_buffer[1] = 0;
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "unable to percent-encode character \'%s\' "
+ "at %d in \"%s\"", hex_buffer, (int)s_off, s);
+ }
+
+ for (hex_off = 0; hex_off < hex_len; hex_off++) {
+ dest[dest_off++] = hex_buffer[hex_off];
+ }
+ } /* end else (not a regular character) */
+ } /* end for each character */
+
+ if (dest_off < s_len)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "buffer overflow");
+
+ *n_written = dest_off;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5FD_s3comms_uriencode */
+
+#endif /* H5_HAVE_ROS3_VFD */
+
diff --git a/src/H5FDs3comms.h b/src/H5FDs3comms.h
new file mode 100644
index 0000000..90c6650
--- /dev/null
+++ b/src/H5FDs3comms.h
@@ -0,0 +1,604 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*****************************************************************************
+ * Read-Only S3 Virtual File Driver (VFD)
+ *
+ * This is the header for the S3 Communications module
+ *
+ * ***NOT A FILE DRIVER***
+ *
+ * Purpose:
+ *
+ * - Provide structures and functions related to communicating with
+ * Amazon S3 (Simple Storage Service).
+ * - Abstract away the REST API (HTTP,
+ * networked communications) behind a series of uniform function calls.
+ * - Handle AWS4 authentication, if appropriate.
+ * - Fail predictably in event of errors.
+ * - Eventually, support more S3 operations, such as creating, writing to,
+ * and removing Objects remotely.
+ *
+ * translates:
+ * `read(some_file, bytes_offset, bytes_length, &dest_buffer);`
+ * to:
+ * ```
+ * GET myfile HTTP/1.1
+ * Host: somewhere.me
+ * Range: bytes=4096-5115
+ * ```
+ * and places received bytes from HTTP response...
+ * ```
+ * HTTP/1.1 206 Partial-Content
+ * Content-Range: 4096-5115/63239
+ *
+ * <bytes>
+ * ```
+ * ...in destination buffer.
+ *
+ * TODO: put documentation in a consistent place and point to it from here.
+ *
+ * Programmer: Jacob Smith
+ * 2017-11-30
+ *
+ *****************************************************************************/
+
+#include "H5private.h" /* Generic Functions */
+
+#ifdef H5_HAVE_ROS3_VFD
+
+/* Necessary S3 headers */
+#include <curl/curl.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+#include <openssl/sha.h>
+
+/*****************
+ * PUBLIC MACROS *
+ *****************/
+
+/* hexadecimal string of pre-computed sha256 checksum of the empty string
+ * hex(sha256sum(""))
+ */
+#define EMPTY_SHA256 \
+"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+
+/* string length (plus null terminator)
+ * example ISO8601-format string: "20170713T145903Z" (YYYYmmdd'T'HHMMSS'_')
+ */
+#define ISO8601_SIZE 17
+
+/* string length (plus null terminator)
+ * example RFC7231-format string: "Fri, 30 Jun 2017 20:41:55 GMT"
+ */
+#define RFC7231_SIZE 30
+
+/*---------------------------------------------------------------------------
+ *
+ * Macro: ISO8601NOW()
+ *
+ * Purpose:
+ *
+ * write "YYYYmmdd'T'HHMMSS'Z'" (less single-quotes) to dest
+ * e.g., "20170630T204155Z"
+ *
+ * wrapper for strftime()
+ *
+ * It is left to the programmer to check return value of
+ * ISO8601NOW (should equal ISO8601_SIZE - 1).
+ *
+ *---------------------------------------------------------------------------
+ */
+#define ISO8601NOW(dest, now_gm) \
+strftime((dest), ISO8601_SIZE, "%Y%m%dT%H%M%SZ", (now_gm))
+
+/*---------------------------------------------------------------------------
+ *
+ * Macro: RFC7231NOW()
+ *
+ * Purpose:
+ *
+ * write "Day, dd Mmm YYYY HH:MM:SS GMT" to dest
+ * e.g., "Fri, 30 Jun 2017 20:41:55 GMT"
+ *
+ * wrapper for strftime()
+ *
+ * It is left to the programmer to check return value of
+ * RFC7231NOW (should equal RFC7231_SIZE - 1).
+ *
+ *---------------------------------------------------------------------------
+ */
+#define RFC7231NOW(dest, now_gm) \
+strftime((dest), RFC7231_SIZE, "%a, %d %b %Y %H:%M:%S GMT", (now_gm))
+
+
+/* Reasonable maximum length of a credential string.
+ * Provided for error-checking S3COMMS_FORMAT_CREDENTIAL (below).
+ * 17 <- "////aws4_request\0"
+ * 2 < "s3" (service)
+ * 8 <- "YYYYmmdd" (date)
+ * 128 <- (access_id)
+ * 155 :: sum
+ */
+#define S3COMMS_MAX_CREDENTIAL_SIZE 155
+
+
+/*---------------------------------------------------------------------------
+ *
+ * Macro: H5FD_S3COMMS_FORMAT_CREDENTIAL()
+ *
+ * Purpose:
+ *
+ * Format "S3 Credential" string from inputs, for AWS4.
+ *
+ * Wrapper for HDsnprintf().
+ *
+ * _HAS NO ERROR-CHECKING FACILITIES_
+ * It is left to programmer to ensure that return value confers success.
+ * e.g.,
+ * ```
+ * assert( S3COMMS_MAX_CREDENTIAL_SIZE >=
+ * S3COMMS_FORMAT_CREDENTIAL(...) );
+ * ```
+ *
+ * "<access-id>/<date>/<aws-region>/<aws-service>/aws4_request"
+ * assuming that `dest` has adequate space.
+ *
+ * ALL inputs must be null-terminated strings.
+ *
+ * `access` should be the user's access key ID.
+ * `date` must be of format "YYYYmmdd".
+ * `region` should be relevant AWS region, i.e. "us-east-1".
+ * `service` should be "s3".
+ *
+ *---------------------------------------------------------------------------
+ */
+#define S3COMMS_FORMAT_CREDENTIAL(dest, access, iso8601_date, region, service) \
+HDsnprintf((dest), S3COMMS_MAX_CREDENTIAL_SIZE, \
+ "%s/%s/%s/%s/aws4_request", \
+ (access), (iso8601_date), (region), (service))
+
+/*********************
+ * PUBLIC STRUCTURES *
+ *********************/
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Structure: hrb_node_t
+ *
+ * HTTP Header Field Node
+ *
+ *
+ *
+ * Maintain a ordered (linked) list of HTTP Header fields.
+ *
+ * Provides efficient access and manipulation of a logical sequence of
+ * HTTP header fields, of particular use when composing an
+ * "S3 Canonical Request" for authentication.
+ *
+ * - The creation of a Canoncial Request involves:
+ * - convert field names to lower case
+ * - sort by this lower-case name
+ * - convert ": " name-value separator in HTTP string to ":"
+ * - get sorted lowercase names without field or separator
+ *
+ * As HTTP headers allow headers in any order (excepting the case of multiple
+ * headers with the same name), the list ordering can be optimized for Canonical
+ * Request creation, suggesting alphabtical order. For more expedient insertion
+ * and removal of elements in the list, linked list seems preferable to a
+ * dynamically-expanding array. The usually-smaller number of entries (5 or
+ * fewer) makes performance overhead of traversing the list trivial.
+ *
+ * The above requirements of creating at Canonical Request suggests a reasonable
+ * trade-off of speed for space with the option to compute elements as needed
+ * or to have the various elements prepared and stored in the structure
+ * (e.g. name, value, lowername, concatenated name:value)
+ * The structure currently is implemented to pre-compute.
+ *
+ * At all times, the "first" node of the list should be the least,
+ * alphabetically. For all nodes, the `next` node should be either NULL or
+ * of greater alphabetical value.
+ *
+ * Each node contains its own header field information, plus a pointer to the
+ * next node.
+ *
+ * It is not allowed to have multiple nodes with the same _lowercase_ `name`s
+ * in the same list
+ * (i.e., name is case-insensitive for access and modification.)
+ *
+ * All data (`name`, `value`, `lowername`, and `cat`) are null-terminated
+ * strings allocated specifically for their node.
+ *
+ *
+ *
+ * `magic` (unsigned long)
+ *
+ * "unique" idenfier number for the structure type
+ *
+ * `name` (char *)
+ *
+ * Case-meaningful name of the HTTP field.
+ * Given case is how it is supplied to networking code.
+ * e.g., "Range"
+ *
+ * `lowername` (char *)
+ *
+ * Lowercase copy of name.
+ * e.g., "range"
+ *
+ * `value` (char *)
+ *
+ * Case-meaningful value of HTTP field.
+ * e.g., "bytes=0-9"
+ *
+ * `cat` (char *)
+ *
+ * Concatenated, null-terminated string of HTTP header line,
+ * as the field would appear in an HTTP request.
+ * e.g., "Range: bytes=0-9"
+ *
+ * `next` (hrb_node_t *)
+ *
+ * Pointers to next node in the list, or NULL sentinel as end of list.
+ * Next node must have a greater `lowername` as determined by strcmp().
+ *
+ *----------------------------------------------------------------------------
+ */
+typedef struct hrb_node_t {
+ unsigned long magic;
+ char *name;
+ char *value;
+ char *cat;
+ char *lowername;
+ struct hrb_node_t *next;
+} hrb_node_t;
+#define S3COMMS_HRB_NODE_MAGIC 0x7F5757UL
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Structure: hrb_t
+ *
+ * HTTP Request Buffer structure
+ *
+ *
+ *
+ * Logically represent an HTTP request
+ *
+ * GET /myplace/myfile.h5 HTTP/1.1
+ * Host: over.rainbow.oz
+ * Date: Fri, 01 Dec 2017 12:35:04 CST
+ *
+ * <body>
+ *
+ * ...with fast, efficient access to and modification of primary and field
+ * elements.
+ *
+ * Structure for building HTTP requests while hiding much of the string
+ * processing required "under the hood."
+ *
+ * Information about the request target -- the first line -- and the body text,
+ * if any, are managed directly with this structure. All header fields, e.g.,
+ * "Host" and "Date" above, are created with a linked list of `hrb_node_t` and
+ * included in the request by a pointer to the head of the list.
+ *
+ *
+ *
+ * `magic` (unsigned long)
+ *
+ * "Magic" number confirming that this is an hrb_t structure and
+ * what operations are valid for it.
+ *
+ * Must be S3COMMS_HRB_MAGIC to be valid.
+ *
+ * `body` (char *) :
+ *
+ * Pointer to start of HTTP body.
+ *
+ * Can be NULL, in which case it is treated as the empty string, "".
+ *
+ * `body_len` (size_t) :
+ *
+ * Number of bytes (characters) in `body`. 0 if empty or NULL `body`.
+ *
+ * `first_header` (hrb_node_t *) :
+ *
+ * Pointer to first SORTED header node, if any.
+ * It is left to the programmer to ensure that this node and associated
+ * list is destroyed when done.
+ *
+ * `resource` (char *) :
+ *
+ * Pointer to resource URL string, e.g., "/folder/page.xhtml".
+ *
+ * `verb` (char *) :
+ *
+ * Pointer to HTTP verb string, e.g., "GET".
+ *
+ * `version` (char *) :
+ *
+ * Pointer to HTTP version string, e.g., "HTTP/1.1".
+ *
+ *----------------------------------------------------------------------------
+ */
+typedef struct {
+ unsigned long magic;
+ char *body;
+ size_t body_len;
+ hrb_node_t *first_header;
+ char *resource;
+ char *verb;
+ char *version;
+} hrb_t;
+#define S3COMMS_HRB_MAGIC 0x6DCC84UL
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Structure: parsed_url_t
+ *
+ *
+ * Represent a URL with easily-accessed pointers to logical elements within.
+ * These elements (components) are stored as null-terminated strings (or just
+ * NULLs). These components should be allocated for the structure, making the
+ * data as safe as possible from modification. If a component is NULL, it is
+ * either implicit in or absent from the URL.
+ *
+ * "http://mybucket.s3.amazonaws.com:8080/somefile.h5?param=value&arg=value"
+ * ^--^ ^-----------------------^ ^--^ ^---------^ ^-------------------^
+ * Scheme Host Port Resource Query/-ies
+ *
+ *
+ *
+ * `magic` (unsigned long)
+ *
+ * Structure identification and validation identifier.
+ * Identifies as `parsed_url_t` type.
+ *
+ * `scheme` (char *)
+ *
+ * String representing which protocol is to be expected.
+ * _Must_ be present.
+ * "http", "https", "ftp", e.g.
+ *
+ * `host` (char *)
+ *
+ * String of host, either domain name, IPv4, or IPv6 format.
+ * _Must_ be present.
+ * "over.rainbow.oz", "192.168.0.1", "[0000:0000:0000:0001]"
+ *
+ * `port` (char *)
+ *
+ * String representation of specified port. Must resolve to a valid unsigned
+ * integer.
+ * "9000", "80"
+ *
+ * `path` (char *)
+ *
+ * Path to resource on host. If not specified, assumes root "/".
+ * "lollipop_guild.wav", "characters/witches/white.dat"
+ *
+ * `query` (char *)
+ *
+ * Single string of all query parameters in url (if any).
+ * "arg1=value1&arg2=value2"
+ *
+ *----------------------------------------------------------------------------
+ */
+typedef struct {
+ unsigned long magic;
+ char *scheme; /* required */
+ char *host; /* required */
+ char *port;
+ char *path;
+ char *query;
+} parsed_url_t;
+#define S3COMMS_PARSED_URL_MAGIC 0x21D0DFUL
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Structure: s3r_t
+ *
+ *
+ *
+ * S3 request structure "handle".
+ *
+ * Holds persistent information for Amazon S3 requests.
+ *
+ * Instantiated through `H5FD_s3comms_s3r_open()`, copies data into self.
+ *
+ * Intended to be re-used for operations on a remote object.
+ *
+ * Cleaned up through `H5FD_s3comms_s3r_close()`.
+ *
+ * _DO NOT_ share handle between threads: curl easy handle `curlhandle` has
+ * undefined behavior if called to perform in multiple threads.
+ *
+ *
+ *
+ * `magic` (unsigned long)
+ *
+ * "magic" number identifying this structure as unique type.
+ * MUST equal `S3R_MAGIC` to be valid.
+ *
+ * `curlhandle` (CURL)
+ *
+ * Pointer to the curl_easy handle generated for the request.
+ *
+ * `httpverb` (char *)
+ *
+ * Pointer to NULL-terminated string. HTTP verb,
+ * e.g. "GET", "HEAD", "PUT", etc.
+ *
+ * Default is NULL, resulting in a "GET" request.
+ *
+ * `purl` (parsed_url_t *)
+ *
+ * Pointer to structure holding the elements of URL for file open.
+ *
+ * e.g., "http://bucket.aws.com:8080/myfile.dat?q1=v1&q2=v2"
+ * parsed into...
+ * { scheme: "http"
+ * host: "bucket.aws.com"
+ * port: "8080"
+ * path: "myfile.dat"
+ * query: "q1=v1&q2=v2"
+ * }
+ *
+ * Cannot be NULL.
+ *
+ * `region` (char *)
+ *
+ * Pointer to NULL-terminated string, specifying S3 "region",
+ * e.g., "us-east-1".
+ *
+ * Required to authenticate.
+ *
+ * `secret_id` (char *)
+ *
+ * Pointer to NULL-terminated string for "secret" access id to S3 resource.
+ *
+ * Requred to authenticate.
+ *
+ * `signing_key` (unsigned char *)
+ *
+ * Pointer to `SHA256_DIGEST_LENGTH`-long string for "re-usable" signing
+ * key, generated via
+ * `HMAC-SHA256(HMAC-SHA256(HMAC-SHA256(HMAC-SHA256("AWS4<secret_key>",
+ * "<yyyyMMDD"), "<aws-region>"), "<aws-service>"), "aws4_request")`
+ * which may be re-used for several (up to seven (7)) days from creation?
+ * Computed once upon file open.
+ *
+ * Requred to authenticate.
+ *
+ *----------------------------------------------------------------------------
+ */
+typedef struct {
+ unsigned long magic;
+ CURL *curlhandle;
+ size_t filesize;
+ char *httpverb;
+ parsed_url_t *purl;
+ char *region;
+ char *secret_id;
+ unsigned char *signing_key;
+} s3r_t;
+
+#define S3COMMS_S3R_MAGIC 0x44d8d79
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*******************************************
+ * DECLARATION OF HTTP FIELD LIST ROUTINES *
+ *******************************************/
+
+H5_DLL herr_t H5FD_s3comms_hrb_node_set(hrb_node_t **L,
+ const char *name,
+ const char *value);
+
+/***********************************************
+ * DECLARATION OF HTTP REQUEST BUFFER ROUTINES *
+ ***********************************************/
+
+H5_DLL herr_t H5FD_s3comms_hrb_destroy(hrb_t **buf);
+
+H5_DLL hrb_t * H5FD_s3comms_hrb_init_request(const char *verb,
+ const char *resource,
+ const char *host);
+
+/*************************************
+ * DECLARATION OF S3REQUEST ROUTINES *
+ *************************************/
+
+H5_DLL herr_t H5FD_s3comms_s3r_close(s3r_t *handle);
+
+H5_DLL size_t H5FD_s3comms_s3r_get_filesize(s3r_t *handle);
+
+H5_DLL s3r_t * H5FD_s3comms_s3r_open(const char url[],
+ const char region[],
+ const char id[],
+ const unsigned char signing_key[]);
+
+H5_DLL herr_t H5FD_s3comms_s3r_read(s3r_t *handle,
+ haddr_t offset,
+ size_t len,
+ void *dest);
+
+/*********************************
+ * DECLARATION OF OTHER ROUTINES *
+ *********************************/
+
+H5_DLL struct tm * gmnow(void);
+
+H5_DLL herr_t H5FD_s3comms_aws_canonical_request(char *canonical_request_dest,
+ int cr_size,
+ char *signed_headers_dest,
+ int sh_size,
+ hrb_t *http_request);
+
+H5_DLL herr_t H5FD_s3comms_bytes_to_hex(char *dest,
+ const unsigned char *msg,
+ size_t msg_len,
+ hbool_t lowercase);
+
+H5_DLL herr_t H5FD_s3comms_free_purl(parsed_url_t *purl);
+
+H5_DLL herr_t H5FD_s3comms_HMAC_SHA256(const unsigned char *key,
+ size_t key_len,
+ const char *msg,
+ size_t msg_len,
+ char *dest);
+
+H5_DLL herr_t H5FD_s3comms_load_aws_profile(const char *name,
+ char *key_id_out,
+ char *secret_access_key_out,
+ char *aws_region_out);
+
+H5_DLL herr_t H5FD_s3comms_nlowercase(char *dest,
+ const char *s,
+ size_t len);
+
+H5_DLL herr_t H5FD_s3comms_parse_url(const char *str,
+ parsed_url_t **purl);
+
+H5_DLL herr_t H5FD_s3comms_percent_encode_char(char *repr,
+ const unsigned char c,
+ size_t *repr_len);
+
+H5_DLL herr_t H5FD_s3comms_signing_key(unsigned char *md,
+ const char *secret,
+ const char *region,
+ const char *iso8601now);
+
+H5_DLL herr_t H5FD_s3comms_tostringtosign(char *dest,
+ const char *req_str,
+ const char *now,
+ const char *region);
+
+H5_DLL herr_t H5FD_s3comms_trim(char *dest,
+ char *s,
+ size_t s_len,
+ size_t *n_written);
+
+H5_DLL herr_t H5FD_s3comms_uriencode(char *dest, const char *s, size_t s_len,
+ hbool_t encode_slash, size_t *n_written);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* H5_HAVE_ROS3_VFD */
+
diff --git a/src/H5FDsec2.c b/src/H5FDsec2.c
index 32aff0f..0054a86 100644
--- a/src/H5FDsec2.c
+++ b/src/H5FDsec2.c
@@ -94,7 +94,7 @@ typedef struct H5FD_sec2_t {
* Whether to eliminate the family driver info and convert this file to
* a single file.
*/
- hbool_t fam_to_sec2;
+ hbool_t fam_to_single;
} H5FD_sec2_t;
@@ -208,8 +208,8 @@ done:
* Purpose: Initialize this driver by registering the driver with the
* library.
*
- * Return: Success: The driver ID for the sec2 driver.
- * Failure: Negative
+ * Return: Success: The driver ID for the sec2 driver
+ * Failure: H5I_INVALID_HID
*
* Programmer: Robb Matzke
* Thursday, July 29, 1999
@@ -221,7 +221,7 @@ H5FD_sec2_init(void)
{
hid_t ret_value = H5I_INVALID_HID; /* Return value */
- FUNC_ENTER_NOAPI(FAIL)
+ FUNC_ENTER_NOAPI(H5I_INVALID_HID)
if(H5I_VFL != H5I_get_type(H5FD_SEC2_g))
H5FD_SEC2_g = H5FD_register(&H5FD_sec2_g, sizeof(H5FD_class_t), FALSE);
@@ -386,13 +386,13 @@ H5FD_sec2_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr)
HGOTO_ERROR(H5E_VFL, H5E_BADTYPE, NULL, "not a file access property list")
/* This step is for h5repart tool only. If user wants to change file driver from
- * family to sec2 while using h5repart, this private property should be set so that
- * in the later step, the library can ignore the family driver information saved
- * in the superblock.
+ * family to one that uses single files (sec2, etc.) while using h5repart, this
+ * private property should be set so that in the later step, the library can ignore
+ * the family driver information saved in the superblock.
*/
- if(H5P_exist_plist(plist, H5F_ACS_FAMILY_TO_SEC2_NAME) > 0)
- if(H5P_get(plist, H5F_ACS_FAMILY_TO_SEC2_NAME, &file->fam_to_sec2) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTGET, NULL, "can't get property of changing family to sec2")
+ if(H5P_exist_plist(plist, H5F_ACS_FAMILY_TO_SINGLE_NAME) > 0)
+ if(H5P_get(plist, H5F_ACS_FAMILY_TO_SINGLE_NAME, &file->fam_to_single) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTGET, NULL, "can't get property of changing family to single")
} /* end if */
/* Set return value */
@@ -532,7 +532,7 @@ H5FD_sec2_query(const H5FD_t *_file, unsigned long *flags /* out */)
*flags |= H5FD_FEAT_DEFAULT_VFD_COMPATIBLE; /* VFD creates a file which can be opened with the default VFD */
/* Check for flags that are set by h5repart */
- if(file && file->fam_to_sec2)
+ if(file && file->fam_to_single)
*flags |= H5FD_FEAT_IGNORE_DRVRINFO; /* Ignore the driver info when file is opened (which eliminates it) */
} /* end if */
@@ -682,11 +682,13 @@ H5FD_sec2_read(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type, hid_t H5_ATTR_UNUS
if(REGION_OVERFLOW(addr, size))
HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, FAIL, "addr overflow, addr = %llu", (unsigned long long)addr)
- /* Seek to the correct location */
+#ifndef H5_HAVE_PREADWRITE
+ /* Seek to the correct location (if we don't have pread) */
if(addr != file->pos || OP_READ != file->op) {
if(HDlseek(file->fd, (HDoff_t)addr, SEEK_SET) < 0)
HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to seek to proper position")
} /* end if */
+#endif /* H5_HAVE_PREADWRITE */
/* Read data, being careful of interrupted system calls, partial results,
* and the end of the file.
@@ -694,7 +696,8 @@ H5FD_sec2_read(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type, hid_t H5_ATTR_UNUS
while(size > 0) {
h5_posix_io_t bytes_in = 0; /* # of bytes to read */
- h5_posix_io_ret_t bytes_read = -1; /* # of bytes actually read */
+ h5_posix_io_ret_t bytes_read = -1; /* # of bytes actually read */
+ HDoff_t offset = (HDoff_t)addr;
/* Trying to read more bytes than the return type can handle is
* undefined behavior in POSIX.
@@ -705,15 +708,21 @@ H5FD_sec2_read(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type, hid_t H5_ATTR_UNUS
bytes_in = (h5_posix_io_t)size;
do {
+#ifdef H5_HAVE_PREADWRITE
+ bytes_read = HDpread(file->fd, buf, bytes_in, offset);
+ offset += bytes_read;
+#else
bytes_read = HDread(file->fd, buf, bytes_in);
+#endif /* H5_HAVE_PREADWRITE */
} while(-1 == bytes_read && EINTR == errno);
if(-1 == bytes_read) { /* error */
int myerrno = errno;
time_t mytime = HDtime(NULL);
- HDoff_t myoffset = HDlseek(file->fd, (HDoff_t)0, SEEK_CUR);
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file read failed: time = %s, filename = '%s', file descriptor = %d, errno = %d, error message = '%s', buf = %p, total read size = %llu, bytes this sub-read = %llu, bytes actually read = %llu, offset = %llu", HDctime(&mytime), file->filename, file->fd, myerrno, HDstrerror(myerrno), buf, (unsigned long long)size, (unsigned long long)bytes_in, (unsigned long long)bytes_read, (unsigned long long)myoffset);
+ offset = HDlseek(file->fd, (HDoff_t)0, SEEK_CUR);
+
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file read failed: time = %s, filename = '%s', file descriptor = %d, errno = %d, error message = '%s', buf = %p, total read size = %llu, bytes this sub-read = %llu, bytes actually read = %llu, offset = %llu", HDctime(&mytime), file->filename, file->fd, myerrno, HDstrerror(myerrno), buf, (unsigned long long)size, (unsigned long long)bytes_in, (unsigned long long)bytes_read, (unsigned long long)offset);
} /* end if */
if(0 == bytes_read) {
@@ -777,11 +786,13 @@ H5FD_sec2_write(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type, hid_t H5_ATTR_UNU
if(REGION_OVERFLOW(addr, size))
HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, FAIL, "addr overflow, addr = %llu, size = %llu", (unsigned long long)addr, (unsigned long long)size)
- /* Seek to the correct location */
+#ifndef H5_HAVE_PREADWRITE
+ /* Seek to the correct location (if we don't have pwrite) */
if(addr != file->pos || OP_WRITE != file->op) {
if(HDlseek(file->fd, (HDoff_t)addr, SEEK_SET) < 0)
HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to seek to proper position")
} /* end if */
+#endif /* H5_HAVE_PREADWRITE */
/* Write the data, being careful of interrupted system calls and partial
* results
@@ -790,6 +801,7 @@ H5FD_sec2_write(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type, hid_t H5_ATTR_UNU
h5_posix_io_t bytes_in = 0; /* # of bytes to write */
h5_posix_io_ret_t bytes_wrote = -1; /* # of bytes written */
+ HDoff_t offset = (HDoff_t)addr;
/* Trying to write more bytes than the return type can handle is
* undefined behavior in POSIX.
@@ -800,15 +812,21 @@ H5FD_sec2_write(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type, hid_t H5_ATTR_UNU
bytes_in = (h5_posix_io_t)size;
do {
+#ifdef H5_HAVE_PREADWRITE
+ bytes_wrote = HDpwrite(file->fd, buf, bytes_in, offset);
+ offset += bytes_wrote;
+#else
bytes_wrote = HDwrite(file->fd, buf, bytes_in);
+#endif /* H5_HAVE_PREADWRITE */
} while(-1 == bytes_wrote && EINTR == errno);
if(-1 == bytes_wrote) { /* error */
int myerrno = errno;
time_t mytime = HDtime(NULL);
- HDoff_t myoffset = HDlseek(file->fd, (HDoff_t)0, SEEK_CUR);
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed: time = %s, filename = '%s', file descriptor = %d, errno = %d, error message = '%s', buf = %p, total write size = %llu, bytes this sub-write = %llu, bytes actually written = %llu, offset = %llu", HDctime(&mytime), file->filename, file->fd, myerrno, HDstrerror(myerrno), buf, (unsigned long long)size, (unsigned long long)bytes_in, (unsigned long long)bytes_wrote, (unsigned long long)myoffset);
+ offset = HDlseek(file->fd, (HDoff_t)0, SEEK_CUR);
+
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed: time = %s, filename = '%s', file descriptor = %d, errno = %d, error message = '%s', buf = %p, total write size = %llu, bytes this sub-write = %llu, bytes actually written = %llu, offset = %llu", HDctime(&mytime), file->filename, file->fd, myerrno, HDstrerror(myerrno), buf, (unsigned long long)size, (unsigned long long)bytes_in, (unsigned long long)bytes_wrote, (unsigned long long)offset);
} /* end if */
HDassert(bytes_wrote > 0);
diff --git a/src/H5FDtest.c b/src/H5FDtest.c
index 18b53a0..aa256a3 100644
--- a/src/H5FDtest.c
+++ b/src/H5FDtest.c
@@ -108,11 +108,10 @@ H5FD__supports_swmr_test(const char *vfd_name)
FUNC_ENTER_NOAPI_NOINIT_NOERR
- if(!vfd_name || !HDstrcmp(vfd_name, ""))
+ if(!vfd_name || !HDstrcmp(vfd_name, "") || !HDstrcmp(vfd_name, "nomatch"))
ret_value = TRUE;
else
- ret_value = !HDstrcmp(vfd_name, "log")
- || !HDstrcmp(vfd_name, "sec2");
+ ret_value = !HDstrcmp(vfd_name, "log") || !HDstrcmp(vfd_name, "sec2");
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5FDvfd_swmr.c b/src/H5FDvfd_swmr.c
index 2fc9149..c804fb7 100644
--- a/src/H5FDvfd_swmr.c
+++ b/src/H5FDvfd_swmr.c
@@ -26,6 +26,7 @@
#include "H5Iprivate.h" /* IDs */
#include "H5MMprivate.h" /* Memory management */
#include "H5Pprivate.h" /* Property lists */
+#include "H5retry_private.h"/* Retry loops. */
/* The driver identification number, initialized at runtime */
static hid_t H5FD_VFD_SWMR_g = 0;
@@ -1133,119 +1134,115 @@ H5FD__vfd_swmr_load_hdr_and_idx(H5FD_t *_file, hbool_t open)
{
H5FD_vfd_swmr_t *file = /* VFD SWMR file struct */
(H5FD_vfd_swmr_t *)_file;
- unsigned load_retries = /* Retries for loading header */
- H5FD_VFD_SWMR_MD_LOAD_RETRY_MAX; /* and index */
- uint64_t nanosec = 1; /* # of nanoseconds to sleep */
- /* between retries */
+ bool do_try;
+ h5_retry_t retry;
H5FD_vfd_swmr_md_header md_header; /* Metadata file header */
H5FD_vfd_swmr_md_index md_index; /* Metadata file index */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC
- do {
+ for (do_try = h5_retry_init(&retry, H5FD_VFD_SWMR_MD_LOAD_RETRY_MAX,
+ 1, H5_RETRY_ONE_HOUR / 3600);
+ do_try;
+ do_try = h5_retry_next(&retry)) {
HDmemset(&md_header, 0, sizeof(H5FD_vfd_swmr_md_header));
HDmemset(&md_index, 0, sizeof(H5FD_vfd_swmr_md_index));
/* Load and decode the header */
- if(H5FD__vfd_swmr_header_deserialize(_file, &md_header) >= 0) {
+ if(H5FD__vfd_swmr_header_deserialize(_file, &md_header) < 0)
+ continue;
- /* Error if header + index does not fit within md_pages_reserved */
- if((H5FD_MD_HEADER_SIZE + md_header.index_length) >
- (uint64_t)((hsize_t)file->md_pages_reserved *
- md_header.fs_page_size))
+ /* Error if header + index does not fit within md_pages_reserved */
+ if((H5FD_MD_HEADER_SIZE + md_header.index_length) >
+ (uint64_t)((hsize_t)file->md_pages_reserved *
+ md_header.fs_page_size))
- HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, \
- "header + index does not fit within md_pages_reserved")
+ HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, \
+ "header + index does not fit within md_pages_reserved")
- if(!open) {
+ if(!open) {
- if(md_header.tick_num == file->md_header.tick_num) {
+ if(md_header.tick_num == file->md_header.tick_num) {
- break;
+ break;
- } else if(md_header.tick_num < file->md_header.tick_num)
+ } else if(md_header.tick_num < file->md_header.tick_num)
- HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, \
- "tick number read is less than local copy")
- }
+ HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, \
+ "tick number read is less than local copy")
+ }
- HDassert(md_header.tick_num > file->md_header.tick_num || open);
+ HDassert(md_header.tick_num > file->md_header.tick_num || open);
- /* Load and decode the index */
- if(H5FD__vfd_swmr_index_deserialize(_file, &md_index,
- &md_header) >= 0) {
+ /* Load and decode the index */
+ if(H5FD__vfd_swmr_index_deserialize(_file, &md_index,
+ &md_header) >= 0) {
- /* tick_num is the same in both header and index */
- if(md_header.tick_num == md_index.tick_num) {
+ /* tick_num is the same in both header and index */
+ if(md_header.tick_num == md_index.tick_num) {
- /* Copy header to VFD local copy */
- HDmemcpy(&file->md_header, &md_header,
- sizeof(H5FD_vfd_swmr_md_header));
+ /* Copy header to VFD local copy */
+ HDmemcpy(&file->md_header, &md_header,
+ sizeof(H5FD_vfd_swmr_md_header));
- /* Free VFD local entries */
- if(file->md_index.entries) {
+ /* Free VFD local entries */
+ if(file->md_index.entries) {
- HDassert(file->md_index.num_entries);
+ HDassert(file->md_index.num_entries);
- file->md_index.entries = (H5FD_vfd_swmr_idx_entry_t *)
- H5FL_SEQ_FREE(H5FD_vfd_swmr_idx_entry_t,
- file->md_index.entries);
- }
+ file->md_index.entries = (H5FD_vfd_swmr_idx_entry_t *)
+ H5FL_SEQ_FREE(H5FD_vfd_swmr_idx_entry_t,
+ file->md_index.entries);
+ }
- /* Copy index info to VFD local copy */
- file->md_index.tick_num = md_index.tick_num;
- file->md_index.num_entries = md_index.num_entries;
+ /* Copy index info to VFD local copy */
+ file->md_index.tick_num = md_index.tick_num;
+ file->md_index.num_entries = md_index.num_entries;
- /* Allocate and copy index entries */
- if(md_index.num_entries) {
+ /* Allocate and copy index entries */
+ if(md_index.num_entries) {
- if(NULL == (file->md_index.entries =
- H5FL_SEQ_MALLOC(H5FD_vfd_swmr_idx_entry_t,
- md_index.num_entries)))
+ if(NULL == (file->md_index.entries =
+ H5FL_SEQ_MALLOC(H5FD_vfd_swmr_idx_entry_t,
+ md_index.num_entries)))
- HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, \
- "memory allocation failed for index entries")
+ HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, \
+ "memory allocation failed for index entries")
- HDmemcpy(file->md_index.entries, md_index.entries,
- md_index.num_entries *
- sizeof(H5FD_vfd_swmr_idx_entry_t));
- }
- break;
+ HDmemcpy(file->md_index.entries, md_index.entries,
+ md_index.num_entries *
+ sizeof(H5FD_vfd_swmr_idx_entry_t));
}
- /* Error when tick_num in header is more than one greater
- * that in the index
- */
- else if (md_header.tick_num > (md_index.tick_num + 1))
-
- HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, \
- "tick number mis-match in header and index")
-
- if(md_index.entries) {
+ break;
+ }
+ /* Error when tick_num in header is more than one greater
+ * that in the index
+ */
+ else if (md_header.tick_num > (md_index.tick_num + 1))
- HDassert(md_index.num_entries);
- md_index.entries = (H5FD_vfd_swmr_idx_entry_t *)
- H5FL_SEQ_FREE(H5FD_vfd_swmr_idx_entry_t,
- md_index.entries);
- }
+ HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, \
+ "tick number mis-match in header and index")
- } /* end if index ok */
- } /* end if header ok */
+ if(md_index.entries) {
- /* Sleep and double the sleep time next time */
- H5_nanosleep(nanosec);
- nanosec *= 2;
+ HDassert(md_index.num_entries);
+ md_index.entries = (H5FD_vfd_swmr_idx_entry_t *)
+ H5FL_SEQ_FREE(H5FD_vfd_swmr_idx_entry_t,
+ md_index.entries);
+ }
- } while(--load_retries);
+ } /* end if index ok */
+ }
/* Exhaust all retries for loading and decoding the md file header
* and index
*/
- if(load_retries == 0)
-
+ if (!do_try) {
HGOTO_ERROR(H5E_VFL, H5E_CANTLOAD, FAIL, \
"error in loading/decoding the metadata file header and index")
+ }
done:
@@ -1586,12 +1583,10 @@ H5FD_vfd_swmr_get_tick_and_idx(H5FD_t *_file, hbool_t reload_hdr_and_index,
FUNC_ENTER_NOAPI(FAIL)
/* Load and decode the header and index as indicated */
- if(reload_hdr_and_index) {
-
- if(H5FD__vfd_swmr_load_hdr_and_idx(_file, FALSE) < 0)
-
- HGOTO_ERROR(H5E_VFL, H5E_CANTLOAD, FAIL, \
- "unable to load/decode md header and index")
+ if (reload_hdr_and_index &&
+ H5FD__vfd_swmr_load_hdr_and_idx(_file, FALSE) < 0) {
+ HGOTO_ERROR(H5E_VFL, H5E_CANTLOAD, FAIL,
+ "unable to load/decode md header and index")
}
/* Return tick_num */
diff --git a/src/H5FDvfd_swmr_private.h b/src/H5FDvfd_swmr_private.h
index 5d1afdb..c12239c 100644
--- a/src/H5FDvfd_swmr_private.h
+++ b/src/H5FDvfd_swmr_private.h
@@ -12,11 +12,9 @@
#ifndef _H5FDvfd_swmr_private_H
#define _H5FDvfd_swmr_private_H
-#define SECOND_TO_NANOSECS 1000000000 /* Second to nanoseconds */
-#define TENTH_SEC_TO_NANOSECS 100000000 /* 0.1 second to nanoseconds */
-
/* Forward declaration */
struct H5F_t;
+struct H5F_shared_t;
struct H5FD_vfd_swmr_idx_entry_t;
/*
@@ -75,10 +73,10 @@ extern H5F_vfd_swmr_eot_queue_entry_t *vfd_swmr_eot_queue_tail_g;
H5_DLL herr_t H5F_vfd_swmr_init(struct H5F_t *f, hbool_t file_create);
H5_DLL herr_t H5F_vfd_swmr_close_or_flush(struct H5F_t *f, hbool_t closing);
-H5_DLL herr_t H5F_update_vfd_swmr_metadata_file(struct H5F_t *f, uint32_t index_len,
- struct H5FD_vfd_swmr_idx_entry_t *index);
-H5_DLL herr_t H5F_vfd_swmr_writer__delay_write(struct H5F_t *f, uint64_t page,
- uint64_t *delay_write_until_ptr);
+H5_DLL herr_t H5F_update_vfd_swmr_metadata_file(struct H5F_t *f,
+ uint32_t index_len, struct H5FD_vfd_swmr_idx_entry_t *index);
+H5_DLL herr_t H5F_vfd_swmr_writer__delay_write(struct H5F_shared_t *, uint64_t,
+ uint64_t *);
H5_DLL herr_t H5F_vfd_swmr_writer__prep_for_flush_or_close(struct H5F_t *f);
H5_DLL herr_t H5F_vfd_swmr_writer_end_of_tick(struct H5F_t *f);
H5_DLL herr_t H5F_vfd_swmr_writer__dump_index(struct H5F_t * f);
diff --git a/src/H5FL.c b/src/H5FL.c
index 89a580a..9ed867d 100644
--- a/src/H5FL.c
+++ b/src/H5FL.c
@@ -642,7 +642,7 @@ H5FL__reg_term(void)
tmp = H5FL_reg_gc_head.first->next;
#ifdef H5FL_DEBUG
-printf("%s: head->name = %s, head->allocated = %d\n", FUNC, H5FL_reg_gc_head.first->list->name, (int)H5FL_reg_gc_head.first->list->allocated);
+HDprintf("%s: head->name = %s, head->allocated = %d\n", FUNC, H5FL_reg_gc_head.first->list->name, (int)H5FL_reg_gc_head.first->list->allocated);
#endif /* H5FL_DEBUG */
/* Check if the list has allocations outstanding */
if(H5FL_reg_gc_head.first->list->allocated > 0) {
@@ -1055,7 +1055,7 @@ H5FL_blk_free(H5FL_blk_head_t *head, void *block)
#endif /* H5FL_TRACK */
/* Get the pointer to the native block info header in front of the native block to free */
- temp=(H5FL_blk_list_t *)((unsigned char *)block-sizeof(H5FL_blk_list_t)); /*lint !e826 Pointer-to-pointer cast is appropriate here */
+ temp = (H5FL_blk_list_t *)((void *)((unsigned char *)block - sizeof(H5FL_blk_list_t))); /*lint !e826 Pointer-to-pointer cast is appropriate here */
/* Save the block's size for later */
free_size=temp->size;
@@ -1133,7 +1133,7 @@ H5FL_blk_realloc(H5FL_blk_head_t *head, void *block, size_t new_size H5FL_TRACK_
H5FL_blk_list_t *temp; /* Temp. ptr to the new block node allocated */
/* Get the pointer to the chunk info header in front of the chunk to free */
- temp=(H5FL_blk_list_t *)((unsigned char *)block - (sizeof(H5FL_blk_list_t) + H5FL_TRACK_SIZE)); /*lint !e826 Pointer-to-pointer cast is appropriate here */
+ temp = (H5FL_blk_list_t *)((void *)((unsigned char *)block - (sizeof(H5FL_blk_list_t) + H5FL_TRACK_SIZE))); /*lint !e826 Pointer-to-pointer cast is appropriate here */
/* check if we are actually changing the size of the buffer */
if(new_size!=temp->size) {
@@ -1142,7 +1142,7 @@ H5FL_blk_realloc(H5FL_blk_head_t *head, void *block, size_t new_size H5FL_TRACK_
if((ret_value=H5FL_blk_malloc(head,new_size H5FL_TRACK_INFO_INT))==NULL)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for block")
blk_size=MIN(new_size,temp->size);
- HDmemcpy(ret_value,block,blk_size);
+ H5MM_memcpy(ret_value,block,blk_size);
H5FL_blk_free(head,block);
} /* end if */
else {
@@ -1312,7 +1312,7 @@ H5FL__blk_term(void)
tmp = H5FL_blk_gc_head.first->next;
#ifdef H5FL_DEBUG
-printf("%s: head->name = %s, head->allocated = %d\n", FUNC, H5FL_blk_gc_head.first->pq->name, (int)H5FL_blk_gc_head.first->pq->allocated);
+HDprintf("%s: head->name = %s, head->allocated = %d\n", FUNC, H5FL_blk_gc_head.first->pq->name, (int)H5FL_blk_gc_head.first->pq->allocated);
#endif /* H5FL_DEBUG */
/* Check if the list has allocations outstanding */
@@ -1430,7 +1430,7 @@ H5FL_arr_free(H5FL_arr_head_t *head, void *obj)
HDassert(head->init);
/* Get the pointer to the info header in front of the block to free */
- temp=(H5FL_arr_list_t *)((unsigned char *)obj-sizeof(H5FL_arr_list_t)); /*lint !e826 Pointer-to-pointer cast is appropriate here */
+ temp = (H5FL_arr_list_t *)((void *)((unsigned char *)obj - sizeof(H5FL_arr_list_t))); /*lint !e826 Pointer-to-pointer cast is appropriate here */
/* Get the number of elements */
free_nelem=temp->nelem;
@@ -1619,7 +1619,7 @@ H5FL_arr_realloc(H5FL_arr_head_t *head, void * obj, size_t new_elem)
HDassert((int)new_elem <= head->maxelem);
/* Get the pointer to the info header in front of the block to free */
- temp = (H5FL_arr_list_t *)((unsigned char *)obj - sizeof(H5FL_arr_list_t)); /*lint !e826 Pointer-to-pointer cast is appropriate here */
+ temp = (H5FL_arr_list_t *)((void *)((unsigned char *)obj - sizeof(H5FL_arr_list_t))); /*lint !e826 Pointer-to-pointer cast is appropriate here */
/* Check if the size is really changing */
if(temp->nelem != new_elem) {
@@ -1630,7 +1630,7 @@ H5FL_arr_realloc(H5FL_arr_head_t *head, void * obj, size_t new_elem)
/* Copy the appropriate amount of elements */
blk_size = head->list_arr[MIN(temp->nelem, new_elem)].size;
- HDmemcpy(ret_value, obj, blk_size);
+ H5MM_memcpy(ret_value, obj, blk_size);
/* Free the old block */
H5FL_arr_free(head, obj);
@@ -1780,7 +1780,7 @@ H5FL__arr_term(void)
/* Check if the list has allocations outstanding */
#ifdef H5FL_DEBUG
-printf("%s: head->name = %s, head->allocated = %d\n", FUNC, H5FL_arr_gc_head.first->list->name, (int)H5FL_arr_gc_head.first->list->allocated);
+HDprintf("%s: head->name = %s, head->allocated = %d\n", FUNC, H5FL_arr_gc_head.first->list->name, (int)H5FL_arr_gc_head.first->list->allocated);
#endif /* H5FL_DEBUG */
if(H5FL_arr_gc_head.first->list->allocated > 0) {
/* Add free list to the list of nodes with allocations open still */
@@ -2408,7 +2408,7 @@ H5FL__fac_term_all(void)
tmp = H5FL_fac_gc_head.first->next;
#ifdef H5FL_DEBUG
-printf("%s: head->size = %d, head->allocated = %d\n", FUNC, (int)H5FL_fac_gc_head.first->list->size, (int)H5FL_fac_gc_head.first->list->allocated);
+HDprintf("%s: head->size = %d, head->allocated = %d\n", FUNC, (int)H5FL_fac_gc_head.first->list->size, (int)H5FL_fac_gc_head.first->list->allocated);
#endif /* H5FL_DEBUG */
/* The list cannot have any allocations outstanding */
diff --git a/src/H5FLprivate.h b/src/H5FLprivate.h
index 4aa44f9..d5a68d7 100644
--- a/src/H5FLprivate.h
+++ b/src/H5FLprivate.h
@@ -189,10 +189,10 @@ typedef struct H5FL_blk_head_t {
/* Declare a static free list to manage objects of type 't' */
#define H5FL_BLK_DEFINE_STATIC(t) static H5FL_BLK_DEFINE_COMMON(t)
-/* Allocate an block of type 't' */
+/* Allocate a block of type 't' */
#define H5FL_BLK_MALLOC(t,size) (uint8_t *)H5FL_blk_malloc(&(H5FL_BLK_NAME(t)),size H5FL_TRACK_INFO)
-/* Allocate an block of type 't' and clear it to zeros */
+/* Allocate a block of type 't' and clear it to zeros */
#define H5FL_BLK_CALLOC(t,size) (uint8_t *)H5FL_blk_calloc(&(H5FL_BLK_NAME(t)),size H5FL_TRACK_INFO)
/* Free a block of type 't' */
diff --git a/src/H5FS.c b/src/H5FS.c
index 8fee634..dbcb6b5 100644
--- a/src/H5FS.c
+++ b/src/H5FS.c
@@ -36,6 +36,7 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5FSpkg.h" /* File free space */
#include "H5MFprivate.h" /* File memory management */
+#include "H5MMprivate.h" /* Memory management */
/****************/
@@ -615,7 +616,7 @@ H5FS__new(const H5F_t *f, uint16_t nclasses, const H5FS_section_class_t *classes
HDassert(u == classes[u]->type);
/* Copy the class information into the free space manager */
- HDmemcpy(&fspace->sect_cls[u], classes[u], sizeof(H5FS_section_class_t));
+ H5MM_memcpy(&fspace->sect_cls[u], classes[u], sizeof(H5FS_section_class_t));
/* Call the class initialization routine, if there is one */
if(fspace->sect_cls[u].init_cls)
diff --git a/src/H5FScache.c b/src/H5FScache.c
index b40ac79..aa21cd2 100644
--- a/src/H5FScache.c
+++ b/src/H5FScache.c
@@ -38,6 +38,7 @@
#include "H5Fprivate.h" /* File */
#include "H5FSpkg.h" /* File free space */
#include "H5MFprivate.h" /* File memory management */
+#include "H5MMprivate.h" /* Memory management */
#include "H5VMprivate.h" /* Vectors and arrays */
#include "H5WBprivate.h" /* Wrapped Buffers */
@@ -518,14 +519,36 @@ H5FS__cache_hdr_pre_serialize(H5F_t *f, void *_thing,
if(!H5F_addr_defined(fspace->sect_addr)) { /* case 1 */
haddr_t tag = HADDR_UNDEF;
+ haddr_t sect_addr;
+ hsize_t saved_sect_size, new_sect_size;
/* allocate file space for the section info, and insert it
* into the metadata cache.
*/
- if(HADDR_UNDEF == (fspace->sect_addr = H5MF_alloc((H5F_t *)f, H5FD_MEM_FSPACE_SINFO, fspace->sect_size)))
+ saved_sect_size = fspace->sect_size;
+ if(HADDR_UNDEF == (sect_addr = H5MF_alloc((H5F_t *)f, H5FD_MEM_FSPACE_SINFO, fspace->sect_size)))
HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections")
- fspace->alloc_sect_size = (size_t)fspace->sect_size;
+ /* fspace->sect_size may change in size after H5MF_alloc().
+ * If increased in size, free the previous allocation and
+ * allocate again with the bigger fspace->sect_size.
+ */
+ if(fspace->sect_size > saved_sect_size) {
+
+ new_sect_size = fspace->sect_size;
+
+ if(H5MF_xfree(f, H5FD_MEM_FSPACE_SINFO, sect_addr, saved_sect_size) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to free free space sections")
+
+ if(HADDR_UNDEF == (sect_addr = H5MF_alloc((H5F_t *)f, H5FD_MEM_FSPACE_SINFO, new_sect_size)))
+ HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections")
+ fspace->sect_size = new_sect_size;
+ fspace->alloc_sect_size = new_sect_size;
+ } else {
+ fspace->alloc_sect_size = saved_sect_size;
+ fspace->sect_size = saved_sect_size;
+ }
+ fspace->sect_addr = sect_addr;
/* Get the tag for this free space manager and use it to insert the entry */
if(H5AC_get_tag((const void *)fspace, &tag) < 0)
@@ -594,7 +617,6 @@ H5FS__cache_hdr_pre_serialize(H5F_t *f, void *_thing,
* a nonsense section info address.
*/
if(!H5F_POINT_OF_NO_RETURN(f)) {
- HDassert(fspace->serial_sect_count > 0);
HDassert(fspace->sect_size > 0);
HDassert(fspace->alloc_sect_size == (size_t)fspace->sect_size);
} /* end if */
@@ -704,12 +726,11 @@ H5FS__cache_hdr_serialize(const H5F_t *f, void *_image, size_t len,
if(!H5F_POINT_OF_NO_RETURN(f))
HDassert((! H5F_addr_defined(fspace->sect_addr)) ||
- ((fspace->serial_sect_count > 0) &&
- (fspace->sect_size > 0) &&
- (fspace->alloc_sect_size == (size_t)fspace->sect_size)));
+ ((fspace->sect_size > 0) &&
+ (fspace->alloc_sect_size == (size_t)fspace->sect_size)));
/* Magic number */
- HDmemcpy(image, H5FS_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ H5MM_memcpy(image, H5FS_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
image += H5_SIZEOF_MAGIC;
/* Version # */
@@ -969,6 +990,7 @@ H5FS__cache_sinfo_deserialize(const void *_image, size_t len, void *_udata,
haddr_t fs_addr; /* Free space header address */
size_t old_sect_size; /* Old section size */
const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ const uint8_t *chksum_image; /* Points to chksum location */
uint32_t stored_chksum; /* Stored metadata checksum */
void * ret_value = NULL; /* Return value */
@@ -1065,10 +1087,14 @@ H5FS__cache_sinfo_deserialize(const void *_image, size_t len, void *_udata,
if(H5FS_sect_add(udata->f, fspace, new_sect, H5FS_ADD_DESERIALIZING, udata) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, NULL, "can't add section to free space manager")
} /* end for */
+
+ if(fspace->tot_sect_count == old_tot_sect_count)
+ break;
+
} while(image < (((const uint8_t *)_image + old_sect_size) - H5FS_SIZEOF_CHKSUM));
/* Sanity check */
- HDassert((size_t)(image - (const uint8_t *)_image) == (old_sect_size - H5FS_SIZEOF_CHKSUM));
+ HDassert((size_t)(image - (const uint8_t *)_image) <= (old_sect_size - H5FS_SIZEOF_CHKSUM));
HDassert(old_sect_size == fspace->sect_size);
HDassert(old_tot_sect_count == fspace->tot_sect_count);
HDassert(old_serial_sect_count == fspace->serial_sect_count);
@@ -1078,11 +1104,14 @@ H5FS__cache_sinfo_deserialize(const void *_image, size_t len, void *_udata,
/* checksum verification already done in verify_chksum cb */
+ /* There may be empty space between entries and chksum */
+ chksum_image = (const uint8_t *)(_image) + old_sect_size - H5FS_SIZEOF_CHKSUM;
/* Metadata checksum */
- UINT32DECODE(image, stored_chksum);
+ UINT32DECODE(chksum_image, stored_chksum);
/* Sanity check */
- HDassert((size_t)(image - (const uint8_t *)_image) == old_sect_size);
+ HDassert((image == chksum_image) ||
+ ((size_t)((image - (const uint8_t *)_image) + (chksum_image - image)) == old_sect_size));
/* Set return value */
ret_value = sinfo;
@@ -1178,10 +1207,6 @@ H5FS__cache_sinfo_pre_serialize(H5F_t *f, void *_thing, haddr_t addr,
HDassert(new_len);
HDassert(flags);
- /* we shouldn't be called if the section info is empty, unless we hit the point of no return. */
- if(!H5F_POINT_OF_NO_RETURN(f))
- HDassert(fspace->serial_sect_count > 0);
-
sinfo_addr = addr; /* this will change if we relocate the section data */
/* Check for section info at temporary address */
@@ -1247,6 +1272,7 @@ H5FS__cache_sinfo_serialize(const H5F_t *f, void *_image, size_t len,
H5FS_t *fspace; /* Free space header */
H5FS_iter_ud_t udata; /* User data for callbacks */
uint8_t *image = (uint8_t *)_image; /* Pointer into raw data buffer */
+ uint8_t *chksum_image = NULL; /* Points to chksum location */
uint32_t metadata_chksum; /* Computed metadata checksum value */
unsigned bin; /* Current bin we are on */
herr_t ret_value = SUCCEED; /* Return value */
@@ -1267,7 +1293,7 @@ H5FS__cache_sinfo_serialize(const H5F_t *f, void *_image, size_t len,
HDassert(fspace->sect_cls);
/* Magic number */
- HDmemcpy(image, H5FS_SINFO_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ H5MM_memcpy(image, H5FS_SINFO_MAGIC, (size_t)H5_SIZEOF_MAGIC);
image += H5_SIZEOF_MAGIC;
/* Version # */
@@ -1291,13 +1317,16 @@ H5FS__cache_sinfo_serialize(const H5F_t *f, void *_image, size_t len,
/* Compute checksum */
- metadata_chksum = H5_checksum_metadata(_image, (size_t)(image - (uint8_t *)_image), 0);
+ /* There may be empty space between entries and chksum */
+ chksum_image = (uint8_t *)(_image) + len - H5FS_SIZEOF_CHKSUM;
+ metadata_chksum = H5_checksum_metadata(_image, (size_t)(chksum_image - (uint8_t *)_image), 0);
/* Metadata checksum */
- UINT32ENCODE(image, metadata_chksum);
+ UINT32ENCODE(chksum_image, metadata_chksum);
/* Sanity check */
- HDassert((size_t)(image - (uint8_t *)_image) == sinfo->fspace->sect_size);
+ HDassert((chksum_image == image) ||
+ ((size_t)((image - (uint8_t *)_image) + (chksum_image - image)) == sinfo->fspace->sect_size));
HDassert(sinfo->fspace->sect_size <= sinfo->fspace->alloc_sect_size);
done:
diff --git a/src/H5FSprivate.h b/src/H5FSprivate.h
index 374576e..3757472 100644
--- a/src/H5FSprivate.h
+++ b/src/H5FSprivate.h
@@ -25,9 +25,6 @@
#ifndef _H5FSprivate_H
#define _H5FSprivate_H
-/* Include package's public header */
-#include "H5FSpublic.h"
-
/* Private headers needed by this file */
#include "H5Fprivate.h" /* File access */
#include "H5FLprivate.h" /* Free Lists */
diff --git a/src/H5FSsection.c b/src/H5FSsection.c
index 9fbc6f0..64393e3 100644
--- a/src/H5FSsection.c
+++ b/src/H5FSsection.c
@@ -307,6 +307,20 @@ HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu, fspace->sect_size = %Hu\n"
* Purpose: Release the section info, either giving ownership back to
* the cache or letting the free space header keep it.
*
+ * Add the fix in this routine to resolve the potential infinite loop
+ * problem when allocating file space for the meta data of the
+ * self-referential free-space managers at file closing.
+ *
+ * On file close or flushing, when the section info is modified
+ * and protected/unprotected, does not allow the section info size
+ * to shrink:
+ * --if the current allocated section info size in fspace->sect_size is
+ * larger than the previous section info size in fpsace->alloc_sect_size,
+ * release the section info
+ * --Otherwise, set the fspace->sect_size to be the same as
+ * fpsace->alloc_sect_size. This means fspace->sect_size may be larger
+ * than what is actually needed.
+ *
* Return: SUCCEED/FAIL
*
* Programmer: Quincey Koziol
@@ -357,6 +371,17 @@ HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu, fspace->sect_size = %Hu\n"
/* Check if section info lock count dropped to zero */
if(fspace->sinfo_lock_count == 0) {
hbool_t release_sinfo_space = FALSE; /* Flag to indicate section info space in file should be released */
+ hbool_t closing_or_flushing = f->shared->closing;
+
+ /* There is no need to check whether cache-flush is in progress if
+ * we already found that either closing is in progress. Furthermore,
+ * if closing *is* in progress, then the cache may have been destroyed,
+ * already. Calling H5AC_get_cache_flush_in_progress() on a destroyed
+ * cache *may* cause a crash, but it will definitely make us bail
+ * out of this routine with an error.
+ */
+ if(!closing_or_flushing && H5AC_get_cache_flush_in_progress(f->shared->cache, &closing_or_flushing) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't get flush_in_progress")
/* Check if we actually protected the section info */
if(fspace->sinfo_protected) {
@@ -370,9 +395,17 @@ HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu, fspace->sect_size = %Hu\n"
/* Note that we've modified the section info */
cache_flags |= H5AC__DIRTIED_FLAG;
+ /* On file close or flushing, does not allow section info to shrink in size */
+ if(closing_or_flushing) {
+ if(fspace->sect_size > fspace->alloc_sect_size)
+ cache_flags |= H5AC__DELETED_FLAG | H5AC__TAKE_OWNERSHIP_FLAG;
+ else
+ fspace->sect_size = fspace->alloc_sect_size;
+
/* Check if the section info size in the file has changed */
- if(fspace->sect_size != fspace->alloc_sect_size)
+ } else if(fspace->sect_size != fspace->alloc_sect_size)
cache_flags |= H5AC__DELETED_FLAG | H5AC__TAKE_OWNERSHIP_FLAG;
+
} /* end if */
/* Sanity check */
@@ -410,11 +443,20 @@ HDfprintf(stderr, "%s: Relinquishing section info ownership\n", FUNC);
/* Check if the section info was modified */
if(fspace->sinfo_modified) {
/* Check if we need to release section info in the file */
- if(H5F_addr_defined(fspace->sect_addr))
+ if(H5F_addr_defined(fspace->sect_addr)) {
/* Set flag to release section info space in file */
- release_sinfo_space = TRUE;
- else
+ /* On file close or flushing, only need to release section info with size
+ bigger than previous section */
+ if(closing_or_flushing) {
+ if(fspace->sect_size > fspace->alloc_sect_size)
+ release_sinfo_space = TRUE;
+ else
+ fspace->sect_size = fspace->alloc_sect_size;
+ } else
+ release_sinfo_space = TRUE;
+ } else
HDassert(fspace->alloc_sect_size == 0);
+
} /* end if */
else {
/* Sanity checks... */
@@ -2414,84 +2456,31 @@ done:
/*-------------------------------------------------------------------------
* Function: H5FS_vfd_alloc_hdr_and_section_info_if_needed
*
- * Purpose: This function is part of a hack to patch over a design
- * flaw in the free space managers for file space allocation.
- * Specifically, if a free space manager allocates space for
- * its own section info, it is possible for it to
- * go into an infinite loop as it:
- *
- * 1) computes the size of the section info
- *
- * 2) allocates file space for the section info
- *
- * 3) notices that the size of the section info
- * has changed
- *
- * 4) deallocates the section info file space and
- * returns to 1) above.
- *
- * Similarly, if it allocates space for its own header, it
- * can go into an infinite loop as it:
- *
- * 1) allocates space for the header
- *
- * 2) notices that the free space manager is empty
- * and thus should not have file space allocated
- * to its header
- *
- * 3) frees the space allocated to the header
- *
- * 4) notices that the free space manager is not
- * empty and thus must have file space allocated
- * to it, and thus returns to 1) above.
- *
- * In a nutshell, the solution applied in this hack is to
- * deallocate file space for the free space manager(s) that
- * handle FSM header and/or section info file space allocations,
- * wait until all other allocation/deallocation requests have
- * been handled, and then test to see if the free space manager(s)
- * in question are empty. If they are, do nothing. If they
- * are not, allocate space for them at end of file bypassing the
- * usual file space allocation calls, and thus avoiding the
- * potential infinite loops.
- *
- * The purpose of this function is to allocate file space for
+ * Purpose: The purpose of this function is to allocate file space for
* the header and section info of the target free space manager
- * directly from the VFD if needed. In this case the function
- * also re-inserts the header and section info in the metadata
- * cache with this allocation.
- *
- * When paged allocation is not enabled, allocation of space
- * for the free space manager header and section info is
- * straight forward -- we simply allocate the space directly
- * from file driver.
- *
- * Note that if f->shared->alignment > 1, and EOA is not a
- * multiple of the alignment, it is possible that performing
- * these allocations may generate a fragment of file space in
- * addition to the space allocated for the section info. This
- * excess space is dropped on the floor. As shall be seen,
- * it will usually be reclaimed later.
- *
- * When page allocation is enabled, things are more difficult,
- * as there is the possibility that page buffering will be
- * enabled when the free space managers are read. To allow
- * for this, we must ensure that space allocated for the
- * free space manager header and section info is either larger
- * than a page, or resides completely within a page.
- *
- * Do this by allocating space for the free space header and
- * section info starting at page boundaries, and extending
- * allocation to the next page boundary. This of course wastes
- * space, but see below.
- *
- * On the first free space allocation / deallocation after the
- * next file open, we will read the self referential free space
- * managers, float them and reduce the EOA to its value prior
- * to allocation of file space for the self referential free
- * space managers on the preceeding file close. This EOA value
- * is stored in the free space manager superblock extension
- * message.
+ * if they are not allocated yet.
+ *
+ * The previous hack in this routine to avoid the potential infinite
+ * loops by allocating file space directly from the end of the file
+ * is removed. The allocation can now be done via the usual
+ * file space allocation call H5MF_alloc().
+ *
+ * The design flaw is addressed by not allowing the size
+ * of section info to shrink. This means, when trying to allocate
+ * section info size X via H5MF_alloc() and the section info size
+ * after H5MF_alloc() changes to Y:
+ * --if Y is larger than X, free the just allocated file space X
+ * via H5MF_xfree() and set fspace->sect_size to Y.
+ * This routine will be called again later from
+ * H5MF_settle_meta_data_fsm() to allocate section info with the
+ * larger fpsace->sect_size Y.
+ * --if Y is smaller than X, no further allocation is needed and
+ * fspace->sect_size and fspace->alloc_sect_size are set to X.
+ * This means fspace->sect_size may be larger than what is
+ * actually needed.
+ *
+ * This routine also re-inserts the header and section info in the
+ * metadata cache with this allocation.
*
* Return: Success: non-negative
* Failure: negative
@@ -2508,8 +2497,6 @@ H5FS_vfd_alloc_hdr_and_section_info_if_needed(H5F_t *f, H5FS_t *fspace,
hsize_t hdr_alloc_size;
hsize_t sinfo_alloc_size;
haddr_t sect_addr = HADDR_UNDEF; /* address of sinfo */
- haddr_t eoa_frag_addr = HADDR_UNDEF; /* Address of fragment at EOA */
- hsize_t eoa_frag_size = 0; /* Size of fragment at EOA */
haddr_t eoa = HADDR_UNDEF; /* Initial EOA for the file */
herr_t ret_value = SUCCEED; /* Return value */
@@ -2525,12 +2512,6 @@ H5FS_vfd_alloc_hdr_and_section_info_if_needed(H5F_t *f, H5FS_t *fspace,
/* the section info should be unlocked */
HDassert(fspace->sinfo_lock_count == 0);
- /* no space should be allocated */
- HDassert(*fs_addr_ptr == HADDR_UNDEF);
- HDassert(fspace->addr == HADDR_UNDEF);
- HDassert(fspace->sect_addr == HADDR_UNDEF);
- HDassert(fspace->alloc_sect_size == 0);
-
/* persistent free space managers must be enabled */
HDassert(f->shared->fs_persist);
@@ -2542,125 +2523,109 @@ H5FS_vfd_alloc_hdr_and_section_info_if_needed(H5F_t *f, H5FS_t *fspace,
HDassert((f->shared->fs_strategy == H5F_FSPACE_STRATEGY_FSM_AGGR) ||
(f->shared->fs_strategy == H5F_FSPACE_STRATEGY_PAGE));
- if(fspace->serial_sect_count > 0) {
+ if(fspace->serial_sect_count > 0 && fspace->sinfo) {
/* the section info is floating, so space->sinfo should be defined */
- HDassert(fspace->sinfo);
-
- /* start by allocating file space for the header */
-
- /* Get the EOA for the file -- need for sanity check below */
- if(HADDR_UNDEF == (eoa = H5F_get_eoa(f, H5FD_MEM_FSPACE_HDR)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "Unable to get eoa")
- /* check for overlap into temporary allocation space */
- if(H5F_IS_TMP_ADDR(f, (eoa + fspace->sect_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_BADRANGE, FAIL, "hdr file space alloc will overlap into 'temporary' file space")
+ if(!H5F_addr_defined(fspace->addr)) {
- hdr_alloc_size = H5FS_HEADER_SIZE(f);
-
- /* if page allocation is enabled, extend the hdr_alloc_size to the
- * next page boundary.
- */
- if(H5F_PAGED_AGGR(f)) {
- HDassert(0 == (eoa % f->shared->fs_page_size));
+ /* start by allocating file space for the header */
- hdr_alloc_size = ((hdr_alloc_size / f->shared->fs_page_size) + 1) * f->shared->fs_page_size;
+ /* Get the EOA for the file -- need for sanity check below */
+ if(HADDR_UNDEF == (eoa = H5F_get_eoa(f, H5FD_MEM_FSPACE_HDR)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "Unable to get eoa")
- HDassert(hdr_alloc_size >= H5FS_HEADER_SIZE(f));
- HDassert((hdr_alloc_size % f->shared->fs_page_size) == 0);
- } /* end if */
+ /* check for overlap into temporary allocation space */
+ if(H5F_IS_TMP_ADDR(f, (eoa + fspace->sect_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_BADRANGE, FAIL, "hdr file space alloc will overlap into 'temporary' file space")
- /* allocate space for the hdr */
- if(HADDR_UNDEF == (fspace->addr = H5FD_alloc(f->shared->lf, H5FD_MEM_FSPACE_HDR,
- f, hdr_alloc_size, &eoa_frag_addr, &eoa_frag_size)))
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTALLOC, FAIL, "can't allocate file space for hdr")
+ hdr_alloc_size = H5FS_HEADER_SIZE(f);
- /* if the file alignment is 1, there should be no
- * eoa fragment. Otherwise, drop any fragment on the floor.
- */
- HDassert((eoa_frag_size == 0) || (f->shared->alignment != 1));
+ if(H5F_PAGED_AGGR(f))
+ HDassert(0 == (eoa % f->shared->fs_page_size));
- /* Cache the new free space header (pinned) */
- if(H5AC_insert_entry(f, H5AC_FSPACE_HDR, fspace->addr, fspace, H5AC__PIN_ENTRY_FLAG) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTINIT, FAIL, "can't add free space header to cache")
+ /* Allocate space for the free space header */
+ if(HADDR_UNDEF == (fspace->addr = H5MF_alloc(f, H5FD_MEM_FSPACE_HDR, hdr_alloc_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for free space header")
- *fs_addr_ptr = fspace->addr;
+ /* Cache the new free space header (pinned) */
+ if(H5AC_insert_entry(f, H5AC_FSPACE_HDR, fspace->addr, fspace, H5AC__PIN_ENTRY_FLAG) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTINIT, FAIL, "can't add free space header to cache")
- /* now allocate file space for the section info */
+ *fs_addr_ptr = fspace->addr;
+ }
- /* Get the EOA for the file -- need for sanity check below */
- if(HADDR_UNDEF == (eoa = H5F_get_eoa(f, H5FD_MEM_FSPACE_SINFO)))
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "Unable to get eoa")
+ if(!H5F_addr_defined(fspace->sect_addr)) {
- /* check for overlap into temporary allocation space */
- if(H5F_IS_TMP_ADDR(f, (eoa + fspace->sect_size)))
- HGOTO_ERROR(H5E_FSPACE, H5E_BADRANGE, FAIL, "sinfo file space alloc will overlap into 'temporary' file space")
+ /* now allocate file space for the section info */
- sinfo_alloc_size = fspace->sect_size;
+ /* Get the EOA for the file -- need for sanity check below */
+ if(HADDR_UNDEF == (eoa = H5F_get_eoa(f, H5FD_MEM_FSPACE_SINFO)))
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "Unable to get eoa")
- /* if paged allocation is enabled, extend the sinfo_alloc_size to the
- * next page boundary.
- */
- if(H5F_PAGED_AGGR(f)) {
- HDassert(0 == (eoa % f->shared->fs_page_size));
+ /* check for overlap into temporary allocation space */
+ if(H5F_IS_TMP_ADDR(f, (eoa + fspace->sect_size)))
+ HGOTO_ERROR(H5E_FSPACE, H5E_BADRANGE, FAIL, "sinfo file space alloc will overlap into 'temporary' file space")
- sinfo_alloc_size = ((sinfo_alloc_size / f->shared->fs_page_size) + 1) * f->shared->fs_page_size;
+ sinfo_alloc_size = fspace->sect_size;
- HDassert(sinfo_alloc_size >= fspace->sect_size);
- HDassert((sinfo_alloc_size % f->shared->fs_page_size) == 0);
- } /* end if */
+ if(H5F_PAGED_AGGR(f))
+ HDassert(0 == (eoa % f->shared->fs_page_size));
- /* allocate space for the section info */
- if(HADDR_UNDEF == (sect_addr = H5FD_alloc(f->shared->lf, H5FD_MEM_FSPACE_SINFO,
- f, sinfo_alloc_size, &eoa_frag_addr, &eoa_frag_size)))
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTALLOC, FAIL, "can't allocate file space")
+ /* allocate space for the section info */
+ if(HADDR_UNDEF == (sect_addr = H5MF_alloc(f, H5FD_MEM_FSPACE_SINFO, sinfo_alloc_size)))
+ HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for section info")
- /* if the file alignment is 1, there should be no
- * eoa fragment. Otherwise, drop the fragment on the floor.
- */
- HDassert((eoa_frag_size == 0) || (f->shared->alignment != 1));
+ /* update fspace->alloc_sect_size and fspace->sect_addr to reflect
+ * the allocation
+ */
+ if(fspace->sect_size > sinfo_alloc_size) {
+ hsize_t saved_sect_size = fspace->sect_size;
- /* update fspace->alloc_sect_size and fspace->sect_addr to reflect
- * the allocation
- */
- fspace->alloc_sect_size = fspace->sect_size;
- fspace->sect_addr = sect_addr;
-
- /* insert the new section info into the metadata cache. */
-
- /* Question: Do we need to worry about this insertion causing an
- * eviction from the metadata cache? Think on this. If so, add a
- * flag to H5AC_insert() to force it to skip the call to make space in
- * cache.
- *
- * On reflection, no.
- *
- * On a regular file close, any eviction will not change the
- * the contents of the free space manager(s), as all entries
- * should have correct file space allocated by the time this
- * function is called.
- *
- * In the cache image case, the selection of entries for inclusion
- * in the cache image will not take place until after this call.
- * (Recall that this call is made during the metadata fsm settle
- * routine, which is called during the serialization routine in
- * the cache image case. Entries are not selected for inclusion
- * in the image until after the cache is serialized.)
- *
- * JRM -- 11/4/16
- */
- if(H5AC_insert_entry(f, H5AC_FSPACE_SINFO, sect_addr, fspace->sinfo, H5AC__NO_FLAGS_SET) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTINIT, FAIL, "can't add free space sinfo to cache")
+ if(H5MF_xfree(f, H5FD_MEM_FSPACE_SINFO, sect_addr, sinfo_alloc_size) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to free free space sections")
+ fspace->sect_size = saved_sect_size;
+ } else {
+ fspace->alloc_sect_size = sinfo_alloc_size;
+ fspace->sect_size = sinfo_alloc_size;
+ fspace->sect_addr = sect_addr;
+
+ /* insert the new section info into the metadata cache. */
+
+ /* Question: Do we need to worry about this insertion causing an
+ * eviction from the metadata cache? Think on this. If so, add a
+ * flag to H5AC_insert() to force it to skip the call to make space in
+ * cache.
+ *
+ * On reflection, no.
+ *
+ * On a regular file close, any eviction will not change the
+ * the contents of the free space manager(s), as all entries
+ * should have correct file space allocated by the time this
+ * function is called.
+ *
+ * In the cache image case, the selection of entries for inclusion
+ * in the cache image will not take place until after this call.
+ * (Recall that this call is made during the metadata fsm settle
+ * routine, which is called during the serialization routine in
+ * the cache image case. Entries are not selected for inclusion
+ * in the image until after the cache is serialized.)
+ *
+ * JRM -- 11/4/16
+ */
+ if(H5AC_insert_entry(f, H5AC_FSPACE_SINFO, sect_addr, fspace->sinfo, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTINIT, FAIL, "can't add free space sinfo to cache")
- /* We have changed the sinfo address -- Mark free space header dirty */
- if(H5AC_mark_entry_dirty(fspace) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty")
+ /* We have changed the sinfo address -- Mark free space header dirty */
+ if(H5AC_mark_entry_dirty(fspace) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty")
- /* since space has been allocated for the section info and the sinfo
- * has been inserted into the cache, relinquish ownership (i.e. float)
- * the section info.
- */
- fspace->sinfo = NULL;
+ /* since space has been allocated for the section info and the sinfo
+ * has been inserted into the cache, relinquish ownership (i.e. float)
+ * the section info.
+ */
+ fspace->sinfo = NULL;
+ }
+ }
} /* end if */
done:
diff --git a/src/H5Faccum.c b/src/H5Faccum.c
index 0b33f8e..74a170b 100644
--- a/src/H5Faccum.c
+++ b/src/H5Faccum.c
@@ -38,6 +38,7 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5Fpkg.h" /* File access */
#include "H5FDprivate.h" /* File drivers */
+#include "H5MMprivate.h" /* Memory management */
#include "H5VMprivate.h" /* Vectors and arrays */
@@ -110,7 +111,7 @@ H5FL_BLK_DEFINE_STATIC(meta_accum);
*-------------------------------------------------------------------------
*/
herr_t
-H5F__accum_read(H5F_t *f, H5FD_mem_t map_type, haddr_t addr,
+H5F__accum_read(H5F_shared_t *f_sh, H5FD_mem_t map_type, haddr_t addr,
size_t size, void *buf/*out*/)
{
H5FD_t *file; /* File driver pointer */
@@ -119,18 +120,18 @@ H5F__accum_read(H5F_t *f, H5FD_mem_t map_type, haddr_t addr,
FUNC_ENTER_PACKAGE
/* Sanity checks */
- HDassert(f);
+ HDassert(f_sh);
HDassert(buf);
/* Translate to file driver I/O info object */
- file = f->shared->lf;
+ file = f_sh->lf;
/* Check if this information is in the metadata accumulator */
- if((f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && map_type != H5FD_MEM_DRAW) {
+ if((f_sh->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && map_type != H5FD_MEM_DRAW) {
H5F_meta_accum_t *accum; /* Alias for file's metadata accumulator */
/* Set up alias for file's metadata accumulator info */
- accum = &f->shared->accum;
+ accum = &f_sh->accum;
if(size < H5F_ACCUM_MAX_SIZE) {
/* Sanity check */
@@ -198,7 +199,7 @@ H5F__accum_read(H5F_t *f, H5FD_mem_t map_type, haddr_t addr,
} /* end if */
/* Copy the data out of the buffer */
- HDmemcpy(buf, accum->buf + (addr - new_addr), size);
+ H5MM_memcpy(buf, accum->buf + (addr - new_addr), size);
/* Adjust the accumulator address & size */
accum->loc = new_addr;
@@ -250,7 +251,7 @@ H5F__accum_read(H5F_t *f, H5FD_mem_t map_type, haddr_t addr,
} /* end else */
/* Copy the dirty region to buffer */
- HDmemcpy((unsigned char *)buf + buf_off, (unsigned char *)accum->buf + accum->dirty_off + dirty_off, overlap_size);
+ H5MM_memcpy((unsigned char *)buf + buf_off, (unsigned char *)accum->buf + accum->dirty_off + dirty_off, overlap_size);
} /* end if */
} /* end else */
} /* end if */
@@ -418,7 +419,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5F__accum_write(H5F_t *f, H5FD_mem_t map_type, haddr_t addr,
+H5F__accum_write(H5F_shared_t *f_sh, H5FD_mem_t map_type, haddr_t addr,
size_t size, const void *buf)
{
H5FD_t *file; /* File driver pointer */
@@ -427,19 +428,19 @@ H5F__accum_write(H5F_t *f, H5FD_mem_t map_type, haddr_t addr,
FUNC_ENTER_NOAPI(FAIL)
/* Sanity checks */
- HDassert(f);
- HDassert(H5F_INTENT(f) & H5F_ACC_RDWR);
+ HDassert(f_sh);
+ HDassert(H5F_SHARED_INTENT(f_sh) & H5F_ACC_RDWR);
HDassert(buf);
/* Translate to file driver pointer */
- file = f->shared->lf;
+ file = f_sh->lf;
/* Check for accumulating metadata */
- if((f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && map_type != H5FD_MEM_DRAW) {
+ if((f_sh->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && map_type != H5FD_MEM_DRAW) {
H5F_meta_accum_t *accum; /* Alias for file's metadata accumulator */
/* Set up alias for file's metadata accumulator info */
- accum = &f->shared->accum;
+ accum = &f_sh->accum;
if(size < H5F_ACCUM_MAX_SIZE) {
/* Sanity check */
@@ -457,7 +458,7 @@ H5F__accum_write(H5F_t *f, H5FD_mem_t map_type, haddr_t addr,
HDmemmove(accum->buf + size, accum->buf, accum->size);
/* Copy the new metadata at the front */
- HDmemcpy(accum->buf, buf, size);
+ H5MM_memcpy(accum->buf, buf, size);
/* Set the new size & location of the metadata accumulator */
accum->loc = addr;
@@ -479,7 +480,7 @@ H5F__accum_write(H5F_t *f, H5FD_mem_t map_type, haddr_t addr,
HGOTO_ERROR(H5E_IO, H5E_CANTRESIZE, FAIL, "can't adjust metadata accumulator")
/* Copy the new metadata to the end */
- HDmemcpy(accum->buf + accum->size, buf, size);
+ H5MM_memcpy(accum->buf + accum->size, buf, size);
/* Adjust the dirty region and mark accumulator dirty */
if(accum->dirty)
@@ -502,7 +503,7 @@ H5F__accum_write(H5F_t *f, H5FD_mem_t map_type, haddr_t addr,
size_t dirty_off = (size_t)(addr - accum->loc);
/* Copy the new metadata to the proper location within the accumulator */
- HDmemcpy(accum->buf + dirty_off, buf, size);
+ H5MM_memcpy(accum->buf + dirty_off, buf, size);
/* Adjust the dirty region and mark accumulator dirty */
if(accum->dirty) {
@@ -545,7 +546,7 @@ H5F__accum_write(H5F_t *f, H5FD_mem_t map_type, haddr_t addr,
HDmemmove(accum->buf + size, accum->buf + old_offset, (accum->size - old_offset));
/* Copy the new metadata at the front */
- HDmemcpy(accum->buf, buf, size);
+ H5MM_memcpy(accum->buf, buf, size);
/* Set the new size & location of the metadata accumulator */
accum->loc = addr;
@@ -582,7 +583,7 @@ H5F__accum_write(H5F_t *f, H5FD_mem_t map_type, haddr_t addr,
dirty_off = (size_t)(addr - accum->loc);
/* Copy the new metadata to the end */
- HDmemcpy(accum->buf + dirty_off, buf, size);
+ H5MM_memcpy(accum->buf + dirty_off, buf, size);
/* Set the new size of the metadata accumulator */
accum->size += add_size;
@@ -625,7 +626,7 @@ H5F__accum_write(H5F_t *f, H5FD_mem_t map_type, haddr_t addr,
} /* end if */
/* Copy the new metadata to the buffer */
- HDmemcpy(accum->buf, buf, size);
+ H5MM_memcpy(accum->buf, buf, size);
/* Set the new size & location of the metadata accumulator */
accum->loc = addr;
@@ -688,7 +689,7 @@ H5F__accum_write(H5F_t *f, H5FD_mem_t map_type, haddr_t addr,
accum->size = size;
/* Store the piece of metadata in the accumulator */
- HDmemcpy(accum->buf, buf, size);
+ H5MM_memcpy(accum->buf, buf, size);
/* Adjust the dirty region and mark accumulator dirty */
accum->dirty_off = 0;
@@ -721,7 +722,7 @@ H5F__accum_write(H5F_t *f, H5FD_mem_t map_type, haddr_t addr,
accum->size = size;
/* Store the piece of metadata in the accumulator */
- HDmemcpy(accum->buf, buf, size);
+ H5MM_memcpy(accum->buf, buf, size);
/* Adjust the dirty region and mark accumulator dirty */
accum->dirty_off = 0;
@@ -731,9 +732,9 @@ H5F__accum_write(H5F_t *f, H5FD_mem_t map_type, haddr_t addr,
} /* end if */
else {
/* Make certain that data in accumulator is visible before new write */
- if((H5F_INTENT(f) & H5F_ACC_SWMR_WRITE) > 0)
+ if((H5F_SHARED_INTENT(f_sh) & H5F_ACC_SWMR_WRITE) > 0)
/* Flush if dirty and reset accumulator */
- if(H5F__accum_reset(f, TRUE) < 0)
+ if(H5F__accum_reset(f_sh, TRUE) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTRESET, FAIL, "can't reset accumulator")
/* Write the data */
@@ -782,7 +783,7 @@ H5F__accum_write(H5F_t *f, H5FD_mem_t map_type, haddr_t addr,
} /* end if */
else { /* Access covers whole accumulator */
/* Reset accumulator, but don't flush */
- if(H5F__accum_reset(f, FALSE) < 0)
+ if(H5F__accum_reset(f_sh, FALSE) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTRESET, FAIL, "can't reset accumulator")
} /* end else */
} /* end if */
@@ -846,7 +847,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5F__accum_free(H5F_t *f, H5FD_mem_t H5_ATTR_UNUSED type, haddr_t addr,
+H5F__accum_free(H5F_shared_t *f_sh, H5FD_mem_t H5_ATTR_UNUSED type, haddr_t addr,
hsize_t size)
{
H5F_meta_accum_t *accum; /* Alias for file's metadata accumulator */
@@ -856,16 +857,16 @@ H5F__accum_free(H5F_t *f, H5FD_mem_t H5_ATTR_UNUSED type, haddr_t addr,
FUNC_ENTER_PACKAGE
/* check arguments */
- HDassert(f);
+ HDassert(f_sh);
/* Set up alias for file's metadata accumulator info */
- accum = &f->shared->accum;
+ accum = &f_sh->accum;
/* Translate to file driver pointer */
- file = f->shared->lf;
+ file = f_sh->lf;
/* Adjust the metadata accumulator to remove the freed block, if it overlaps */
- if((f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA)
+ if((f_sh->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA)
&& H5F_addr_overlap(addr, size, accum->loc, accum->size)) {
size_t overlap_size; /* Size of overlap with accumulator */
@@ -1012,28 +1013,28 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5F__accum_flush(H5F_t *f)
+H5F__accum_flush(H5F_shared_t *f_sh)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
/* Sanity checks */
- HDassert(f);
+ HDassert(f_sh);
/* Check if we need to flush out the metadata accumulator */
- if((f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && f->shared->accum.dirty) {
+ if((f_sh->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && f_sh->accum.dirty) {
H5FD_t *file; /* File driver pointer */
/* Translate to file driver pointer */
- file = f->shared->lf;
+ file = f_sh->lf;
/* Flush the metadata contents */
- if(H5FD_write(file, H5FD_MEM_DEFAULT, f->shared->accum.loc + f->shared->accum.dirty_off, f->shared->accum.dirty_len, f->shared->accum.buf + f->shared->accum.dirty_off) < 0)
+ if(H5FD_write(file, H5FD_MEM_DEFAULT, f_sh->accum.loc + f_sh->accum.dirty_off, f_sh->accum.dirty_len, f_sh->accum.buf + f_sh->accum.dirty_off) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed")
/* Reset the dirty flag */
- f->shared->accum.dirty = FALSE;
+ f_sh->accum.dirty = FALSE;
} /* end if */
done:
@@ -1055,34 +1056,31 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5F__accum_reset(H5F_t *f, hbool_t flush)
+H5F__accum_reset(H5F_shared_t *f_sh, hbool_t flush)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
/* Sanity checks */
- HDassert(f);
+ HDassert(f_sh);
/* Flush any dirty data in accumulator, if requested */
if(flush)
- if(H5F__accum_flush(f) < 0)
+ if(H5F__accum_flush(f_sh) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "can't flush metadata accumulator")
/* Check if we need to reset the metadata accumulator information */
- if(f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) {
- /* Sanity check */
- HDassert(!f->closing || FALSE == f->shared->accum.dirty);
-
+ if(f_sh->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) {
/* Free the buffer */
- if(f->shared->accum.buf)
- f->shared->accum.buf = H5FL_BLK_FREE(meta_accum, f->shared->accum.buf);
+ if(f_sh->accum.buf)
+ f_sh->accum.buf = H5FL_BLK_FREE(meta_accum, f_sh->accum.buf);
/* Reset the buffer sizes & location */
- f->shared->accum.alloc_size = f->shared->accum.size = 0;
- f->shared->accum.loc = HADDR_UNDEF;
- f->shared->accum.dirty = FALSE;
- f->shared->accum.dirty_len = 0;
+ f_sh->accum.alloc_size = f_sh->accum.size = 0;
+ f_sh->accum.loc = HADDR_UNDEF;
+ f_sh->accum.dirty = FALSE;
+ f_sh->accum.dirty_len = 0;
} /* end if */
done:
diff --git a/src/H5Fcwfs.c b/src/H5Fcwfs.c
index aa5f8ab..26452b6 100644
--- a/src/H5Fcwfs.c
+++ b/src/H5Fcwfs.c
@@ -299,7 +299,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5F_cwfs_remove_heap(H5F_file_t *shared, H5HG_heap_t *heap)
+H5F_cwfs_remove_heap(H5F_shared_t *shared, H5HG_heap_t *heap)
{
unsigned u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
diff --git a/src/H5Fdeprec.c b/src/H5Fdeprec.c
index c91d0ea..18e915f 100644
--- a/src/H5Fdeprec.c
+++ b/src/H5Fdeprec.c
@@ -42,6 +42,8 @@
#include "H5Iprivate.h" /* IDs */
#include "H5SMprivate.h" /* Shared object header messages */
+#include "H5VLnative_private.h" /* Native VOL connector */
+
/****************/
/* Local Macros */
@@ -96,7 +98,8 @@
herr_t
H5Fget_info1(hid_t obj_id, H5F_info1_t *finfo)
{
- H5F_t *f; /* Top file in mount hierarchy */
+ H5VL_object_t *vol_obj = NULL;
+ H5I_type_t type;
H5F_info2_t finfo2; /* Current file info struct */
herr_t ret_value = SUCCEED; /* Return value */
@@ -107,27 +110,17 @@ H5Fget_info1(hid_t obj_id, H5F_info1_t *finfo)
if(!finfo)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no info struct")
- /* For file IDs, get the file object directly
- *
- * (This prevents the H5G_loc() call from returning the file pointer for
- * the top file in a mount hierarchy)
- */
- if(H5I_get_type(obj_id) == H5I_FILE ) {
- if(NULL == (f = (H5F_t *)H5I_object(obj_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file")
- }
- else {
- H5G_loc_t loc; /* Object location */
-
- /* Get symbol table entry */
- if(H5G_loc(obj_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a valid object ID")
- f = loc.oloc->file;
- }
- HDassert(f->shared);
-
- /* Get the current file info */
- if(H5F__get_info(f, &finfo2) < 0)
+ /* Check the type */
+ type = H5I_get_type(obj_id);
+ if(H5I_FILE != type && H5I_GROUP != type && H5I_DATATYPE != type && H5I_DATASET != type && H5I_ATTR != type)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+
+ /* Get the file object */
+ if(NULL == (vol_obj = H5VL_vol_object(obj_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier")
+
+ /* Get the file information */
+ if(H5VL_file_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_FILE_GET_INFO, type, &finfo2) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to retrieve file info")
/* Copy the compatible fields into the older struct */
@@ -141,6 +134,40 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5Fis_hdf5
+ *
+ * Purpose: Check the file signature to detect an HDF5 file.
+ *
+ * Bugs: This function is not robust: it only uses the default file
+ * driver when attempting to open the file when in fact it
+ * should use all known file drivers.
+ *
+ * Return: TRUE/FALSE/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5Fis_hdf5(const char *name)
+{
+ htri_t ret_value; /* Return value */
+
+ FUNC_ENTER_API((-1))
+ H5TRACE1("t", "*s", name);
+
+ /* Check args and all the boring stuff. */
+ if(!name || !*name)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, (-1), "no file name specified")
+
+ /* Check if file is accessible */
+ if(H5VL_file_specific(NULL, H5VL_FILE_IS_ACCESSIBLE, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5P_FILE_ACCESS_DEFAULT, name, &ret_value) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, (-1), "unable to determine if file is accessible as HDF5")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Fis_hdf5() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5Fset_latest_format
*
* Purpose: Enable switching between latest or non-latest format while
@@ -177,27 +204,31 @@ done:
herr_t
H5Fset_latest_format(hid_t file_id, hbool_t latest_format)
{
- H5F_t *f; /* File */
- H5F_libver_t low = H5F_LIBVER_LATEST; /* Low bound */
- H5F_libver_t high = H5F_LIBVER_LATEST; /* High bound */
- herr_t ret_value = SUCCEED; /* Return value */
+ H5VL_object_t *vol_obj; /* File as VOL object */
+ H5F_libver_t low = H5F_LIBVER_LATEST; /* Low bound */
+ H5F_libver_t high = H5F_LIBVER_LATEST; /* High bound */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE2("e", "ib", file_id, latest_format);
/* Check args */
- if(NULL == (f = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "not a file ID")
+ /* Set up collective metadata if appropriate */
+ if(H5CX_set_loc(file_id) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set collective metadata read info")
+
/* 'low' and 'high' are both initialized to LATEST.
* If latest format is not expected, set 'low' to EARLIEST
- */
+ */
if(!latest_format)
low = H5F_LIBVER_EARLIEST;
- /* Call private set_libver_bounds function to set the bounds */
- if(H5F__set_libver_bounds(f, low, high) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "cannot set low/high bounds")
+ /* Set the library's version bounds */
+ if(H5VL_file_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_FILE_SET_LIBVER_BOUNDS, (int)low, (int)high) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set library version bounds")
done:
FUNC_LEAVE_API(ret_value)
diff --git a/src/H5Fefc.c b/src/H5Fefc.c
index a394071..66d68b2 100644
--- a/src/H5Fefc.c
+++ b/src/H5Fefc.c
@@ -29,8 +29,10 @@
/* Packages needed by this file... */
#include "H5private.h" /* Generic Functions */
+#include "H5CXprivate.h" /* API Contexts */
#include "H5Eprivate.h" /* Error handling */
#include "H5Fpkg.h" /* File access */
+#include "H5Iprivate.h" /* IDs */
#include "H5MMprivate.h" /* Memory management */
#include "H5Pprivate.h" /* Property lists */
@@ -58,14 +60,14 @@ struct H5F_efc_t {
unsigned max_nfiles; /* Maximum size of the external file cache */
unsigned nrefs; /* Number of times this file appears in another file's EFC */
int tag; /* Temporary variable used by H5F__efc_try_close() */
- H5F_file_t *tmp_next; /* Next file in temporary list used by H5F__efc_try_close() */
+ H5F_shared_t *tmp_next; /* Next file in temporary list used by H5F__efc_try_close() */
};
/* Private prototypes */
static herr_t H5F__efc_release_real(H5F_efc_t *efc);
static herr_t H5F__efc_remove_ent(H5F_efc_t *efc, H5F_efc_ent_t *ent);
-static void H5F__efc_try_close_tag1(H5F_file_t *sf, H5F_file_t **tail);
-static void H5F__efc_try_close_tag2(H5F_file_t *sf, H5F_file_t **tail);
+static void H5F__efc_try_close_tag1(H5F_shared_t *sf, H5F_shared_t **tail);
+static void H5F__efc_try_close_tag2(H5F_shared_t *sf, H5F_shared_t **tail);
/* Free lists */
H5FL_DEFINE_STATIC(H5F_efc_ent_t);
@@ -144,6 +146,8 @@ H5F__efc_open(H5F_t *parent, const char *name, unsigned flags, hid_t fcpl_id, hi
H5F_efc_t *efc = NULL; /* External file cache for parent file */
H5F_efc_ent_t *ent = NULL; /* Entry for target file in efc */
hbool_t open_file = FALSE; /* Whether ent->file needs to be closed in case of error */
+ H5P_genplist_t *plist; /* Property list pointer for FAPL */
+ H5VL_connector_prop_t connector_prop; /* Property for VOL connector ID & info */
H5F_t *ret_value = NULL; /* Return value */
FUNC_ENTER_PACKAGE
@@ -153,6 +157,18 @@ H5F__efc_open(H5F_t *parent, const char *name, unsigned flags, hid_t fcpl_id, hi
HDassert(parent->shared);
HDassert(name);
+ /* Get the VOL info from the fapl */
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id)))
+ HGOTO_ERROR(H5E_FILE, H5E_BADTYPE, NULL, "not a file access property list")
+ if(H5P_peek(plist, H5F_ACS_VOL_CONN_NAME, &connector_prop) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't get VOL connector info")
+
+ /* Stash a copy of the "top-level" connector property, before any pass-through
+ * connectors modify or unwrap it.
+ */
+ if(H5CX_set_vol_connector_prop(&connector_prop) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "can't set VOL connector info in API context")
+
/* Get external file cache */
efc = parent->shared->efc;
@@ -628,10 +644,10 @@ done:
*-------------------------------------------------------------------------
*/
static void
-H5F__efc_try_close_tag1(H5F_file_t *sf, H5F_file_t **tail)
+H5F__efc_try_close_tag1(H5F_shared_t *sf, H5F_shared_t **tail)
{
H5F_efc_ent_t *ent = NULL; /* EFC entry */
- H5F_file_t *esf; /* Convenience pointer to ent->file->shared */
+ H5F_shared_t *esf; /* Convenience pointer to ent->file->shared */
FUNC_ENTER_STATIC_NOERR
@@ -702,10 +718,10 @@ H5F__efc_try_close_tag1(H5F_file_t *sf, H5F_file_t **tail)
*-------------------------------------------------------------------------
*/
static void
-H5F__efc_try_close_tag2(H5F_file_t *sf, H5F_file_t **tail)
+H5F__efc_try_close_tag2(H5F_shared_t *sf, H5F_shared_t **tail)
{
H5F_efc_ent_t *ent = NULL; /* EFC entry */
- H5F_file_t *esf; /* Convenience pointer to ent->file->shared */
+ H5F_shared_t *esf; /* Convenience pointer to ent->file->shared */
FUNC_ENTER_STATIC_NOERR
@@ -811,11 +827,11 @@ H5F__efc_try_close_tag2(H5F_file_t *sf, H5F_file_t **tail)
herr_t
H5F__efc_try_close(H5F_t *f)
{
- H5F_file_t *tail; /* Tail of linked list of found files. Head will be f->shared. */
- H5F_file_t *uncloseable_head = NULL; /* Head of linked list of files found to be uncloseable by the first pass */
- H5F_file_t *uncloseable_tail = NULL; /* Tail of linked list of files found to be uncloseable by the first pass */
- H5F_file_t *sf; /* Temporary file pointer */
- H5F_file_t *next; /* Temporary file pointer */
+ H5F_shared_t *tail; /* Tail of linked list of found files. Head will be f->shared. */
+ H5F_shared_t *uncloseable_head = NULL; /* Head of linked list of files found to be uncloseable by the first pass */
+ H5F_shared_t *uncloseable_tail = NULL; /* Tail of linked list of files found to be uncloseable by the first pass */
+ H5F_shared_t *sf; /* Temporary file pointer */
+ H5F_shared_t *next; /* Temporary file pointer */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
diff --git a/src/H5Ffake.c b/src/H5Ffake.c
index 6072f2e..67bd180 100644
--- a/src/H5Ffake.c
+++ b/src/H5Ffake.c
@@ -50,7 +50,7 @@ H5F_fake_alloc(uint8_t sizeof_size)
/* Allocate faked file struct */
if(NULL == (f = H5FL_CALLOC(H5F_t)))
HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, NULL, "can't allocate top file structure")
- if(NULL == (f->shared = H5FL_CALLOC(H5F_file_t)))
+ if(NULL == (f->shared = H5FL_CALLOC(H5F_shared_t)))
HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, NULL, "can't allocate shared file structure")
/* Only set fields necessary for clients */
@@ -93,7 +93,7 @@ H5F_fake_free(H5F_t *f)
if(f) {
/* Destroy shared file struct */
if(f->shared)
- f->shared = H5FL_FREE(H5F_file_t, f->shared);
+ f->shared = H5FL_FREE(H5F_shared_t, f->shared);
f = H5FL_FREE(H5F_t, f);
} /* end if */
diff --git a/src/H5Fint.c b/src/H5Fint.c
index db1b7de..35b3982 100644
--- a/src/H5Fint.c
+++ b/src/H5Fint.c
@@ -38,6 +38,9 @@
#include "H5Pprivate.h" /* Property lists */
#include "H5SMprivate.h" /* Shared Object Header Messages */
#include "H5Tprivate.h" /* Datatypes */
+#include "H5VLprivate.h" /* Virtual Object Layer */
+
+#include "H5VLnative_private.h" /* Native VOL connector */
/****************/
@@ -56,7 +59,7 @@ typedef struct H5F_olist_t {
struct {
hbool_t local; /* Set flag for "local" file searches */
union {
- H5F_file_t *shared; /* Pointer to shared file to look inside */
+ H5F_shared_t *shared; /* Pointer to shared file to look inside */
const H5F_t *file; /* Pointer to file to look inside */
} ptr;
} file_info;
@@ -74,10 +77,12 @@ typedef struct H5F_olist_t {
/* Local Prototypes */
/********************/
+static herr_t H5F__set_vol_conn(H5F_t *file);
static herr_t H5F__get_objects(const H5F_t *f, unsigned types, size_t max_index, hid_t *obj_id_list, hbool_t app_ref, size_t *obj_id_count_ptr);
static int H5F__get_objects_cb(void *obj_ptr, hid_t obj_id, void *key);
static herr_t H5F__build_name(const char *prefix, const char *file_name, char **full_name/*out*/);
static char *H5F__getenv_prefix_name(char **env_prefix/*in,out*/);
+static H5F_t *H5F__new(H5F_shared_t *shared, unsigned flags, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf);
static herr_t H5F__build_actual_name(const H5F_t *f, const H5P_genplist_t *fapl, const char *name, char ** /*out*/ actual_name);
static herr_t H5F__flush_phase1(H5F_t *f);
static herr_t H5F__flush_phase2(H5F_t *f, hbool_t closing);
@@ -98,12 +103,62 @@ static herr_t H5F__flush_phase2(H5F_t *f, hbool_t closing);
/* Declare a free list to manage the H5F_t struct */
H5FL_DEFINE(H5F_t);
-/* Declare a free list to manage the H5F_file_t struct */
-H5FL_DEFINE(H5F_file_t);
+/* Declare a free list to manage the H5F_shared_t struct */
+H5FL_DEFINE(H5F_shared_t);
/*-------------------------------------------------------------------------
+ * Function: H5F__set_vol_conn
+ *
+ * Purpose: Set the VOL connector ID and info for a file.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5F__set_vol_conn(H5F_t *file)
+{
+ H5VL_connector_prop_t connector_prop; /* Property for VOL connector ID & info */
+ void *new_connector_info = NULL; /* Copy of connector info */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity check */
+ HDassert(file);
+
+ /* Retrieve a copy of the "top-level" connector property, before any pass-through
+ * connectors modified or unwrapped it.
+ */
+ if(H5CX_get_vol_connector_prop(&connector_prop) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get VOL connector info from API context")
+
+ /* Sanity check */
+ HDassert(0 != connector_prop.connector_id);
+
+ /* Retrieve the connector for the ID */
+ if(NULL == (file->shared->vol_cls = (H5VL_class_t *)H5I_object(connector_prop.connector_id)))
+ HGOTO_ERROR(H5E_FILE, H5E_BADTYPE, FAIL, "not a VOL connector ID")
+
+ /* Allocate and copy connector info, if it exists */
+ if(connector_prop.connector_info)
+ if(H5VL_copy_connector_info(file->shared->vol_cls, &new_connector_info, connector_prop.connector_info) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCOPY, FAIL, "connector info copy failed")
+
+ /* Cache the connector ID & info for the container */
+ file->shared->vol_id = connector_prop.connector_id;
+ file->shared->vol_info = new_connector_info;
+ if(H5I_inc_ref(file->shared->vol_id, FALSE) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINC, FAIL, "incrementing VOL connector ID failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F__set_vol_conn() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5F_get_access_plist
*
* Purpose: Returns a copy of the file access property list of the
@@ -126,6 +181,7 @@ H5F_get_access_plist(H5F_t *f, hbool_t app_ref)
H5P_genplist_t *old_plist; /* Old property list */
H5FD_driver_prop_t driver_prop; /* Property for driver ID & info */
hbool_t driver_prop_copied = FALSE; /* Whether the driver property has been set up */
+ H5VL_connector_prop_t connector_prop; /* Property for VOL connector ID & info */
unsigned efc_size = 0;
hid_t ret_value = H5I_INVALID_HID; /* Return value */
@@ -138,64 +194,64 @@ H5F_get_access_plist(H5F_t *f, hbool_t app_ref)
if(NULL == (old_plist = (H5P_genplist_t *)H5I_object(H5P_LST_FILE_ACCESS_ID_g)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a property list")
if((ret_value = H5P_copy_plist(old_plist, app_ref)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, H5I_INVALID_HID, "can't copy file access property list")
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, H5I_INVALID_HID, "can't copy file access property list")
if(NULL == (new_plist = (H5P_genplist_t *)H5I_object(ret_value)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a property list")
/* Copy properties of the file access property list */
if(H5P_set(new_plist, H5F_ACS_META_CACHE_INIT_CONFIG_NAME, &(f->shared->mdc_initCacheCfg)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, H5I_INVALID_HID, "can't set initial metadata cache resize config.")
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set initial metadata cache resize config.")
if(H5P_set(new_plist, H5F_ACS_DATA_CACHE_NUM_SLOTS_NAME, &(f->shared->rdcc_nslots)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, H5I_INVALID_HID, "can't set data cache number of slots")
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set data cache number of slots")
if(H5P_set(new_plist, H5F_ACS_DATA_CACHE_BYTE_SIZE_NAME, &(f->shared->rdcc_nbytes)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, H5I_INVALID_HID, "can't set data cache byte size")
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set data cache byte size")
if(H5P_set(new_plist, H5F_ACS_PREEMPT_READ_CHUNKS_NAME, &(f->shared->rdcc_w0)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, H5I_INVALID_HID, "can't set preempt read chunks")
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set preempt read chunks")
if(H5P_set(new_plist, H5F_ACS_ALIGN_THRHD_NAME, &(f->shared->threshold)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, H5I_INVALID_HID, "can't set alignment threshold")
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set alignment threshold")
if(H5P_set(new_plist, H5F_ACS_ALIGN_NAME, &(f->shared->alignment)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, H5I_INVALID_HID, "can't set alignment")
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set alignment")
if(H5P_set(new_plist, H5F_ACS_GARBG_COLCT_REF_NAME, &(f->shared->gc_ref)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, H5I_INVALID_HID, "can't set garbage collect reference")
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set garbage collect reference")
if(H5P_set(new_plist, H5F_ACS_META_BLOCK_SIZE_NAME, &(f->shared->meta_aggr.alloc_size)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, H5I_INVALID_HID, "can't set metadata cache size")
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set metadata cache size")
if(H5P_set(new_plist, H5F_ACS_SIEVE_BUF_SIZE_NAME, &(f->shared->sieve_buf_size)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, H5I_INVALID_HID, "can't sieve buffer size")
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't sieve buffer size")
if(H5P_set(new_plist, H5F_ACS_SDATA_BLOCK_SIZE_NAME, &(f->shared->sdata_aggr.alloc_size)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, H5I_INVALID_HID, "can't set 'small data' cache size")
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set 'small data' cache size")
if(H5P_set(new_plist, H5F_ACS_LIBVER_LOW_BOUND_NAME, &f->shared->low_bound) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, H5I_INVALID_HID, "can't set 'low' bound for library format versions")
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set 'low' bound for library format versions")
if(H5P_set(new_plist, H5F_ACS_LIBVER_HIGH_BOUND_NAME, &f->shared->high_bound) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, H5I_INVALID_HID, "can't set 'high' bound for library format versions")
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set 'high' bound for library format versions")
if(H5P_set(new_plist, H5F_ACS_METADATA_READ_ATTEMPTS_NAME, &(f->shared->read_attempts)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, H5I_INVALID_HID, "can't set 'read attempts ' flag")
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set 'read attempts ' flag")
if(H5P_set(new_plist, H5F_ACS_OBJECT_FLUSH_CB_NAME, &(f->shared->object_flush)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, H5I_INVALID_HID, "can't set object flush callback")
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set object flush callback")
if(f->shared->efc)
efc_size = H5F__efc_max_nfiles(f->shared->efc);
if(H5P_set(new_plist, H5F_ACS_EFC_SIZE_NAME, &efc_size) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, H5I_INVALID_HID, "can't set elink file cache size")
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, H5I_INVALID_HID, "can't set elink file cache size")
if(f->shared->pb_ptr != NULL) {
if(H5P_set(new_plist, H5F_ACS_PAGE_BUFFER_SIZE_NAME, &(f->shared->pb_ptr->max_size)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, H5I_INVALID_HID, "can't set page buffer size")
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, H5I_INVALID_HID, "can't set page buffer size")
if(H5P_set(new_plist, H5F_ACS_PAGE_BUFFER_MIN_META_PERC_NAME, &(f->shared->pb_ptr->min_meta_perc)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, H5I_INVALID_HID, "can't set minimum metadata fraction of page buffer")
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, H5I_INVALID_HID, "can't set minimum metadata fraction of page buffer")
if(H5P_set(new_plist, H5F_ACS_PAGE_BUFFER_MIN_RAW_PERC_NAME, &(f->shared->pb_ptr->min_raw_perc)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, H5I_INVALID_HID, "can't set minimum raw data fraction of page buffer")
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, H5I_INVALID_HID, "can't set minimum raw data fraction of page buffer")
} /* end if */
if(H5P_set(new_plist, H5F_ACS_VFD_SWMR_CONFIG_NAME, &(f->shared->vfd_swmr_config)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set initial metadata cache resize config.")
#ifdef H5_HAVE_PARALLEL
- if(H5P_set(new_plist, H5_COLL_MD_READ_FLAG_NAME, &(f->coll_md_read)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, H5I_INVALID_HID, "can't set collective metadata read flag")
- if(H5P_set(new_plist, H5F_ACS_COLL_MD_WRITE_FLAG_NAME, &(f->coll_md_write)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, H5I_INVALID_HID, "can't set collective metadata read flag")
+ if(H5P_set(new_plist, H5_COLL_MD_READ_FLAG_NAME, &(f->shared->coll_md_read)) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, H5I_INVALID_HID, "can't set collective metadata read flag")
+ if(H5P_set(new_plist, H5F_ACS_COLL_MD_WRITE_FLAG_NAME, &(f->shared->coll_md_write)) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, H5I_INVALID_HID, "can't set collective metadata read flag")
#endif /* H5_HAVE_PARALLEL */
if(H5P_set(new_plist, H5F_ACS_META_CACHE_INIT_IMAGE_CONFIG_NAME, &(f->shared->mdc_initCacheImageCfg)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, H5I_INVALID_HID, "can't set initial metadata cache resize config.")
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set initial metadata cache resize config.")
/* Prepare the driver property */
driver_prop.driver_id = f->shared->lf->driver_id;
@@ -204,13 +260,19 @@ H5F_get_access_plist(H5F_t *f, hbool_t app_ref)
/* Set the driver property */
if(H5P_set(new_plist, H5F_ACS_FILE_DRV_NAME, &driver_prop) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, H5I_INVALID_HID, "can't set file driver ID & info")
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set file driver ID & info")
+
+ /* Set the VOL connector property */
+ connector_prop.connector_id = f->shared->vol_id;
+ connector_prop.connector_info = f->shared->vol_info;
+ if(H5P_set(new_plist, H5F_ACS_VOL_CONN_NAME, &connector_prop) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set VOL connector ID & info")
/* Set the file close degree appropriately */
if(f->shared->fc_degree == H5F_CLOSE_DEFAULT && H5P_set(new_plist, H5F_ACS_CLOSE_DEGREE_NAME, &(f->shared->lf->cls->fc_degree)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, H5I_INVALID_HID, "can't set file close degree")
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set file close degree")
else if(f->shared->fc_degree != H5F_CLOSE_DEFAULT && H5P_set(new_plist, H5F_ACS_CLOSE_DEGREE_NAME, &(f->shared->fc_degree)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, H5I_INVALID_HID, "can't set file close degree")
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set file close degree")
done:
/* Release the copy of the driver info, if it was set up */
@@ -308,11 +370,11 @@ H5F__get_objects(const H5F_t *f, unsigned types, size_t max_nobjs, hid_t *obj_id
if(types & H5F_OBJ_LOCAL) {
olist.file_info.local = TRUE;
olist.file_info.ptr.file = f;
- }
+ } /* end if */
else {
olist.file_info.local = FALSE;
olist.file_info.ptr.shared = f ? f->shared : NULL;
- }
+ } /* end else */
/* Iterate through file IDs to count the number, and put their
* IDs on the object list. */
@@ -320,7 +382,7 @@ H5F__get_objects(const H5F_t *f, unsigned types, size_t max_nobjs, hid_t *obj_id
olist.obj_type = H5I_FILE;
if(H5I_iterate(H5I_FILE, H5F__get_objects_cb, &olist, app_ref) < 0)
HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(1)")
- }
+ } /* end if */
/* If the caller just wants to count the number of objects (OLIST.MAX_NOBJS is zero),
* or the caller wants to get the list of IDs and the list isn't full,
@@ -331,8 +393,8 @@ H5F__get_objects(const H5F_t *f, unsigned types, size_t max_nobjs, hid_t *obj_id
olist.obj_type = H5I_DATASET;
if(H5I_iterate(H5I_DATASET, H5F__get_objects_cb, &olist, app_ref) < 0)
HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(2)")
- }
- }
+ } /* end if */
+ } /* end if */
/* If the caller just wants to count the number of objects (OLIST.MAX_NOBJS is zero),
* or the caller wants to get the list of IDs and the list isn't full,
@@ -343,8 +405,8 @@ H5F__get_objects(const H5F_t *f, unsigned types, size_t max_nobjs, hid_t *obj_id
olist.obj_type = H5I_GROUP;
if(H5I_iterate(H5I_GROUP, H5F__get_objects_cb, &olist, app_ref) < 0)
HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(3)")
- }
- }
+ } /* end if */
+ } /* end if */
/* If the caller just wants to count the number of objects (OLIST.MAX_NOBJS is zero),
* or the caller wants to get the list of IDs and the list isn't full,
@@ -355,8 +417,8 @@ H5F__get_objects(const H5F_t *f, unsigned types, size_t max_nobjs, hid_t *obj_id
olist.obj_type = H5I_DATATYPE;
if(H5I_iterate(H5I_DATATYPE, H5F__get_objects_cb, &olist, app_ref) < 0)
HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(4)")
- }
- }
+ } /* end if */
+ } /* end if */
/* If the caller just wants to count the number of objects (OLIST.MAX_NOBJS is zero),
* or the caller wants to get the list of IDs and the list isn't full,
@@ -367,8 +429,8 @@ H5F__get_objects(const H5F_t *f, unsigned types, size_t max_nobjs, hid_t *obj_id
olist.obj_type = H5I_ATTR;
if(H5I_iterate(H5I_ATTR, H5F__get_objects_cb, &olist, app_ref) < 0)
HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(5)")
- }
- }
+ } /* end if */
+ } /* end if */
/* Set the number of objects currently open */
*obj_id_count_ptr = obj_id_count;
@@ -410,8 +472,8 @@ H5F__get_objects_cb(void *obj_ptr, hid_t obj_id, void *key)
(!olist->file_info.ptr.shared ||
(olist->file_info.ptr.shared && ((H5F_t*)obj_ptr)->shared == olist->file_info.ptr.shared)))) {
add_obj = TRUE;
- }
- }
+ } /* end if */
+ } /* end if */
else { /* Either count opened object IDs or put the IDs on the list */
H5O_loc_t *oloc; /* Group entry info for object */
@@ -435,17 +497,21 @@ H5F__get_objects_cb(void *obj_ptr, hid_t obj_id, void *key)
oloc = NULL;
break;
+ case H5I_MAP:
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5_ITER_ERROR, "maps not supported in native VOL connector")
+
case H5I_UNINIT:
case H5I_BADID:
case H5I_FILE:
case H5I_DATASPACE:
- case H5I_REFERENCE:
case H5I_VFL:
+ case H5I_VOL:
case H5I_GENPROP_CLS:
case H5I_GENPROP_LST:
case H5I_ERROR_CLASS:
case H5I_ERROR_MSG:
case H5I_ERROR_STACK:
+ case H5I_SPACE_SEL_ITER:
case H5I_NTYPES:
default:
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5_ITER_ERROR, "unknown or invalid data object")
@@ -460,7 +526,7 @@ H5F__get_objects_cb(void *obj_ptr, hid_t obj_id, void *key)
(!olist->file_info.ptr.shared && olist->obj_type != H5I_DATATYPE) ||
(oloc && oloc->file && oloc->file->shared == olist->file_info.ptr.shared)))) {
add_obj = TRUE;
- }
+ } /* end if */
} /* end else */
if(add_obj) {
@@ -468,7 +534,7 @@ H5F__get_objects_cb(void *obj_ptr, hid_t obj_id, void *key)
if(olist->obj_id_list) {
olist->obj_id_list[olist->list_index] = obj_id;
olist->list_index++;
- }
+ } /* end if */
/* Increment the number of open objects */
if(olist->obj_id_count)
@@ -481,7 +547,7 @@ H5F__get_objects_cb(void *obj_ptr, hid_t obj_id, void *key)
*/
if(olist->max_nobjs > 0 && olist->list_index >= olist->max_nobjs)
HGOTO_DONE(H5_ITER_STOP) /* Indicate that the iterator should stop */
- }
+ } /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -508,11 +574,11 @@ H5F__build_name(const char *prefix, const char *file_name, char **full_name/*out
fname_len = HDstrlen(file_name);
/* Allocate a buffer to hold the filename + prefix + possibly the delimiter + terminating null byte */
- if(NULL == (*full_name = (char *)H5MM_malloc(prefix_len + fname_len + 2)))
+ if(NULL == (*full_name = (char *)H5MM_malloc(prefix_len + fname_len + 2 + 2))) /* Extra "+2" to quiet GCC warning - 2019/07/05, QAK */
HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "unable to allocate filename buffer")
/* Compose the full file name */
- HDsnprintf(*full_name, (prefix_len + fname_len + 2), "%s%s%s", prefix,
+ HDsnprintf(*full_name, (prefix_len + fname_len + 2 + 2), "%s%s%s", prefix, /* Extra "+2" to quiet GCC warning - 2019/07/05, QAK */
((prefix_len == 0 || H5_CHECK_DELIMITER(prefix[prefix_len - 1])) ? "" : H5_DIR_SEPS), file_name);
done:
@@ -739,14 +805,12 @@ H5F_prefix_open_file(H5F_t *primary_file, H5F_prefix_open_t prefix_type,
/* get last component of file_name */
H5_GET_LAST_DELIMITER(actual_file_name, ptr)
- if(!ptr)
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file, file name = '%s', temp_file_name = '%s'", file_name, temp_file_name)
-
- /* Truncate filename portion from actual file name path */
- *ptr = '\0';
+ if(ptr)
+ /* Truncate filename portion from actual file name path */
+ *ptr = '\0';
/* Build new file name for the external file */
- if(H5F__build_name(actual_file_name, temp_file_name, &full_name/*out*/) < 0)
+ if(H5F__build_name((ptr ? actual_file_name : ""), temp_file_name, &full_name/*out*/) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't prepend prefix to filename")
actual_file_name = (char *)H5MM_xfree(actual_file_name);
@@ -762,7 +826,7 @@ H5F_prefix_open_file(H5F_t *primary_file, H5F_prefix_open_t prefix_type,
H5E_clear_stack(NULL);
} /* end if */
- /* Success */
+ /* Set return value (possibly NULL or valid H5F_t *) */
ret_value = src_file;
done:
@@ -785,36 +849,35 @@ done:
*
* Purpose: Check the file signature to detect an HDF5 file.
*
- * Bugs: This function is not robust: it only uses the default file
- * driver when attempting to open the file when in fact it
- * should use all known file drivers.
- *
* Return: TRUE/FALSE/FAIL
*-------------------------------------------------------------------------
*/
htri_t
-H5F__is_hdf5(const char *name)
+H5F__is_hdf5(const char *name, hid_t fapl_id)
{
H5FD_t *file = NULL; /* Low-level file struct */
- haddr_t sig_addr; /* Addess of hdf5 file signature */
+ haddr_t sig_addr = HADDR_UNDEF; /* Addess of hdf5 file signature */
htri_t ret_value = FAIL; /* Return value */
FUNC_ENTER_PACKAGE
/* Open the file */
- if(NULL == (file = H5FD_open(name, H5F_ACC_RDONLY, H5P_FILE_ACCESS_DEFAULT, HADDR_UNDEF)))
- HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "unable to open file")
+ /* NOTE: This now uses the fapl_id that was passed in, so H5Fis_accessible()
+ * should work with arbitrary VFDs, unlike H5Fis_hdf5().
+ */
+ if(NULL == (file = H5FD_open(name, H5F_ACC_RDONLY, fapl_id, HADDR_UNDEF)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to open file")
/* The file is an hdf5 file if the hdf5 file signature can be found */
if(H5FD_locate_signature(file, &sig_addr) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, FAIL, "unable to locate file signature")
+ HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, FAIL, "error while trying to locate file signature")
ret_value = (HADDR_UNDEF != sig_addr);
done:
/* Close the file */
if(file)
if(H5FD_close(file) < 0 && TRUE == ret_value)
- HDONE_ERROR(H5E_IO, H5E_CANTCLOSEFILE, FAIL, "unable to close file")
+ HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "unable to close file")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5F__is_hdf5() */
@@ -836,17 +899,17 @@ done:
*
*-------------------------------------------------------------------------
*/
-H5F_t *
-H5F__new(H5F_file_t *shared, unsigned flags, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf)
+static H5F_t *
+H5F__new(H5F_shared_t *shared, unsigned flags, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf)
{
H5F_t *f = NULL;
H5F_t *ret_value = NULL;
- FUNC_ENTER_PACKAGE
+ FUNC_ENTER_STATIC
if(NULL == (f = H5FL_CALLOC(H5F_t)))
HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, NULL, "can't allocate top file structure")
- f->file_id = H5I_INVALID_HID;
+ f->id_exists = FALSE;
if(shared) {
HDassert(lf == NULL);
@@ -858,7 +921,7 @@ H5F__new(H5F_file_t *shared, unsigned flags, hid_t fcpl_id, hid_t fapl_id, H5FD_
size_t u; /* Local index variable */
HDassert(lf != NULL);
- if(NULL == (f->shared = H5FL_CALLOC(H5F_file_t)))
+ if(NULL == (f->shared = H5FL_CALLOC(H5F_shared_t)))
HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, NULL, "can't allocate shared file structure")
f->shared->flags = flags;
@@ -873,9 +936,9 @@ H5F__new(H5F_file_t *shared, unsigned flags, hid_t fcpl_id, hid_t fapl_id, H5FD_
f->shared->fs_addr[u] = HADDR_UNDEF;
f->shared->fs_man[u] = NULL;
}
- f->shared->first_alloc_dealloc = FALSE;
- f->shared->eoa_pre_fsm_fsalloc = HADDR_UNDEF;
- f->shared->eoa_post_fsm_fsalloc = HADDR_UNDEF;
+ /* This will be stored as eoa_pre_fsm_fsalloc in the fsinfo message */
+ /* This is done to be backward compatible with 1.10 library that has the FSM hack */
+ f->shared->eoa_fsm_fsalloc = HADDR_UNDEF;
f->shared->eoa_post_mdci_fsalloc = HADDR_UNDEF;
/* Initialization for handling file space (for paged aggregation) */
@@ -956,9 +1019,9 @@ H5F__new(H5F_file_t *shared, unsigned flags, hid_t fcpl_id, hid_t fapl_id, H5FD_
if(NULL == (f->shared->efc = H5F__efc_create(efc_size)))
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "can't create external file cache")
#ifdef H5_HAVE_PARALLEL
- if(H5P_get(plist, H5_COLL_MD_READ_FLAG_NAME, &(f->coll_md_read)) < 0)
+ if(H5P_get(plist, H5_COLL_MD_READ_FLAG_NAME, &(f->shared->coll_md_read)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get collective metadata read flag")
- if(H5P_get(plist, H5F_ACS_COLL_MD_WRITE_FLAG_NAME, &(f->coll_md_write)) < 0)
+ if(H5P_get(plist, H5F_ACS_COLL_MD_WRITE_FLAG_NAME, &(f->shared->coll_md_write)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get collective metadata write flag")
#endif /* H5_HAVE_PARALLEL */
if(H5P_get(plist, H5F_ACS_META_CACHE_INIT_IMAGE_CONFIG_NAME, &(f->shared->mdc_initCacheImageCfg)) < 0)
@@ -977,7 +1040,7 @@ H5F__new(H5F_file_t *shared, unsigned flags, hid_t fcpl_id, hid_t fapl_id, H5FD_
if(H5FD_get_fs_type_map(lf, f->shared->fs_type_map) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't get free space type mapping from VFD")
- if(H5MF_init_merge_flags(f) < 0)
+ if(H5MF_init_merge_flags(f->shared) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "problem initializing free space merge flags")
f->shared->tmp_addr = f->shared->maxaddr;
/* Disable temp. space allocation for parallel I/O (for now) */
@@ -1006,12 +1069,12 @@ H5F__new(H5F_file_t *shared, unsigned flags, hid_t fcpl_id, hid_t fapl_id, H5FD_
f->shared->feature_flags &= ~(unsigned)H5FD_FEAT_ACCUMULATE_METADATA;
if(H5FD_set_feature_flags(f->shared->lf, f->shared->feature_flags) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "can't set feature_flags in VFD")
- }
+ } /* end if */
else {
/* If no value for read attempts has been set, use the default */
if(!f->shared->read_attempts)
f->shared->read_attempts = H5F_METADATA_READ_ATTEMPTS;
- }
+ } /* end else */
/* Determine the # of bins for metdata read retries */
if(H5F_set_retries(f) < 0)
@@ -1058,6 +1121,10 @@ H5F__new(H5F_file_t *shared, unsigned flags, hid_t fcpl_id, hid_t fapl_id, H5FD_
f->shared->dl_tail_ptr = NULL;
f->shared->dl_len = 0;
+ /* Get the VOL connector info */
+ if(H5F__set_vol_conn(f) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "can't cache VOL connector info")
+
/* Create a metadata cache with the specified number of elements.
* The cache might be created with a different number of elements and
* the access property list should be updated to reflect that.
@@ -1094,7 +1161,7 @@ done:
if(H5I_dec_ref(f->shared->fcpl_id) < 0)
HDONE_ERROR(H5E_FILE, H5E_CANTDEC, NULL, "can't close property list")
- f->shared = H5FL_FREE(H5F_file_t, f->shared);
+ f->shared = H5FL_FREE(H5F_shared_t, f->shared);
}
f = H5FL_FREE(H5F_t, f);
}
@@ -1128,6 +1195,9 @@ H5F__dest(H5F_t *f, hbool_t flush)
if(1 == f->shared->nrefs) {
int actype; /* metadata cache type (enum value) */
+ /* Mark this file as closing */
+ f->shared->closing = TRUE;
+
/* Flush at this point since the file will be closed (phase 1).
* Only try to flush the file if it was opened with write access, and if
* the caller requested a flush.
@@ -1284,7 +1354,7 @@ H5F__dest(H5F_t *f, hbool_t flush)
HDONE_ERROR(H5E_IO, H5E_CANTFLUSH, FAIL, "vfd swmr prep for flush or close failed")
/* Shutdown the page buffer cache */
- if(H5PB_dest(f) < 0)
+ if(H5PB_dest(f->shared) < 0)
/* Push error, but keep going*/
HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing page buffer cache")
@@ -1305,7 +1375,7 @@ H5F__dest(H5F_t *f, hbool_t flush)
} /* end if */
/* Destroy other components of the file */
- if(H5F__accum_reset(f, TRUE) < 0)
+ if(H5F__accum_reset(f->shared, TRUE) < 0)
/* Push error, but keep going*/
HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file")
if(H5FO_dest(f) < 0)
@@ -1335,22 +1405,45 @@ H5F__dest(H5F_t *f, hbool_t flush)
HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "unable to remove entry from EOT queue")
}
+ /* Clean up the cached VOL connector ID & info */
+ if(f->shared->vol_info)
+ if(H5VL_free_connector_info(f->shared->vol_id, f->shared->vol_info) < 0)
+ /* Push error, but keep going*/
+ HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "unable to release VOL connector info object")
+ if(f->shared->vol_id > 0)
+ if(H5I_dec_ref(f->shared->vol_id) < 0)
+ /* Push error, but keep going*/
+ HDONE_ERROR(H5E_FILE, H5E_CANTDEC, FAIL, "can't close VOL connector ID")
+ f->shared->vol_cls = NULL;
+
/* Close the file */
if(H5FD_close(f->shared->lf) < 0)
/* Push error, but keep going*/
HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "unable to close file")
+ /* A VFD SWMR reader may still have a metadata index at this stage.
+ * If so, free it.
+ */
+ if (f->shared->vfd_swmr && f->shared->mdf_idx != NULL) {
+ HDfree(f->shared->mdf_idx);
+ f->shared->mdf_idx = NULL;
+ f->shared->mdf_idx_len = 0;
+ }
+
/* Free mount table */
f->shared->mtab.child = (H5F_mount_t *)H5MM_xfree(f->shared->mtab.child);
f->shared->mtab.nalloc = 0;
+ /* Free the external link file */
+ f->shared->extpath = (char *)H5MM_xfree(f->shared->extpath);
+
/* Clean up the metadata retries array */
for(actype = 0; actype < (int)H5AC_NTYPES; actype++)
if(f->shared->retries[actype])
f->shared->retries[actype] = (uint32_t *)H5MM_xfree(f->shared->retries[actype]);
/* Destroy shared file struct */
- f->shared = (H5F_file_t *)H5FL_FREE(H5F_file_t, f->shared);
+ f->shared = (H5F_shared_t *)H5FL_FREE(H5F_shared_t, f->shared);
}
else if(f->shared->nrefs > 0) {
@@ -1369,7 +1462,6 @@ H5F__dest(H5F_t *f, hbool_t flush)
/* Free the non-shared part of the file */
f->open_name = (char *)H5MM_xfree(f->open_name);
f->actual_name = (char *)H5MM_xfree(f->actual_name);
- f->extpath = (char *)H5MM_xfree(f->extpath);
if(H5FO_top_dest(f) < 0)
HDONE_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "problems closing file")
f->shared = NULL;
@@ -1456,7 +1548,7 @@ H5F_t *
H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
{
H5F_t *file = NULL; /*the success return value */
- H5F_file_t *shared = NULL; /*shared part of `file' */
+ H5F_shared_t *shared = NULL; /*shared part of `file' */
H5FD_t *lf = NULL; /*file driver part of `shared' */
unsigned tent_flags; /*tentative flags */
H5FD_class_t *drvr; /*file driver class info */
@@ -1538,26 +1630,12 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
tent_flags = flags;
if(NULL == (lf = H5FD_open(name, tent_flags, fapl_id, HADDR_UNDEF))) {
- if(tent_flags == flags) {
-#ifndef H5_USING_MEMCHECKER
- time_t mytime = HDtime(NULL);
-
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file: time = %s, name = '%s', tent_flags = %x", HDctime(&mytime), name, tent_flags)
-#else /* H5_USING_MEMCHECKER */
+ if(tent_flags == flags)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file: name = '%s', tent_flags = %x", name, tent_flags)
-#endif /* H5_USING_MEMCHECKER */
- } /* end if */
H5E_clear_stack(NULL);
tent_flags = flags;
- if(NULL == (lf = H5FD_open(name, tent_flags, fapl_id, HADDR_UNDEF))) {
-#ifndef H5_USING_MEMCHECKER
- time_t mytime = HDtime(NULL);
-
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file: time = %s, name = '%s', tent_flags = %x", HDctime(&mytime), name, tent_flags)
-#else /* H5_USING_MEMCHECKER */
+ if(NULL == (lf = H5FD_open(name, tent_flags, fapl_id, HADDR_UNDEF)))
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file: name = '%s', tent_flags = %x", name, tent_flags)
-#endif /* H5_USING_MEMCHECKER */
- } /* end if */
} /* end if */
/* For VFD SWMR driver, retrieve the underlying vfd for the search in H5F__sfile_search() */
@@ -1623,7 +1701,7 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
/* Create the 'top' file structure */
if(NULL == (file = H5F__new(NULL, flags, fcpl_id, fapl_id, lf))) {
/* If this is the only time the file has been opened and the struct
- * returned is NULL, H5FD_close() will never be called via H5F_dest()
+ * returned is NULL, H5FD_close() will never be called via H5F__dest()
* so we have to close lf here before heading to the error handling.
*/
if(H5FD_close(lf) < 0)
@@ -1655,7 +1733,7 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
if(page_buf_size) {
#ifdef H5_HAVE_PARALLEL
/* Collective metadata writes are not supported with page buffering */
- if(file->coll_md_write)
+ if(file->shared->coll_md_write)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "collective metadata writes are not supported with page buffering")
/* Temporary: fail file create when page buffering feature is enabled for parallel */
@@ -1681,7 +1759,7 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
/* Create the page buffer before initializing the superblock */
if(page_buf_size)
- if(H5PB_create(file, page_buf_size, page_buf_min_meta_perc, page_buf_min_raw_perc) < 0)
+ if(H5PB_create(shared, page_buf_size, page_buf_min_meta_perc, page_buf_min_raw_perc) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create page buffer")
/* Initialize information about the superblock and allocate space for it */
@@ -1706,7 +1784,7 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
/* Create the page buffer before initializing the superblock */
if(page_buf_size)
- if(H5PB_create(file, page_buf_size, page_buf_min_meta_perc, page_buf_min_raw_perc) < 0)
+ if(H5PB_create(shared, page_buf_size, page_buf_min_meta_perc, page_buf_min_raw_perc) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create page buffer")
/* Open the root group */
@@ -1746,16 +1824,6 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
*/
if(H5P_get(a_plist, H5F_ACS_CLOSE_DEGREE_NAME, &fc_degree) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get file close degree")
-
- /* This is a private property to clear the status_flags in the super block */
- /* Use by h5clear and a routine in test/flush2.c to clear the test file's status_flags */
- if(H5P_exist_plist(a_plist, H5F_ACS_CLEAR_STATUS_FLAGS_NAME) > 0) {
- if(H5P_get(a_plist, H5F_ACS_CLEAR_STATUS_FLAGS_NAME, &clear) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get clearance for status_flags")
- else if(clear)
- file->shared->sblock->status_flags = 0;
- } /* end if */
-
if(shared->nrefs == 1) {
if(fc_degree == H5F_CLOSE_DEFAULT)
shared->fc_degree = lf->cls->fc_degree;
@@ -1769,6 +1837,15 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "file close degree doesn't match")
} /* end if */
+ /* This is a private property to clear the status_flags in the super block */
+ /* Use by h5clear and a routine in test/flush2.c to clear the test file's status_flags */
+ if(H5P_exist_plist(a_plist, H5F_ACS_CLEAR_STATUS_FLAGS_NAME) > 0) {
+ if(H5P_get(a_plist, H5F_ACS_CLEAR_STATUS_FLAGS_NAME, &clear) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get clearance for status_flags")
+ else if(clear)
+ file->shared->sblock->status_flags = 0;
+ } /* end if */
+
/* Record the evict-on-close MDC behavior. If it's the first time opening
* the file, set it to access property list value; if it's the second time
* or later, verify that the access property list value matches the value
@@ -1784,8 +1861,10 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
} /* end if */
/* Formulate the absolute path for later search of target file for external links */
- if(H5_build_extpath(name, &file->extpath) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to build extpath")
+ if(shared->nrefs == 1) {
+ if(H5_build_extpath(name, &file->shared->extpath) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to build extpath")
+ }
/* Formulate the actual file name, after following symlinks, etc. */
if(H5F__build_actual_name(file, a_plist, name, &file->actual_name) < 0)
@@ -1947,7 +2026,7 @@ H5F__flush_phase2(H5F_t *f, hbool_t closing)
#endif /* H5_HAVE_PARALLEL */
/* Flush out the metadata accumulator */
- if(H5F__accum_flush(f) < 0)
+ if(H5F__accum_flush(f->shared) < 0)
/* Push error, but keep going*/
HDONE_ERROR(H5E_IO, H5E_CANTFLUSH, FAIL, "unable to flush metadata accumulator")
@@ -1958,7 +2037,7 @@ H5F__flush_phase2(H5F_t *f, hbool_t closing)
HDONE_ERROR(H5E_IO, H5E_CANTFLUSH, FAIL, "vfd swmr prep for flush or close failed")
/* Flush the page buffer */
- if(H5PB_flush(f) < 0)
+ if(H5PB_flush(f->shared) < 0)
/* Push error, but keep going*/
HDONE_ERROR(H5E_IO, H5E_CANTFLUSH, FAIL, "page buffer flush failed")
@@ -2015,42 +2094,60 @@ H5F__flush(H5F_t *f)
/*-------------------------------------------------------------------------
* Function: H5F__close
*
- * Purpose: Internal routine to close a file.
+ * Purpose: Closes a file or causes the close operation to be pended.
+ * This function is called two ways: from the API it gets called
+ * by H5Fclose->H5I_dec_ref->H5F__close when H5I_dec_ref()
+ * decrements the file ID reference count to zero. The file ID
+ * is removed from the H5I_FILE group by H5I_dec_ref() just
+ * before H5F__close() is called. If there are open object
+ * headers then the close is pended by moving the file to the
+ * H5I_FILE_CLOSING ID group (the f->closing contains the ID
+ * assigned to file).
+ *
+ * This function is also called directly from H5O_close() when
+ * the last object header is closed for the file and the file
+ * has a pending close.
*
* Return: SUCCEED/FAIL
*
*-------------------------------------------------------------------------
*/
herr_t
-H5F__close(hid_t file_id)
+H5F__close(H5F_t *f)
{
- H5F_t *f; /* File pointer */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
- /* Flush file if this is the last reference to this id and we have write
- * intent, unless it will be flushed by the "shared" file being closed.
- * This is only necessary to replicate previous behaviour, and could be
- * disabled by an option/property to improve performance.
- */
- if(NULL == (f = (H5F_t *)H5I_object(file_id)))
- HGOTO_ERROR(H5E_FILE, H5E_BADTYPE, FAIL, "invalid file identifier")
- if((f->shared->nrefs > 1) && (H5F_INTENT(f) & H5F_ACC_RDWR)) {
- int nref; /* Number of references to file ID */
+ /* Sanity check */
+ HDassert(f);
- if((nref = H5I_get_ref(file_id, FALSE)) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get ID ref count")
+ /* Perform checks for "semi" file close degree here, since closing the
+ * file is not allowed if there are objects still open.
+ */
+ if(f->shared->fc_degree == H5F_CLOSE_SEMI) {
+ unsigned nopen_files = 0; /* Number of open files in file/mount hierarchy */
+ unsigned nopen_objs = 0; /* Number of open objects in file/mount hierarchy */
+
+ /* Get the number of open objects and open files on this file/mount hierarchy */
+ if(H5F__mount_count_ids(f, &nopen_files, &nopen_objs) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_MOUNT, FAIL, "problem checking mount hierarchy")
+
+ /* If there are no other file IDs open on this file/mount hier., but
+ * there are still open objects, issue an error and bail out now,
+ * without decrementing the file ID's reference count and triggering
+ * a "real" attempt at closing the file.
+ */
+ if(nopen_files == 1 && nopen_objs > 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file, there are objects still open")
+ }
- if(nref == 1)
- if(H5F__flush(f) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush cache")
- } /* end if */
+ /* Reset the file ID for this file */
+ f->id_exists = FALSE;
- /* Decrement reference count on file ID */
- /* (When it reaches zero the file will be closed) */
- if(H5I_dec_app_ref(file_id) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTDEC, FAIL, "decrementing file ID failed")
+ /* Attempt to close the file/mount hierarchy */
+ if(H5F_try_close(f, NULL) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file")
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -2215,11 +2312,11 @@ H5F_try_close(H5F_t *f, hbool_t *was_closed /*out*/)
/* Delay flush until the shared file struct is closed, in H5F__dest. If the
* application called H5Fclose, it would have been flushed in that function
- * (unless it will have been flushed in H5F_dest anyways).
+ * (unless it will have been flushed in H5F__dest anyways).
*/
/* Destroy the H5F_t struct and decrement the reference count for the
- * shared H5F_file_t struct. If the reference count for the H5F_file_t
+ * shared H5F_shared_t struct. If the reference count for the H5F_shared_t
* struct reaches zero then destroy it also.
*/
if(H5F__dest(f, TRUE) < 0)
@@ -2251,7 +2348,7 @@ done:
H5F_t *
H5F__reopen(H5F_t *f)
{
- H5F_t *ret_value = NULL;
+ H5F_t *ret_value = NULL; /* Return value */
FUNC_ENTER_PACKAGE
@@ -2262,7 +2359,6 @@ H5F__reopen(H5F_t *f)
/* Duplicate old file's names */
ret_value->open_name = H5MM_xstrdup(f->open_name);
ret_value->actual_name = H5MM_xstrdup(f->actual_name);
- ret_value->extpath = H5MM_xstrdup(f->extpath);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -2282,7 +2378,7 @@ done:
*-------------------------------------------------------------------------
*/
hid_t
-H5F_get_id(H5F_t *file, hbool_t app_ref)
+H5F_get_id(H5F_t *file)
{
hid_t ret_value = H5I_INVALID_HID; /* Return value */
@@ -2290,18 +2386,17 @@ H5F_get_id(H5F_t *file, hbool_t app_ref)
HDassert(file);
- if(file->file_id == -1) {
- /* Get an atom for the file */
- if((file->file_id = H5I_register(H5I_FILE, file, app_ref)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to atomize file")
- }
+ if(H5I_find_id(file, H5I_FILE, &ret_value) < 0 || H5I_INVALID_HID == ret_value) {
+ /* resurrect the ID - Register an ID with the native connector */
+ if((ret_value = H5VL_wrap_register(H5I_FILE, file, FALSE)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register group")
+ file->id_exists = TRUE;
+ } /* end if */
else {
/* Increment reference count on existing ID */
- if(H5I_inc_ref(file->file_id, app_ref) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTSET, H5I_INVALID_HID, "incrementing file ID failed")
- }
-
- ret_value = file->file_id;
+ if(H5I_inc_ref(ret_value, FALSE) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTINC, H5I_INVALID_HID, "incrementing file ID failed")
+ } /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -2882,8 +2977,7 @@ H5F__get_file_image(H5F_t *file, void *buf_ptr, size_t buf_len)
/* test to see if a buffer was provided -- if not, we are done */
if(buf_ptr != NULL) {
size_t space_needed; /* size of file image */
- hsize_t tmp;
- size_t tmp_size;
+ unsigned tmp, tmp_size;
/* Check for buffer too small */
if((haddr_t)buf_len < eoa)
@@ -2898,12 +2992,12 @@ H5F__get_file_image(H5F_t *file, void *buf_ptr, size_t buf_len)
/* Offset to "status_flags" in the superblock */
tmp = H5F_SUPER_STATUS_FLAGS_OFF(file->shared->sblock->super_vers);
+
/* Size of "status_flags" depends on the superblock version */
tmp_size = H5F_SUPER_STATUS_FLAGS_SIZE(file->shared->sblock->super_vers);
/* Clear "status_flags" */
- HDmemset((uint8_t *)(buf_ptr) + tmp, 0, tmp_size);
-
+ HDmemset((uint8_t *)buf_ptr + tmp, 0, tmp_size);
} /* end if */
done:
@@ -3032,8 +3126,10 @@ H5F_set_retries(H5F_t *f)
/* Initialize the # of bins for retries */
f->shared->retries_nbins = 0;
if(f->shared->read_attempts > 1) {
- tmp = HDlog10((double)(f->shared->read_attempts - 1));
- f->shared->retries_nbins = (unsigned)tmp + 1;
+ /* Use HDceil to ensure that the log10 value is rounded up to the
+ nearest integer before casting to unsigned */
+ tmp = HDceil(HDlog10((double)f->shared->read_attempts));
+ f->shared->retries_nbins = (unsigned)tmp;
}
FUNC_LEAVE_NOAPI(SUCCEED)
@@ -3116,6 +3212,7 @@ H5F__set_eoa(const H5F_t *f, H5F_mem_t type, haddr_t addr)
HDassert(f->shared);
/* Dispatch to driver */
+ /* (H5FD_set_eoa() will add base_addr to addr) */
if(H5FD_set_eoa(f->shared->lf, type, addr) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "driver set_eoa request failed")
@@ -3189,31 +3286,6 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5F__get_max_eof_eoa() */
-#ifdef H5_HAVE_PARALLEL
-
-/*-------------------------------------------------------------------------
- * Function: H5F_set_coll_md_read
- *
- * Purpose: Set the coll_md_read field with a new value.
- *
- * Return: SUCCEED/FAIL
- *-------------------------------------------------------------------------
- */
-void
-H5F_set_coll_md_read(H5F_t *f, H5P_coll_md_read_flag_t cmr)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOERR
-
- /* Sanity check */
- HDassert(f);
-
- f->coll_md_read = cmr;
-
- FUNC_LEAVE_NOAPI_VOID
-} /* H5F_set_coll_md_read() */
-#endif /* H5_HAVE_PARALLEL */
-
/*-------------------------------------------------------------------------
* Function: H5F_get_metadata_read_retry_info
@@ -3287,7 +3359,7 @@ H5F_get_metadata_read_retry_info(H5F_t *file, H5F_retry_info_t *info)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
/* Copy the information */
- HDmemcpy(info->retries[j], file->shared->retries[i], tot_size);
+ H5MM_memcpy(info->retries[j], file->shared->retries[i], tot_size);
}
/* Increment location in info->retries[] array */
@@ -3351,6 +3423,7 @@ H5F__start_swmr_write(H5F_t *f)
H5G_name_t *obj_paths = NULL; /* Group hierarchy path */
size_t u; /* Local index variable */
hbool_t setup = FALSE; /* Boolean flag to indicate whether SWMR setting is enabled */
+ H5VL_t *vol_connector = NULL; /* VOL connector for the file */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
@@ -3368,7 +3441,7 @@ H5F__start_swmr_write(H5F_t *f)
HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "file superblock version - should be at least 3")
/* Check for correct file format version */
- if((f->shared->low_bound != H5F_LIBVER_V110) || (f->shared->high_bound != H5F_LIBVER_V110))
+ if((f->shared->low_bound < H5F_LIBVER_V110) || (f->shared->high_bound < H5F_LIBVER_V110))
HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "file format version does not support SWMR - needs to be 1.10 or greater")
/* Should not be marked for SWMR writing mode already */
@@ -3390,16 +3463,16 @@ H5F__start_swmr_write(H5F_t *f)
HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush file's cached information")
/* Get the # of opened named datatypes and attributes */
- if(H5F_get_obj_count(f, H5F_OBJ_DATATYPE|H5F_OBJ_ATTR, FALSE, &nt_attr_count) < 0)
+ if(H5F_get_obj_count(f, H5F_OBJ_DATATYPE | H5F_OBJ_ATTR, FALSE, &nt_attr_count) < 0)
HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "H5F_get_obj_count failed")
- if(nt_attr_count)
+ if(nt_attr_count > 0)
HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "named datatypes and/or attributes opened in the file")
/* Get the # of opened datasets and groups */
- if(H5F_get_obj_count(f, H5F_OBJ_GROUP|H5F_OBJ_DATASET, FALSE, &grp_dset_count) < 0)
+ if(H5F_get_obj_count(f, H5F_OBJ_GROUP | H5F_OBJ_DATASET, FALSE, &grp_dset_count) < 0)
HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "H5F_get_obj_count failed")
- if(grp_dset_count) {
+ if(grp_dset_count > 0) {
/* Allocate space for group and object locations */
if((obj_ids = (hid_t *) H5MM_malloc(grp_dset_count * sizeof(hid_t))) == NULL)
HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, FAIL, "can't allocate buffer for hid_t")
@@ -3414,7 +3487,20 @@ H5F__start_swmr_write(H5F_t *f)
if(H5F_get_obj_ids(f, H5F_OBJ_GROUP|H5F_OBJ_DATASET, grp_dset_count, obj_ids, FALSE, &grp_dset_count) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "H5F_get_obj_ids failed")
- /* Refresh opened objects (groups, datasets) in the file */
+ /* Save the VOL connector and the object wrapping context for the refresh step */
+ if(grp_dset_count > 0) {
+ H5VL_object_t *vol_obj;
+
+ /* Get the VOL object for one of the IDs */
+ if(NULL == (vol_obj = H5VL_vol_object(obj_ids[0])))
+ HGOTO_ERROR(H5E_FILE, H5E_BADTYPE, FAIL, "invalid object identifier")
+
+ /* Get the (top) connector for the ID */
+ vol_connector = vol_obj->connector;
+ } /* end if */
+
+ /* Gather information about opened objects (groups, datasets) in the file */
+ /* (For refresh later on) */
for(u = 0; u < grp_dset_count; u++) {
H5O_loc_t *oloc; /* object location */
H5G_loc_t tmp_loc;
@@ -3439,7 +3525,7 @@ H5F__start_swmr_write(H5F_t *f)
} /* end if */
/* Flush and reset the accumulator */
- if(H5F__accum_reset(f, TRUE) < 0)
+ if(H5F__accum_reset(f->shared, TRUE) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTRESET, FAIL, "can't reset accumulator")
/* Turn on SWMR write in shared file open flags */
@@ -3475,10 +3561,9 @@ H5F__start_swmr_write(H5F_t *f)
HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to evict file's cached information")
/* Refresh (reopen) the objects (groups & datasets) in the file */
- for(u = 0; u < grp_dset_count; u++) {
- if(H5O_refresh_metadata_reopen(obj_ids[u], &obj_glocs[u], TRUE) < 0)
+ for(u = 0; u < grp_dset_count; u++)
+ if(H5O_refresh_metadata_reopen(obj_ids[u], &obj_glocs[u], vol_connector, TRUE) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't refresh-close object")
- }
/* Unlock the file */
if(H5FD_unlock(f->shared->lf) < 0)
@@ -3587,3 +3672,215 @@ H5F__format_convert(H5F_t *f)
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5F__format_convert() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F__idx_entry_cmp()
+ *
+ * Purpose: Callback used by HDqsort to sort entries in the index
+ *
+ * Return: 0 if the entries are the same
+ * -1 if entry1's offset is less than that of entry2
+ * 1 if entry1's offset is greater than that of entry2
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5F__idx_entry_cmp(const void *_entry1, const void *_entry2)
+{
+ const H5FD_vfd_swmr_idx_entry_t *entry1 = (const H5FD_vfd_swmr_idx_entry_t *)_entry1;
+ const H5FD_vfd_swmr_idx_entry_t *entry2 = (const H5FD_vfd_swmr_idx_entry_t *)_entry2;
+
+ int ret_value = 0; /* Return value */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Sanity checks */
+ HDassert(entry1);
+ HDassert(entry2);
+
+ if(entry1->hdf5_page_offset < entry2->hdf5_page_offset)
+ ret_value = -1;
+ else if(entry1->hdf5_page_offset > entry2->hdf5_page_offset)
+ ret_value = 1;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5F__idx_entry_cmp() */
+
+
+/*---------------------------------------------------------------------------
+ * Function: H5F__get_file
+ *
+ * Purpose: Utility routine to get file struct for an object
+ *
+ * Returns: SUCCESS: A pointer to the H5F_t struct for the file
+ * associated with the object.
+ * FAILURE: NULL
+ *
+ *---------------------------------------------------------------------------
+ */
+H5F_t *
+H5F__get_file(void *obj, H5I_type_t type)
+{
+ H5F_t *ret_value = NULL; /* File pointer */
+ H5O_loc_t *oloc = NULL; /* Object location for ID */
+
+ FUNC_ENTER_PACKAGE
+
+ switch(type) {
+ case H5I_FILE:
+ ret_value = (H5F_t *)obj;
+ break;
+
+ case H5I_GROUP:
+ oloc = H5G_oloc((H5G_t *)obj);
+ break;
+
+ case H5I_DATATYPE:
+ oloc = H5T_oloc((H5T_t *)obj);
+ break;
+
+ case H5I_DATASET:
+ oloc = H5D_oloc((H5D_t *)obj);
+ break;
+
+ case H5I_ATTR:
+ oloc = H5A_oloc((H5A_t *)obj);
+ break;
+
+ case H5I_MAP:
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "maps not supported in native VOL connector")
+
+ case H5I_UNINIT:
+ case H5I_BADID:
+ case H5I_DATASPACE:
+ case H5I_VFL:
+ case H5I_VOL:
+ case H5I_GENPROP_CLS:
+ case H5I_GENPROP_LST:
+ case H5I_ERROR_CLASS:
+ case H5I_ERROR_MSG:
+ case H5I_ERROR_STACK:
+ case H5I_SPACE_SEL_ITER:
+ case H5I_NTYPES:
+ default:
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file or file object")
+ } /* end switch */
+
+ /* Set return value for objects (not files) */
+ if(oloc)
+ ret_value = oloc->file;
+
+ /* Couldn't find a file struct */
+ if(!ret_value)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "object is not associated with a file")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5F__get_file */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F__get_file_id
+ *
+ * Purpose: The package version of H5Iget_file_id(), obtains the file
+ * ID given an object ID.
+ *
+ * Return: Success: The file ID associated with the object
+ * Failure: H5I_INVALID_HID
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5F__get_file_id(H5F_t *file, hbool_t app_ref)
+{
+ hid_t file_id = H5I_INVALID_HID; /* File ID */
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Check if the file's ID already exists */
+ if(H5I_find_id(file, H5I_FILE, &file_id) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, H5I_INVALID_HID, "getting file ID failed")
+
+ /* If the ID does not exist, register it with the VOL connector */
+ if(H5I_INVALID_HID == file_id) {
+ if((file_id = H5VL_wrap_register(H5I_FILE, file, app_ref)) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to atomize file handle")
+ file->id_exists = TRUE;
+ } /* end if */
+ else {
+ /* Increment ref count on existing ID */
+ if(H5I_inc_ref(file_id, app_ref) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "incrementing file ID failed")
+ } /* end else */
+
+ /* Set return value */
+ ret_value = file_id;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F__get_file_id() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_get_file_id
+ *
+ * Purpose: The private version of H5Iget_file_id(), obtains the file
+ * ID given an object ID.
+ *
+ * Return: Success: The file ID associated with the object
+ * Failure: H5I_INVALID_HID
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5F_get_file_id(hid_t obj_id, H5I_type_t type, hbool_t app_ref)
+{
+ H5VL_object_t *vol_obj; /* File info */
+ hid_t file_id = H5I_INVALID_HID; /* File ID for object */
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5I_INVALID_HID)
+
+ /* Get the object pointer */
+ if(NULL == (vol_obj = H5VL_vol_object(obj_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid identifier")
+
+ /* Get the file through the VOL */
+ if(H5VL_file_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_FILE_GET_FILE_ID, (int)type, (int)app_ref, &file_id) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, H5I_INVALID_HID, "unable to get file ID")
+ if(H5I_INVALID_HID == file_id)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, H5I_INVALID_HID, "unable to get the file ID through the VOL")
+
+ /* Set return value */
+ ret_value = file_id;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_get_file_id() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_set_min_dset_ohdr
+ *
+ * Purpose: Set the crt_dset_ohdr_flag field with a new value.
+ *
+ * Return: SUCCEED/FAIL
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_set_min_dset_ohdr(H5F_t *f, hbool_t minimize)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(f->shared);
+
+ f->shared->crt_dset_min_ohdr_flag = minimize;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5F_set_min_dset_ohdr() */
+
diff --git a/src/H5Fio.c b/src/H5Fio.c
index 69e6bb2..34dd0d6 100644
--- a/src/H5Fio.c
+++ b/src/H5Fio.c
@@ -77,6 +77,50 @@
/*-------------------------------------------------------------------------
+ * Function: H5F_shared_block_read
+ *
+ * Purpose: Reads some data from a file/server/etc into a buffer.
+ * The data is contiguous. The address is relative to the base
+ * address for the file.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Jul 10 1997
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_shared_block_read(H5F_shared_t *f_sh, H5FD_mem_t type, haddr_t addr, size_t size, void *buf/*out*/)
+{
+ H5FD_mem_t map_type; /* Mapped memory type */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(f_sh);
+ HDassert(buf);
+ HDassert(H5F_addr_defined(addr));
+
+ /* Check for attempting I/O on 'temporary' file address */
+ if(H5F_addr_le(f_sh->tmp_addr, (addr + size)))
+ HGOTO_ERROR(H5E_IO, H5E_BADRANGE, FAIL, "attempting I/O in temporary file space")
+
+ /* Treat global heap as raw data */
+ map_type = (type == H5FD_MEM_GHEAP) ? H5FD_MEM_DRAW : type;
+
+ /* Pass through page buffer layer */
+ if(H5PB_read(f_sh, map_type, addr, size, buf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "read through page buffer failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_shared_block_read() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5F_block_read
*
* Purpose: Reads some data from a file/server/etc into a buffer.
@@ -113,7 +157,7 @@ H5F_block_read(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size, void *buf/*
map_type = (type == H5FD_MEM_GHEAP) ? H5FD_MEM_DRAW : type;
/* Pass through page buffer layer */
- if(H5PB_read(f, map_type, addr, size, buf) < 0)
+ if(H5PB_read(f->shared, map_type, addr, size, buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "read through page buffer failed")
done:
@@ -122,6 +166,51 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5F_shared_block_write
+ *
+ * Purpose: Writes some data from memory to a file/server/etc. The
+ * data is contiguous. The address is relative to the base
+ * address.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Jul 10 1997
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_shared_block_write(H5F_shared_t *f_sh, H5FD_mem_t type, haddr_t addr, size_t size, const void *buf)
+{
+ H5FD_mem_t map_type; /* Mapped memory type */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(f_sh);
+ HDassert(H5F_SHARED_INTENT(f_sh) & H5F_ACC_RDWR);
+ HDassert(buf);
+ HDassert(H5F_addr_defined(addr));
+
+ /* Check for attempting I/O on 'temporary' file address */
+ if(H5F_addr_le(f_sh->tmp_addr, (addr + size)))
+ HGOTO_ERROR(H5E_IO, H5E_BADRANGE, FAIL, "attempting I/O in temporary file space")
+
+ /* Treat global heap as raw data */
+ map_type = (type == H5FD_MEM_GHEAP) ? H5FD_MEM_DRAW : type;
+
+ /* Pass through page buffer layer */
+ if(H5PB_write(f_sh, map_type, addr, size, buf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "write through page buffer failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_shared_block_write() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5F_block_write
*
* Purpose: Writes some data from memory to a file/server/etc. The
@@ -159,7 +248,7 @@ H5F_block_write(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size, const void
map_type = (type == H5FD_MEM_GHEAP) ? H5FD_MEM_DRAW : type;
/* Pass through page buffer layer */
- if(H5PB_write(f, map_type, addr, size, buf) < 0)
+ if(H5PB_write(f->shared, map_type, addr, size, buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "write through page buffer failed")
done:
@@ -170,7 +259,7 @@ done:
/*-------------------------------------------------------------------------
* Function: H5F_flush_tagged_metadata
*
- * Purpose: Flushes metadata with specified tag in the metadata cache
+ * Purpose: Flushes metadata with specified tag in the metadata cache
* to disk.
*
* Return: Non-negative on success/Negative on failure
@@ -192,7 +281,7 @@ H5F_flush_tagged_metadata(H5F_t *f, haddr_t tag)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush tagged metadata")
/* Flush and reset the accumulator */
- if(H5F__accum_reset(f, TRUE) < 0)
+ if(H5F__accum_reset(f->shared, TRUE) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTRESET, FAIL, "can't reset accumulator")
/* Flush file buffers to disk. */
diff --git a/src/H5Fmount.c b/src/H5Fmount.c
index e6106a2..13d95aa 100644
--- a/src/H5Fmount.c
+++ b/src/H5Fmount.c
@@ -24,6 +24,7 @@
#include "H5Iprivate.h" /* IDs */
#include "H5MMprivate.h" /* Memory management */
#include "H5Pprivate.h" /* Property lists */
+#include "H5VLprivate.h" /* Virtual Object Layer */
/* PRIVATE PROTOTYPES */
static void H5F__mount_count_ids_recurse(H5F_t *f, unsigned *nopen_files, unsigned *nopen_objs);
@@ -438,8 +439,8 @@ H5F_is_mount(const H5F_t *file)
herr_t
H5Fmount(hid_t loc_id, const char *name, hid_t child_id, hid_t plist_id)
{
- H5G_loc_t loc; /* Parent location */
- H5F_t *child = NULL; /* Child object */
+ H5VL_object_t *loc_vol_obj = NULL; /* Parent object */
+ H5VL_object_t *child_vol_obj = NULL; /* Child object */
H5I_type_t loc_type; /* ID type of location */
H5I_type_t child_type; /* ID type of child */
herr_t ret_value = SUCCEED; /* Return value */
@@ -469,15 +470,19 @@ H5Fmount(hid_t loc_id, const char *name, hid_t child_id, hid_t plist_id)
HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set collective metadata read info")
/* Get the location object */
- if(H5G_loc(loc_id, &loc) < 0)
+ if(NULL == (loc_vol_obj = (H5VL_object_t *)H5I_object(loc_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "could not get location object")
/* Get the child object */
- if(NULL == (child = (H5F_t *)H5I_object_verify(child_id, H5I_FILE)))
+ if(NULL == (child_vol_obj = (H5VL_object_t *)H5I_object(child_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "could not get child object")
+ /* Check if both objects are associated with the same VOL connector */
+ if(loc_vol_obj->connector->cls->value != child_vol_obj->connector->cls->value)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "Can't mount file onto object from different VOL connector")
+
/* Perform the mount operation */
- if(H5F__mount(&loc, name, child, plist_id) < 0)
+ if(H5VL_file_specific(loc_vol_obj, H5VL_FILE_MOUNT, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, (int)loc_type, name, child_vol_obj->data, plist_id) < 0)
HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "unable to mount file")
done:
@@ -504,7 +509,7 @@ done:
herr_t
H5Funmount(hid_t loc_id, const char *name)
{
- H5G_loc_t loc; /* Parent location */
+ H5VL_object_t *vol_obj = NULL; /* Parent object */
H5I_type_t loc_type; /* ID type of location */
herr_t ret_value = SUCCEED; /* Return value */
@@ -525,11 +530,11 @@ H5Funmount(hid_t loc_id, const char *name)
HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set collective metadata read info")
/* Get the location object */
- if(H5G_loc(loc_id, &loc) < 0)
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "could not get location object")
/* Perform the unmount operation */
- if(H5F__unmount(&loc, name) < 0)
+ if(H5VL_file_specific(vol_obj, H5VL_FILE_UNMOUNT, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, (int)loc_type, name) < 0)
HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "unable to unmount file")
done:
@@ -563,7 +568,7 @@ H5F__mount_count_ids_recurse(H5F_t *f, unsigned *nopen_files, unsigned *nopen_ob
HDassert(nopen_objs);
/* If this file is still open, increment number of file IDs open */
- if(f->file_id > 0)
+ if(H5F_ID_EXISTS(f))
*nopen_files += 1;
/* Increment number of open objects in file
diff --git a/src/H5Fmpi.c b/src/H5Fmpi.c
index 7620d95..1630d6b 100644
--- a/src/H5Fmpi.c
+++ b/src/H5Fmpi.c
@@ -38,6 +38,8 @@
#include "H5FDprivate.h" /* File drivers */
#include "H5Iprivate.h" /* IDs */
+#include "H5VLnative_private.h" /* Native VOL connector */
+
/****************/
/* Local Macros */
@@ -90,14 +92,14 @@ herr_t
H5F_get_mpi_handle(const H5F_t *f, MPI_File **f_handle)
{
herr_t ret_value = SUCCEED;
- hid_t fapl = -1;
+ hid_t fapl_id = H5I_INVALID_HID;
FUNC_ENTER_NOAPI(FAIL)
- assert(f && f->shared);
+ HDassert(f && f->shared);
/* Dispatch to driver */
- if ((ret_value = H5FD_get_vfd_handle(f->shared->lf, fapl, (void **)f_handle)) < 0)
+ if ((ret_value = H5FD_get_vfd_handle(f->shared->lf, fapl_id, (void **)f_handle)) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get mpi file handle")
done:
@@ -106,33 +108,31 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5F_mpi_get_rank
+ * Function: H5F_mpi_get_rank
*
- * Purpose: Retrieves the rank of an MPI process.
+ * Purpose: Retrieves the rank of an MPI process.
*
- * Return: Success: The rank (non-negative)
+ * Return: Success: The rank (non-negative)
*
- * Failure: Negative
+ * Failure: Negative
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* Friday, January 30, 2004
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
int
H5F_mpi_get_rank(const H5F_t *f)
{
- int ret_value;
+ int ret_value = -1;
- FUNC_ENTER_NOAPI(FAIL)
+ FUNC_ENTER_NOAPI((-1))
HDassert(f && f->shared);
/* Dispatch to driver */
- if ((ret_value=H5FD_mpi_get_rank(f->shared->lf)) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "driver get_rank request failed")
+ if ((ret_value = H5FD_mpi_get_rank(f->shared->lf)) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, (-1), "driver get_rank request failed")
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -140,33 +140,31 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5F_mpi_get_comm
+ * Function: H5F_mpi_get_comm
*
- * Purpose: Retrieves the file's communicator
+ * Purpose: Retrieves the file's communicator
*
- * Return: Success: The communicator (non-negative)
+ * Return: Success: The communicator (non-negative)
*
- * Failure: Negative
+ * Failure: Negative
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* Friday, January 30, 2004
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
MPI_Comm
H5F_mpi_get_comm(const H5F_t *f)
{
- MPI_Comm ret_value;
+ MPI_Comm ret_value = MPI_COMM_NULL;
FUNC_ENTER_NOAPI(MPI_COMM_NULL)
HDassert(f && f->shared);
/* Dispatch to driver */
- if ((ret_value=H5FD_mpi_get_comm(f->shared->lf))==MPI_COMM_NULL)
- HGOTO_ERROR(H5E_VFL, H5E_CANTGET, MPI_COMM_NULL, "driver get_comm request failed")
+ if ((ret_value = H5FD_mpi_get_comm(f->shared->lf)) == MPI_COMM_NULL)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, MPI_COMM_NULL, "driver get_comm request failed")
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -174,7 +172,7 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5F_mpi_get_size
+ * Function: H5F_shared_mpi_get_size
*
* Purpose: Retrieves the size of an MPI process.
*
@@ -185,22 +183,52 @@ done:
* Programmer: John Mainzer
* Friday, May 6, 2005
*
- * Modifications:
+ *-------------------------------------------------------------------------
+ */
+int
+H5F_shared_mpi_get_size(const H5F_shared_t *f_sh)
+{
+ int ret_value = -1;
+
+ FUNC_ENTER_NOAPI((-1))
+
+ HDassert(f_sh);
+
+ /* Dispatch to driver */
+ if((ret_value = H5FD_mpi_get_size(f_sh->lf)) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, (-1), "driver get_size request failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_shared_mpi_get_size() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_mpi_get_size
+ *
+ * Purpose: Retrieves the size of an MPI process.
+ *
+ * Return: Success: The size (positive)
+ *
+ * Failure: Negative
+ *
+ * Programmer: John Mainzer
+ * Friday, May 6, 2005
*
*-------------------------------------------------------------------------
*/
int
H5F_mpi_get_size(const H5F_t *f)
{
- int ret_value;
+ int ret_value = -1;
- FUNC_ENTER_NOAPI(FAIL)
+ FUNC_ENTER_NOAPI((-1))
HDassert(f && f->shared);
/* Dispatch to driver */
- if ((ret_value=H5FD_mpi_get_size(f->shared->lf)) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "driver get_size request failed")
+ if ((ret_value = H5FD_mpi_get_size(f->shared->lf)) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, (-1), "driver get_size request failed")
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -208,98 +236,154 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5Fset_mpi_atomicity
- *
- * Purpose: Sets the atomicity mode
+ * Function: H5F_set_mpi_atomicity
*
- * Return: Success: Non-negative
+ * Purpose: Private call to set the atomicity mode
*
- * Failure: Negative
- *
- * Programmer: Mohamad Chaarawi
- * Feb 14, 2012
+ * Return: SUCCEED/FAIL
*
*-------------------------------------------------------------------------
*/
herr_t
-H5Fset_mpi_atomicity(hid_t file_id, hbool_t flag)
+H5F_set_mpi_atomicity(H5F_t *file, hbool_t flag)
{
- H5F_t *file;
herr_t ret_value = SUCCEED;
- FUNC_ENTER_API(FAIL)
- H5TRACE2("e", "ib", file_id, flag);
+ FUNC_ENTER_NOAPI(FAIL);
/* Check args */
- if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID")
+ HDassert(file);
/* Check VFD */
- if(!H5F_HAS_FEATURE(file, H5FD_FEAT_HAS_MPI))
- HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "incorrect VFL driver, does not support MPI atomicity mode")
+ if (!H5F_HAS_FEATURE(file, H5FD_FEAT_HAS_MPI))
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "incorrect VFL driver, does not support MPI atomicity mode");
- /* set atomicity value */
- if (H5FD_set_mpio_atomicity (file->shared->lf, flag) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set atomicity flag")
+ /* Set atomicity value */
+ if (H5FD_set_mpio_atomicity(file->shared->lf, flag) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set atomicity flag");
done:
- FUNC_LEAVE_API(ret_value)
-}
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5F_set_mpi_atomicity() */
/*-------------------------------------------------------------------------
- * Function: H5Fget_mpi_atomicity
+ * Function: H5Fset_mpi_atomicity
*
- * Purpose: Returns the atomicity mode
+ * Purpose: Sets the atomicity mode
*
- * Return: Success: Non-negative
+ * Return: Success: Non-negative
+ * Failure: Negative
*
- * Failure: Negative
+ * Programmer: Mohamad Chaarawi
+ * Feb 14, 2012
*
- * Programmer: Mohamad Chaarawi
- * Feb 14, 2012
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Fset_mpi_atomicity(hid_t file_id, hbool_t flag)
+{
+ H5VL_object_t *vol_obj = NULL;
+ int va_flag = (int)flag; /* C is grumpy about passing hbool_t via va_arg */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_API(FAIL);
+ H5TRACE2("e", "ib", file_id, flag);
+
+ /* Get the file object */
+ if (NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(file_id, H5I_FILE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier");
+
+ /* Set atomicity value */
+ if (H5VL_file_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_FILE_SET_MPI_ATOMICITY, va_flag) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to set MPI atomicity");
+
+done:
+ FUNC_LEAVE_API(ret_value);
+} /* end H5Fset_mpi_atomicity() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_get_mpi_atomicity
+ *
+ * Purpose: Private call to get the atomicity mode
+ *
+ * Return: SUCCEED/FAIL
*
*-------------------------------------------------------------------------
*/
herr_t
-H5Fget_mpi_atomicity(hid_t file_id, hbool_t *flag)
+H5F_get_mpi_atomicity(H5F_t *file, hbool_t *flag)
{
- H5F_t *file;
herr_t ret_value = SUCCEED;
- FUNC_ENTER_API(FAIL)
- H5TRACE2("e", "i*b", file_id, flag);
+ FUNC_ENTER_NOAPI(FAIL);
/* Check args */
- if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID")
+ HDassert(file);
+ HDassert(flag);
/* Check VFD */
- if(!H5F_HAS_FEATURE(file, H5FD_FEAT_HAS_MPI))
- HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "incorrect VFL driver, does not support MPI atomicity mode")
+ if (!H5F_HAS_FEATURE(file, H5FD_FEAT_HAS_MPI))
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "incorrect VFL driver, does not support MPI atomicity mode");
- /* get atomicity value */
- if (H5FD_get_mpio_atomicity (file->shared->lf, flag) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get atomicity flag")
+ /* Get atomicity value */
+ if (H5FD_get_mpio_atomicity(file->shared->lf, flag) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get atomicity flag");
done:
- FUNC_LEAVE_API(ret_value)
-}
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5F_get_mpi_atomicity() */
/*-------------------------------------------------------------------------
- * Function: H5F_mpi_retrieve_comm
+ * Function: H5Fget_mpi_atomicity
*
- * Purpose: Retrieves an MPI communicator from the file the location ID
+ * Purpose: Returns the atomicity mode
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Mohamad Chaarawi
+ * Feb 14, 2012
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Fget_mpi_atomicity(hid_t file_id, hbool_t *flag)
+{
+ H5VL_object_t *vol_obj = NULL;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_API(FAIL);
+ H5TRACE2("e", "i*b", file_id, flag);
+
+ /* Get the file object */
+ if (NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(file_id, H5I_FILE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier");
+
+ /* Get atomicity value */
+ if (H5VL_file_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_FILE_GET_MPI_ATOMICITY, flag) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get MPI atomicity");
+
+done:
+ FUNC_LEAVE_API(ret_value);
+} /* end H5Fget_mpi_atomicity() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_mpi_retrieve_comm
+ *
+ * Purpose: Retrieves an MPI communicator from the file the location ID
* is in. If the loc_id is invalid, the fapl_id is used to
* retrieve the communicator.
*
- * Return: Success: Non-negative
+ * Return: Success: Non-negative
*
- * Failure: Negative
+ * Failure: Negative
*
- * Programmer: Mohamad Chaarawi
- * Feb 14, 2012
+ * Programmer: Mohamad Chaarawi
+ * Feb 14, 2012
*
*-------------------------------------------------------------------------
*/
@@ -342,14 +426,9 @@ H5F_mpi_retrieve_comm(hid_t loc_id, hid_t acspl_id, MPI_Comm *mpi_comm)
if(NULL == (plist = H5P_object_verify(acspl_id, H5P_FILE_ACCESS)))
HGOTO_ERROR(H5E_FILE, H5E_BADTYPE, FAIL, "not a file access list")
- if(H5FD_MPIO == H5P_peek_driver(plist)) {
- const H5FD_mpio_fapl_t *fa; /* MPIO fapl info */
-
- if(NULL == (fa = (const H5FD_mpio_fapl_t *)H5P_peek_driver_info(plist)))
- HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad VFL driver info")
-
- *mpi_comm = fa->comm;
- }
+ if(H5FD_MPIO == H5P_peek_driver(plist))
+ if(H5P_peek(plist, H5F_ACS_MPI_PARAMS_COMM_NAME, mpi_comm) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get MPI communicator")
}
done:
diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h
index ff92c98..bedf2f9 100644
--- a/src/H5Fpkg.h
+++ b/src/H5Fpkg.h
@@ -29,13 +29,11 @@
/* Get package's private header */
#include "H5Fprivate.h"
-/* Other public headers needed by this file */
-#include "H5Bpublic.h" /* B-tree header (for H5B_NUM_BTREE_ID) */
-
/* Other private headers needed by this file */
#include "H5private.h" /* Generic Functions */
#include "H5ACprivate.h" /* Metadata cache */
#include "H5FDprivate.h" /* VFD -- for VFD SWMR */
+#include "H5Bprivate.h" /* B-trees */
#include "H5FLprivate.h" /* Free Lists */
#include "H5FOprivate.h" /* File objects */
#include "H5FSprivate.h" /* File free space */
@@ -140,14 +138,14 @@
/* For superblock version 0 & 1:
Offset to the file consistency flags (status_flags) in the superblock (excluding H5F_SUPERBLOCK_FIXED_SIZE) */
-#define H5F_SUPER_STATUS_OFF_V01 \
- (2 /* freespace, and root group versions */ \
- + 1 /* reserved */ \
- + 3 /* shared header vers, size of address, size of lengths */ \
- + 1 /* reserved */ \
- + 4) /* group leaf k, group internal k */
+#define H5F_SUPER_STATUS_OFF_V01 \
+ (unsigned)(2 /* freespace, and root group versions */ \
+ + 1 /* reserved */ \
+ + 3 /* shared header vers, size of address, size of lengths */ \
+ + 1 /* reserved */ \
+ + 4) /* group leaf k, group internal k */
-#define H5F_SUPER_STATUS_OFF(v) (v >= 2 ? 2 : H5F_SUPER_STATUS_OFF_V01)
+#define H5F_SUPER_STATUS_OFF(v) (v >= 2 ? (unsigned)2 : H5F_SUPER_STATUS_OFF_V01)
/* Offset to the file consistency flags (status_flags) in the superblock */
#define H5F_SUPER_STATUS_FLAGS_OFF(v) (H5F_SUPERBLOCK_FIXED_SIZE + H5F_SUPER_STATUS_OFF(v))
@@ -239,7 +237,7 @@ typedef struct H5F_vfd_swmr_dl_entry_t {
} H5F_vfd_swmr_dl_entry_t;
/* Structure specifically to store superblock. This was originally
- * maintained entirely within H5F_file_t, but is now extracted
+ * maintained entirely within H5F_shared_t, but is now extracted
* here because the superblock is now handled by the cache */
typedef struct H5F_super_t {
H5AC_info_t cache_info; /* Cache entry information structure */
@@ -257,14 +255,26 @@ typedef struct H5F_super_t {
H5G_entry_t *root_ent; /* Root group symbol table entry */
} H5F_super_t;
+#include "bsdqueue.h"
+
+typedef struct deferred_free {
+ SIMPLEQ_ENTRY(deferred_free) link;
+ H5FD_mem_t alloc_type;
+ haddr_t addr;
+ hsize_t size;
+ uint64_t free_after_tick;
+} deferred_free_t;
+
+typedef SIMPLEQ_HEAD(deferred_free_head, deferred_free) deferred_free_head_t;
+
/*
* Define the structure to store the file information for HDF5 files. One of
* these structures is allocated per file, not per H5Fopen(). That is, set of
- * H5F_t structs can all point to the same H5F_file_t struct. The `nrefs'
+ * H5F_t structs can all point to the same H5F_shared_t struct. The `nrefs'
* count in this struct indicates the number of H5F_t structs which are
* pointing to this struct.
*/
-struct H5F_file_t {
+struct H5F_shared_t {
H5FD_t *lf; /* Lower level file handle for I/O */
H5F_super_t *sblock; /* Pointer to (pinned) superblock for file */
H5O_drvinfo_t *drvinfo; /* Pointer to the (pinned) driver info
@@ -316,7 +326,7 @@ struct H5F_file_t {
/* begin on file access/create */
char *mdc_log_location; /* location of mdc log */
hid_t fcpl_id; /* File creation property list ID */
- H5F_close_degree_t fc_degree; /* File close behavior degree */
+ H5F_close_degree_t fc_degree; /* File close behavior degree */
hbool_t evict_on_close; /* If the file's objects should be evicted from the metadata cache on close */
size_t rdcc_nslots; /* Size of raw data chunk cache (slots) */
size_t rdcc_nbytes; /* Size of raw data chunk cache (bytes) */
@@ -333,11 +343,20 @@ struct H5F_file_t {
struct H5G_t *root_grp; /* Open root group */
H5FO_t *open_objs; /* Open objects in file */
H5UC_t *grp_btree_shared; /* Ref-counted group B-tree node info */
+ hbool_t closing; /* File is in the process of being closed */
+
+ /* Cached VOL connector ID & info */
+ hid_t vol_id; /* ID of VOL connector for the container */
+ const H5VL_class_t *vol_cls; /* Pointer to VOL connector class for the container */
+ void *vol_info; /* Copy of VOL connector info for container */
/* File space allocation information */
H5F_fspace_strategy_t fs_strategy; /* File space handling strategy */
hsize_t fs_threshold; /* Free space section threshold */
hbool_t fs_persist; /* Free-space persist or not */
+ unsigned fs_version; /* Free-space version: */
+ /* It is used to update fsinfo message in the superblock
+ extension when closing down the free-space managers */
hbool_t use_tmp_space; /* Whether temp. file space allocation is allowed */
haddr_t tmp_addr; /* Next address to use for temp. space in the file */
hbool_t point_of_no_return; /* Flag to indicate that we can't go back and delete a freespace header when it's used up */
@@ -345,14 +364,9 @@ struct H5F_file_t {
H5F_fs_state_t fs_state[H5F_MEM_PAGE_NTYPES]; /* State of free space manager for each type */
haddr_t fs_addr[H5F_MEM_PAGE_NTYPES]; /* Address of free space manager info for each type */
H5FS_t *fs_man[H5F_MEM_PAGE_NTYPES]; /* Free space manager for each file space type */
- hbool_t first_alloc_dealloc; /* TRUE iff free space managers */
- /* are persistent and have not */
- /* been used accessed for either */
- /* allocation or deallocation */
- /* since file open. */
- haddr_t eoa_pre_fsm_fsalloc; /* eoa pre file space allocation */
- /* for self referential FSMs */
- haddr_t eoa_post_fsm_fsalloc; /* eoa post file space allocation */
+ hbool_t null_fsm_addr; /* Used by h5clear tool to tell the library */
+ /* to drop free-space to the floor */
+ haddr_t eoa_fsm_fsalloc; /* eoa after file space allocation */
/* for self referential FSMs */
haddr_t eoa_post_mdci_fsalloc; /* eoa past file space allocation */
/* for metadata cache image, or */
@@ -378,6 +392,7 @@ struct H5F_file_t {
/* Object flush info */
H5F_object_flush_t object_flush; /* Information for object flush callback */
+ hbool_t crt_dset_min_ohdr_flag; /* flag to minimize created dataset object header */
/* VFD SWMR */
@@ -394,7 +409,7 @@ struct H5F_file_t {
*/
uint64_t tick_num; /* Number of the current tick */
struct timespec end_of_tick; /* End time of the current tick */
-
+ deferred_free_head_t deferred_frees; /* For use by VFD SWMR writers. */
/* VFD SWMR metadata file index */
H5FD_vfd_swmr_idx_entry_t * mdf_idx; /* pointer to an array of instance
* of H5FD_vfd_swmr_idx_entry_t of
@@ -457,45 +472,33 @@ struct H5F_file_t {
*/
H5F_vfd_swmr_dl_entry_t *dl_tail_ptr; /* Points to the end of the list */
+ char *extpath; /* Path for searching target external link file */
+
+#ifdef H5_HAVE_PARALLEL
+ H5P_coll_md_read_flag_t coll_md_read; /* Do all metadata reads collectively */
+ hbool_t coll_md_write; /* Do all metadata writes collectively */
+#endif /* H5_HAVE_PARALLEL */
+
};
/*
* This is the top-level file descriptor. One of these structures is
* allocated every time H5Fopen() is called although they may contain pointers
- * to shared H5F_file_t structs.
+ * to shared H5F_shared_t structs.
*/
struct H5F_t {
- char *open_name; /* Name used to open file */
- char *actual_name; /* Actual name of the file, after resolving symlinks, etc. */
- char *extpath; /* Path for searching target external link file */
- H5F_file_t *shared; /* The shared file info */
- unsigned nopen_objs; /* Number of open object headers */
+ char *open_name; /* Name used to open file */
+ char *actual_name; /* Actual name of the file, after resolving symlinks, etc. */
+ H5F_shared_t *shared; /* The shared file info */
+ unsigned nopen_objs; /* Number of open object headers */
H5FO_t *obj_count; /* # of time each object is opened through top file structure */
- hid_t file_id; /* ID of this file */
+ hbool_t id_exists; /* Whether an ID for this struct exists */
hbool_t closing; /* File is in the process of being closed */
struct H5F_t *parent; /* Parent file that this file is mounted to */
unsigned nmounts; /* Number of children mounted to this file */
-#ifdef H5_HAVE_PARALLEL
- H5P_coll_md_read_flag_t coll_md_read; /* Do all metadata reads collectively */
- hbool_t coll_md_write; /* Do all metadata writes collectively */
-#endif /* H5_HAVE_PARALLEL */
};
-/* User data for traversal routine to get ID counts */
-typedef struct {
- ssize_t *obj_count; /* number of objects counted so far */
- unsigned types; /* types of objects to be counted */
-} H5F_trav_obj_cnt_t;
-
-/* User data for traversal routine to get ID lists */
-typedef struct {
- size_t max_objs;
- hid_t *oid_list;
- ssize_t *obj_count; /* number of objects counted so far */
- unsigned types; /* types of objects to be counted */
-} H5F_trav_obj_ids_t;
-
/*****************************/
/* Package Private Variables */
/*****************************/
@@ -503,8 +506,8 @@ typedef struct {
/* Declare a free list to manage the H5F_t struct */
H5FL_EXTERN(H5F_t);
-/* Declare a free list to manage the H5F_file_t struct */
-H5FL_EXTERN(H5F_file_t);
+/* Declare a free list to manage the H5F_shared_t struct */
+H5FL_EXTERN(H5F_shared_t);
/******************************/
@@ -513,16 +516,18 @@ H5FL_EXTERN(H5F_file_t);
/* General routines */
H5_DLL H5F_t *H5F__reopen(H5F_t *f);
-H5_DLL H5F_t *H5F__new(H5F_file_t *shared, unsigned flags, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf);
H5_DLL herr_t H5F__dest(H5F_t *f, hbool_t flush);
H5_DLL herr_t H5F__flush(H5F_t *f);
-H5_DLL htri_t H5F__is_hdf5(const char *name);
+H5_DLL htri_t H5F__is_hdf5(const char *name, hid_t fapl_id);
H5_DLL ssize_t H5F__get_file_image(H5F_t *f, void *buf_ptr, size_t buf_len);
H5_DLL herr_t H5F__get_info(H5F_t *f, H5F_info2_t *finfo);
H5_DLL herr_t H5F__format_convert(H5F_t *f);
H5_DLL herr_t H5F__start_swmr_write(H5F_t *f);
-H5_DLL herr_t H5F__close(hid_t file_id);
+H5_DLL herr_t H5F__close(H5F_t *f);
H5_DLL herr_t H5F__set_libver_bounds(H5F_t *f, H5F_libver_t low, H5F_libver_t high);
+H5_DLL H5F_t *H5F__get_file(void *obj, H5I_type_t type);
+H5_DLL hid_t H5F__get_file_id(H5F_t *file, hbool_t app_ref);
+H5_DLL herr_t H5F__get_cont_info(const H5F_t *f, H5VL_file_cont_info_t *info);
/* File mount related routines */
H5_DLL herr_t H5F__mount(H5G_loc_t *loc, const char *name, H5F_t *child, hid_t plist_id);
@@ -543,16 +548,16 @@ H5_DLL herr_t H5F__super_ext_remove_msg(H5F_t *f, unsigned id);
H5_DLL herr_t H5F__super_ext_close(H5F_t *f, H5O_loc_t *ext_ptr, hbool_t was_created);
/* Metadata accumulator routines */
-H5_DLL herr_t H5F__accum_read(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size, void *buf);
-H5_DLL herr_t H5F__accum_write(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size, const void *buf);
-H5_DLL herr_t H5F__accum_free(H5F_t *f, H5FD_mem_t type, haddr_t addr, hsize_t size);
-H5_DLL herr_t H5F__accum_flush(H5F_t *f);
-H5_DLL herr_t H5F__accum_reset(H5F_t *f, hbool_t flush);
+H5_DLL herr_t H5F__accum_read(H5F_shared_t *f_sh, H5FD_mem_t type, haddr_t addr, size_t size, void *buf);
+H5_DLL herr_t H5F__accum_write(H5F_shared_t *f_sh, H5FD_mem_t type, haddr_t addr, size_t size, const void *buf);
+H5_DLL herr_t H5F__accum_free(H5F_shared_t *f, H5FD_mem_t type, haddr_t addr, hsize_t size);
+H5_DLL herr_t H5F__accum_flush(H5F_shared_t *f_sh);
+H5_DLL herr_t H5F__accum_reset(H5F_shared_t *f_sh, hbool_t flush);
/* Shared file list related routines */
-H5_DLL herr_t H5F__sfile_add(H5F_file_t *shared);
-H5_DLL H5F_file_t *H5F__sfile_search(H5FD_t *lf);
-H5_DLL herr_t H5F__sfile_remove(H5F_file_t *shared);
+H5_DLL herr_t H5F__sfile_add(H5F_shared_t *shared);
+H5_DLL H5F_shared_t *H5F__sfile_search(H5FD_t *lf);
+H5_DLL herr_t H5F__sfile_remove(H5F_shared_t *shared);
/* External file cache routines */
H5_DLL H5F_efc_t *H5F__efc_create(unsigned max_nfiles);
@@ -593,6 +598,8 @@ H5_DLL herr_t H5F__get_sbe_addr_test(hid_t file_id, haddr_t *sbe_addr);
H5_DLL herr_t H5F__vfd_swmr_writer_create_open_flush_test(hid_t file_id, hbool_t create);
H5_DLL herr_t H5F__vfd_swmr_writer_md_test(hid_t file_id, unsigned num_entries, struct H5FD_vfd_swmr_idx_entry_t *index,
unsigned num_dl_entries);
+
+H5_DLL htri_t H5F__same_file_test(hid_t file_id1, hid_t file_id2);
#endif /* H5F_TESTING */
#endif /* _H5Fpkg_H */
diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h
index 6e14540..f04d284 100644
--- a/src/H5Fprivate.h
+++ b/src/H5Fprivate.h
@@ -25,13 +25,15 @@ typedef struct H5F_t H5F_t;
#include "H5Fpublic.h"
/* Public headers needed by this file */
-#include "H5FDpublic.h" /* File drivers */
+#include "H5FDpublic.h" /* File drivers */
+#include "H5VLpublic.h" /* Virtual Object Layer */
/* Private headers needed by this file */
+#include "H5MMprivate.h" /* Memory management */
#ifdef H5_HAVE_PARALLEL
-#include "H5Pprivate.h" /* Property lists */
+#include "H5Pprivate.h" /* Property lists */
#endif /* H5_HAVE_PARALLEL */
-#include "H5VMprivate.h" /* Vectors and arrays */
+#include "H5VMprivate.h" /* Vectors and arrays */
/**************************/
@@ -134,7 +136,7 @@ typedef struct H5F_t H5F_t;
\
HDcompile_assert(sizeof(double) == 8); \
HDcompile_assert(sizeof(double) == sizeof(uint64_t)); \
- HDmemcpy(&_n, &n, sizeof(double)); \
+ H5MM_memcpy(&_n, &n, sizeof(double)); \
for(_u = 0; _u < sizeof(uint64_t); _u++, _n >>= 8) \
*_p++ = (uint8_t)(_n & 0xff); \
(p) = (uint8_t *)(p) + 8; \
@@ -159,16 +161,16 @@ typedef struct H5F_t H5F_t;
(i) |= (uint16_t)((*(p) & 0xff) << 8); (p)++; \
}
-# define INT32DECODE(p, i) { \
- (i) = ((int32_t)(*(p) & (unsigned)0xff)); (p)++; \
- (i) |= ((int32_t)(*(p) & (unsigned)0xff) << 8); (p)++; \
- (i) |= ((int32_t)(*(p) & (unsigned)0xff) << 16); (p)++; \
- (i) |= ((int32_t)(((*(p) & (unsigned)0xff) << 24) | \
- ((*(p) & (unsigned)0x80) ? (unsigned)(~0xffffffff) : (unsigned)0x0))); (p)++; \
+# define INT32DECODE(p, i) { \
+ (i) = ((int32_t)(*(p) & 0xff)); (p)++; \
+ (i) |= ((int32_t)(*(p) & 0xff) << 8); (p)++; \
+ (i) |= ((int32_t)(*(p) & 0xff) << 16); (p)++; \
+ (i) |= ((int32_t)(((*(p) & (unsigned)0xff) << 24) | \
+ ((*(p) & 0x80) ? ~0xffffffffULL : 0x0ULL))); (p)++; \
}
-# define UINT32DECODE(p, i) { \
- (i) = (uint32_t)(*(p) & 0xff); (p)++; \
+# define UINT32DECODE(p, i) { \
+ (i) = (uint32_t)(*(p) & 0xff); (p)++; \
(i) |= ((uint32_t)(*(p) & 0xff) << 8); (p)++; \
(i) |= ((uint32_t)(*(p) & 0xff) << 16); (p)++; \
(i) |= ((uint32_t)(*(p) & 0xff) << 24); (p)++; \
@@ -240,7 +242,7 @@ typedef struct H5F_t H5F_t;
(p) += 8; \
for(_u = 0; _u < sizeof(uint64_t); _u++) \
_n = (_n << 8) | *(--p); \
- HDmemcpy(&(n), &_n, sizeof(double)); \
+ H5MM_memcpy(&(n), &_n, sizeof(double)); \
(p) += 8; \
}
@@ -277,21 +279,23 @@ typedef struct H5F_t H5F_t;
#ifdef H5F_MODULE
#define H5F_LOW_BOUND(F) ((F)->shared->low_bound)
#define H5F_HIGH_BOUND(F) ((F)->shared->high_bound)
+#define H5F_SHARED_INTENT(F_SH) ((F_SH)->flags)
#define H5F_INTENT(F) ((F)->shared->flags)
#define H5F_OPEN_NAME(F) ((F)->open_name)
#define H5F_ACTUAL_NAME(F) ((F)->actual_name)
-#define H5F_EXTPATH(F) ((F)->extpath)
+#define H5F_EXTPATH(F) ((F)->shared->extpath)
#define H5F_SHARED(F) ((F)->shared)
#define H5F_SAME_SHARED(F1, F2) ((F1)->shared == (F2)->shared)
#define H5F_NOPEN_OBJS(F) ((F)->nopen_objs)
#define H5F_INCR_NOPEN_OBJS(F) ((F)->nopen_objs++)
#define H5F_DECR_NOPEN_OBJS(F) ((F)->nopen_objs--)
-#define H5F_FILE_ID(F) ((F)->file_id)
+#define H5F_ID_EXISTS(F) ((F)->id_exists)
#define H5F_PARENT(F) ((F)->parent)
#define H5F_NMOUNTS(F) ((F)->nmounts)
#define H5F_GET_READ_ATTEMPTS(F) ((F)->shared->read_attempts)
#define H5F_DRIVER_ID(F) ((F)->shared->lf->driver_id)
#define H5F_GET_FILENO(F,FILENUM) ((FILENUM) = (F)->shared->lf->fileno)
+#define H5F_SHARED_HAS_FEATURE(F_SH,FL) ((F_SH)->lf->feature_flags & (FL))
#define H5F_HAS_FEATURE(F,FL) ((F)->shared->lf->feature_flags & (FL))
#define H5F_BASE_ADDR(F) ((F)->shared->sblock->base_addr)
#define H5F_SYM_LEAF_K(F) ((F)->shared->sblock->sym_leaf_k)
@@ -320,7 +324,7 @@ typedef struct H5F_t H5F_t;
#define H5F_USE_TMP_SPACE(F) ((F)->shared->fs.use_tmp_space)
#define H5F_IS_TMP_ADDR(F, ADDR) (H5F_addr_le((F)->shared->fs.tmp_addr, (ADDR)))
#ifdef H5_HAVE_PARALLEL
-#define H5F_COLL_MD_READ(F) ((F)->coll_md_read)
+#define H5F_COLL_MD_READ(F) ((F)->shared->coll_md_read)
#endif /* H5_HAVE_PARALLEL */
#define H5F_USE_MDC_LOGGING(F) ((F)->shared->use_mdc_logging)
#define H5F_START_MDC_LOG_ON_ACCESS(F) ((F)->shared->start_mdc_log_on_access)
@@ -333,9 +337,14 @@ typedef struct H5F_t H5F_t;
#define H5F_EOA_PRE_FSM_FSALLOC(F) ((F)->shared->eoa_pre_fsm_fsalloc)
#define H5F_USE_VFD_SWMR(F) ((F)->shared->vfd_swmr)
#define H5F_VFD_SWMR_MD_EOA(F) ((F)->shared->vfd_swmr_md_eoa)
+#define H5F_NULL_FSM_ADDR(F) ((F)->shared->null_fsm_addr)
+#define H5F_GET_MIN_DSET_OHDR(F) ((F)->shared->crt_dset_min_ohdr_flag)
+#define H5F_SET_MIN_DSET_OHDR(F, V) ((F)->shared->crt_dset_min_ohdr_flag = (V))
+#define H5F_VOL_CLS(F) ((F)->shared->vol_cls)
#else /* H5F_MODULE */
#define H5F_LOW_BOUND(F) (H5F_get_low_bound(F))
#define H5F_HIGH_BOUND(F) (H5F_get_high_bound(F))
+#define H5F_SHARED_INTENT(F_SH) (H5F_shared_get_intent(F_SH))
#define H5F_INTENT(F) (H5F_get_intent(F))
#define H5F_OPEN_NAME(F) (H5F_get_open_name(F))
#define H5F_ACTUAL_NAME(F) (H5F_get_actual_name(F))
@@ -345,12 +354,13 @@ typedef struct H5F_t H5F_t;
#define H5F_NOPEN_OBJS(F) (H5F_get_nopen_objs(F))
#define H5F_INCR_NOPEN_OBJS(F) (H5F_incr_nopen_objs(F))
#define H5F_DECR_NOPEN_OBJS(F) (H5F_decr_nopen_objs(F))
-#define H5F_FILE_ID(F) (H5F_get_file_id(F))
+#define H5F_ID_EXISTS(F) (H5F_file_id_exists(F))
#define H5F_PARENT(F) (H5F_get_parent(F))
#define H5F_NMOUNTS(F) (H5F_get_nmounts(F))
#define H5F_GET_READ_ATTEMPTS(F) (H5F_get_read_attempts(F))
#define H5F_DRIVER_ID(F) (H5F_get_driver_id(F))
#define H5F_GET_FILENO(F,FILENUM) (H5F_get_fileno((F), &(FILENUM)))
+#define H5F_SHARED_HAS_FEATURE(F_SH,FL) (H5F_shared_has_feature(F_SH,FL))
#define H5F_HAS_FEATURE(F,FL) (H5F_has_feature(F,FL))
#define H5F_BASE_ADDR(F) (H5F_get_base_addr(F))
#define H5F_SYM_LEAF_K(F) (H5F_sym_leaf_k(F))
@@ -392,6 +402,10 @@ typedef struct H5F_t H5F_t;
#define H5F_EOA_PRE_FSM_FSALLOC(F) (H5F_get_eoa_pre_fsm_fsalloc(F))
#define H5F_USE_VFD_SWMR(F) (H5F_use_vfd_swmr(F))
#define H5F_VFD_SWMR_MD_EOA(F) (H5F_get_vfd_swmr_md_eoa(F))
+#define H5F_NULL_FSM_ADDR(F) (H5F_get_null_fsm_addr(F))
+#define H5F_GET_MIN_DSET_OHDR(F) (H5F_get_min_dset_ohdr(F))
+#define H5F_SET_MIN_DSET_OHDR(F, V) (H5F_set_min_dset_ohdr((F), (V)))
+#define H5F_VOL_CLS(F) (H5F_get_vol_cls(F))
#endif /* H5F_MODULE */
@@ -483,10 +497,11 @@ typedef struct H5F_t H5F_t;
#define H5F_ACS_SDATA_BLOCK_SIZE_NAME "sdata_block_size" /* Minimum "small data" allocation block size (when aggregating "small" raw data allocations) */
#define H5F_ACS_GARBG_COLCT_REF_NAME "gc_ref" /* Garbage-collect references */
#define H5F_ACS_FILE_DRV_NAME "vfd_info" /* File driver ID & info */
+#define H5F_ACS_VOL_CONN_NAME "vol_connector_info" /* VOL connector ID & info */
#define H5F_ACS_CLOSE_DEGREE_NAME "close_degree" /* File close degree */
#define H5F_ACS_FAMILY_OFFSET_NAME "family_offset" /* Offset position in file for family file driver */
#define H5F_ACS_FAMILY_NEWSIZE_NAME "family_newsize" /* New member size of family driver. (private property only used by h5repart) */
-#define H5F_ACS_FAMILY_TO_SEC2_NAME "family_to_sec2" /* Whether to convert family to sec2 driver. (private property only used by h5repart) */
+#define H5F_ACS_FAMILY_TO_SINGLE_NAME "family_to_single" /* Whether to convert family to a single-file driver. (private property only used by h5repart) */
#define H5F_ACS_MULTI_TYPE_NAME "multi_type" /* Data type in multi file driver */
#define H5F_ACS_LIBVER_LOW_BOUND_NAME "libver_low_bound" /* 'low' bound of library format versions */
#define H5F_ACS_LIBVER_HIGH_BOUND_NAME "libver_high_bound" /* 'high' bound of library format versions */
@@ -503,14 +518,16 @@ typedef struct H5F_t H5F_t;
#define H5F_ACS_USE_MDC_LOGGING_NAME "use_mdc_logging" /* Whether to use metadata cache logging */
#define H5F_ACS_MDC_LOG_LOCATION_NAME "mdc_log_location" /* Name of metadata cache log location */
#define H5F_ACS_START_MDC_LOG_ON_ACCESS_NAME "start_mdc_log_on_access" /* Whether logging starts on file create/open */
-#define H5F_ACS_CORE_WRITE_TRACKING_FLAG_NAME "core_write_tracking_flag" /* Whether or not core VFD backing store write tracking is enabled */
#define H5F_ACS_EVICT_ON_CLOSE_FLAG_NAME "evict_on_close_flag" /* Whether or not the metadata cache will evict objects on close */
-#define H5F_ACS_CORE_WRITE_TRACKING_PAGE_SIZE_NAME "core_write_tracking_page_size" /* The page size in kiB when core VFD write tracking is enabled */
#define H5F_ACS_COLL_MD_WRITE_FLAG_NAME "collective_metadata_write" /* property indicating whether metadata writes are done collectively or not */
#define H5F_ACS_META_CACHE_INIT_IMAGE_CONFIG_NAME "mdc_initCacheImageCfg" /* Initial metadata cache image creation configuration */
#define H5F_ACS_PAGE_BUFFER_SIZE_NAME "page_buffer_size" /* the maximum size for the page buffer cache */
#define H5F_ACS_PAGE_BUFFER_MIN_META_PERC_NAME "page_buffer_min_meta_perc" /* the min metadata percentage for the page buffer cache */
#define H5F_ACS_PAGE_BUFFER_MIN_RAW_PERC_NAME "page_buffer_min_raw_perc" /* the min raw data percentage for the page buffer cache */
+#ifdef H5_HAVE_PARALLEL
+#define H5F_ACS_MPI_PARAMS_COMM_NAME "mpi_params_comm" /* the MPI communicator */
+#define H5F_ACS_MPI_PARAMS_INFO_NAME "mpi_params_info" /* the MPI info struct */
+#endif /* H5_HAVE_PARALLEL */
/* Default configuration for VFD SWMR: not configured */
#define H5F_ACS_VFD_SWMR_CONFIG_NAME "vfd_swmr_config"
@@ -592,10 +609,12 @@ typedef struct H5F_t H5F_t;
#define H5F_SDATA_BLOCK_SIZE_DEF 2048
/* Check for file using paged aggregation */
+#define H5F_SHARED_PAGED_AGGR(F_SH) ((F_SH)->fs_strategy == H5F_FSPACE_STRATEGY_PAGE && (F_SH)->fs_page_size)
#define H5F_PAGED_AGGR(F) (F->shared->fs_strategy == H5F_FSPACE_STRATEGY_PAGE && F->shared->fs_page_size)
/* Check for file configured with VFD SWMR */
-#define H5F_VFD_SWMR_CONFIG(F) (F->shared->vfd_swmr_config.version >= H5F__CURR_VFD_SWMR_CONFIG_VERSION)
+#define H5F_SHARED_VFD_SWMR_CONFIG(S) (S->vfd_swmr_config.version >= H5F__CURR_VFD_SWMR_CONFIG_VERSION)
+#define H5F_VFD_SWMR_CONFIG(F) H5F_SHARED_VFD_SWMR_CONFIG(F->shared)
/* Metadata read attempt values */
#define H5F_METADATA_READ_ATTEMPTS 1 /* Default # of read attempts for non-SWMR access */
@@ -671,7 +690,7 @@ struct H5P_genplist_t;
/* Forward declarations for anonymous H5F objects */
/* Main file structures */
-typedef struct H5F_file_t H5F_file_t;
+typedef struct H5F_shared_t H5F_shared_t;
/* Block aggregation structure */
typedef struct H5F_blk_aggr_t H5F_blk_aggr_t;
@@ -720,8 +739,9 @@ typedef enum H5F_mem_page_t {
/* Type of prefix for opening prefixed files */
typedef enum H5F_prefix_open_t {
- H5F_PREFIX_VDS, /* Virtual dataset prefix */
- H5F_PREFIX_ELINK /* External link prefix */
+ H5F_PREFIX_VDS = 0, /* Virtual dataset prefix */
+ H5F_PREFIX_ELINK = 1, /* External link prefix */
+ H5F_PREFIX_EFILE = 2 /* External file prefix */
} H5F_prefix_open_t;
@@ -737,31 +757,35 @@ typedef enum H5F_prefix_open_t {
/* Private functions */
H5_DLL H5F_t *H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id);
H5_DLL herr_t H5F_try_close(H5F_t *f, hbool_t *was_closed/*out*/);
+H5_DLL hid_t H5F_get_file_id(hid_t obj_id, H5I_type_t id_type, hbool_t app_ref);
/* Functions that retrieve values from the file struct */
H5_DLL H5F_libver_t H5F_get_low_bound(const H5F_t *f);
H5_DLL H5F_libver_t H5F_get_high_bound(const H5F_t *f);
+H5_DLL unsigned H5F_shared_get_intent(const H5F_shared_t *f);
H5_DLL unsigned H5F_get_intent(const H5F_t *f);
H5_DLL char *H5F_get_open_name(const H5F_t *f);
H5_DLL char *H5F_get_actual_name(const H5F_t *f);
H5_DLL char *H5F_get_extpath(const H5F_t *f);
-H5_DLL H5F_file_t *H5F_get_shared(const H5F_t *f);
+H5_DLL H5F_shared_t *H5F_get_shared(const H5F_t *f);
H5_DLL hbool_t H5F_same_shared(const H5F_t *f1, const H5F_t *f2);
H5_DLL unsigned H5F_get_nopen_objs(const H5F_t *f);
H5_DLL unsigned H5F_incr_nopen_objs(H5F_t *f);
H5_DLL unsigned H5F_decr_nopen_objs(H5F_t *f);
-H5_DLL hid_t H5F_get_file_id(const H5F_t *f);
+H5_DLL hbool_t H5F_file_id_exists(const H5F_t *f);
H5_DLL H5F_t *H5F_get_parent(const H5F_t *f);
H5_DLL unsigned H5F_get_nmounts(const H5F_t *f);
H5_DLL unsigned H5F_get_read_attempts(const H5F_t *f);
H5_DLL hid_t H5F_get_access_plist(H5F_t *f, hbool_t app_ref);
-H5_DLL hid_t H5F_get_id(H5F_t *file, hbool_t app_ref);
+H5_DLL hid_t H5F_get_id(H5F_t *file);
H5_DLL herr_t H5F_get_obj_count(const H5F_t *f, unsigned types, hbool_t app_ref, size_t *obj_id_count_ptr);
H5_DLL herr_t H5F_get_obj_ids(const H5F_t *f, unsigned types, size_t max_objs, hid_t *oid_list, hbool_t app_ref, size_t *obj_id_count_ptr);
H5_DLL hsize_t H5F_get_pgend_meta_thres(const H5F_t *f);
H5_DLL hbool_t H5F_get_point_of_no_return(const H5F_t *f);
-H5_DLL hbool_t H5F_get_first_alloc_dealloc(const H5F_t *f);
-H5_DLL haddr_t H5F_get_eoa_pre_fsm_fsalloc(const H5F_t *f);
+H5_DLL hbool_t H5F_get_null_fsm_addr(const H5F_t *f);
+H5_DLL hbool_t H5F_get_min_dset_ohdr(const H5F_t *f);
+H5_DLL herr_t H5F_set_min_dset_ohdr(H5F_t *f, hbool_t minimize);
+H5_DLL const H5VL_class_t *H5F_get_vol_cls(const H5F_t *f);
/* Functions than retrieve values set/cached from the superblock/FCPL */
H5_DLL haddr_t H5F_get_base_addr(const H5F_t *f);
@@ -803,7 +827,9 @@ H5_DLL char *H5F_mdc_log_location(const H5F_t *f);
/* Functions that retrieve values from VFD layer */
H5_DLL hid_t H5F_get_driver_id(const H5F_t *f);
H5_DLL herr_t H5F_get_fileno(const H5F_t *f, unsigned long *filenum);
+H5_DLL hbool_t H5F_shared_has_feature(const H5F_shared_t *f, unsigned feature);
H5_DLL hbool_t H5F_has_feature(const H5F_t *f, unsigned feature);
+H5_DLL haddr_t H5F_shared_get_eoa(const H5F_shared_t *f_sh, H5FD_mem_t type);
H5_DLL haddr_t H5F_get_eoa(const H5F_t *f, H5FD_mem_t type);
H5_DLL herr_t H5F_get_vfd_handle(const H5F_t *file, hid_t fapl, void **file_handle);
@@ -814,7 +840,9 @@ H5_DLL herr_t H5F_traverse_mount(struct H5O_loc_t *oloc/*in,out*/);
H5_DLL herr_t H5F_flush_mounts(H5F_t *f);
/* Functions that operate on blocks of bytes wrt super block */
+H5_DLL herr_t H5F_shared_block_read(H5F_shared_t *f_sh, H5FD_mem_t type, haddr_t addr, size_t size, void *buf/*out*/);
H5_DLL herr_t H5F_block_read(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size, void *buf/*out*/);
+H5_DLL herr_t H5F_shared_block_write(H5F_shared_t *f_sh, H5FD_mem_t type, haddr_t addr, size_t size, const void *buf);
H5_DLL herr_t H5F_block_write(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size, const void *buf);
/* Functions that flush or evict */
@@ -854,9 +882,12 @@ H5_DLL herr_t H5F_eoa_dirty(H5F_t *f);
H5_DLL herr_t H5F_get_mpi_handle(const H5F_t *f, MPI_File **f_handle);
H5_DLL int H5F_mpi_get_rank(const H5F_t *f);
H5_DLL MPI_Comm H5F_mpi_get_comm(const H5F_t *f);
+H5_DLL int H5F_shared_mpi_get_size(const H5F_shared_t *f_sh);
H5_DLL int H5F_mpi_get_size(const H5F_t *f);
H5_DLL herr_t H5F_mpi_retrieve_comm(hid_t loc_id, hid_t acspl_id, MPI_Comm *mpi_comm);
H5_DLL herr_t H5F_get_mpi_info(const H5F_t *f, MPI_Info **f_info);
+H5_DLL herr_t H5F_get_mpi_atomicity(H5F_t *file, hbool_t *flag);
+H5_DLL herr_t H5F_set_mpi_atomicity(H5F_t *file, hbool_t flag);
#endif /* H5_HAVE_PARALLEL */
/* External file cache routines */
@@ -870,7 +901,7 @@ H5_DLL H5F_t *H5F_prefix_open_file(H5F_t *primary_file, H5F_prefix_open_t prefix
H5_DLL herr_t H5F_cwfs_add(H5F_t *f, struct H5HG_heap_t *heap);
H5_DLL herr_t H5F_cwfs_find_free_heap(H5F_t *f, size_t need, haddr_t *addr);
H5_DLL herr_t H5F_cwfs_advance_heap(H5F_t *f, struct H5HG_heap_t *heap, hbool_t add_heap);
-H5_DLL herr_t H5F_cwfs_remove_heap(H5F_file_t *shared, struct H5HG_heap_t *heap);
+H5_DLL herr_t H5F_cwfs_remove_heap(H5F_shared_t *shared, struct H5HG_heap_t *heap);
/* Debugging functions */
H5_DLL herr_t H5F_debug(H5F_t *f, FILE * stream, int indent, int fwidth);
diff --git a/src/H5Fpublic.h b/src/H5Fpublic.h
index 26ffc1e..a24a2c0 100644
--- a/src/H5Fpublic.h
+++ b/src/H5Fpublic.h
@@ -47,13 +47,13 @@
* We're assuming that these constants are used rather early in the hdf5
* session.
*/
-#define H5F_ACC_RDONLY (H5CHECK H5OPEN 0x0000u) /*absence of rdwr => rd-only */
-#define H5F_ACC_RDWR (H5CHECK H5OPEN 0x0001u) /*open for read and write */
-#define H5F_ACC_TRUNC (H5CHECK H5OPEN 0x0002u) /*overwrite existing files */
-#define H5F_ACC_EXCL (H5CHECK H5OPEN 0x0004u) /*fail if file already exists*/
+#define H5F_ACC_RDONLY (H5CHECK H5OPEN 0x0000u) /*absence of rdwr => rd-only */
+#define H5F_ACC_RDWR (H5CHECK H5OPEN 0x0001u) /*open for read and write */
+#define H5F_ACC_TRUNC (H5CHECK H5OPEN 0x0002u) /*overwrite existing files */
+#define H5F_ACC_EXCL (H5CHECK H5OPEN 0x0004u) /*fail if file already exists*/
/* NOTE: 0x0008u was H5F_ACC_DEBUG, now deprecated */
-#define H5F_ACC_CREAT (H5CHECK H5OPEN 0x0010u) /*create non-existing files */
-#define H5F_ACC_SWMR_WRITE (H5CHECK 0x0020u) /*indicate that this file is
+#define H5F_ACC_CREAT (H5CHECK H5OPEN 0x0010u) /*create non-existing files */
+#define H5F_ACC_SWMR_WRITE (H5CHECK 0x0020u) /*indicate that this file is
* open for writing in a
* single-writer/multi-reader (SWMR)
* scenario. Note that the
@@ -62,7 +62,7 @@
* with RDONLY access, and use
* the special "SWMR_READ" access
* flag. */
-#define H5F_ACC_SWMR_READ (H5CHECK 0x0040u) /*indicate that this file is
+#define H5F_ACC_SWMR_READ (H5CHECK 0x0040u) /*indicate that this file is
* open for reading in a
* single-writer/multi-reader (SWMR)
* scenario. Note that the
@@ -73,15 +73,15 @@
/* Value passed to H5Pset_elink_acc_flags to cause flags to be taken from the
* parent file. */
-#define H5F_ACC_DEFAULT (H5CHECK H5OPEN 0xffffu) /*ignore setting on lapl */
+#define H5F_ACC_DEFAULT (H5CHECK H5OPEN 0xffffu) /*ignore setting on lapl */
/* Flags for H5Fget_obj_count() & H5Fget_obj_ids() calls */
-#define H5F_OBJ_FILE (0x0001u) /* File objects */
-#define H5F_OBJ_DATASET (0x0002u) /* Dataset objects */
-#define H5F_OBJ_GROUP (0x0004u) /* Group objects */
+#define H5F_OBJ_FILE (0x0001u) /* File objects */
+#define H5F_OBJ_DATASET (0x0002u) /* Dataset objects */
+#define H5F_OBJ_GROUP (0x0004u) /* Group objects */
#define H5F_OBJ_DATATYPE (0x0008u) /* Named datatype objects */
#define H5F_OBJ_ATTR (0x0010u) /* Attribute objects */
-#define H5F_OBJ_ALL (H5F_OBJ_FILE|H5F_OBJ_DATASET|H5F_OBJ_GROUP|H5F_OBJ_DATATYPE|H5F_OBJ_ATTR)
+#define H5F_OBJ_ALL (H5F_OBJ_FILE|H5F_OBJ_DATASET|H5F_OBJ_GROUP|H5F_OBJ_DATATYPE|H5F_OBJ_ATTR)
#define H5F_OBJ_LOCAL (0x0020u) /* Restrict search to objects opened through current file ID */
/* (as opposed to objects opened through any file ID accessing this file) */
@@ -99,20 +99,20 @@
/* The difference between a single file and a set of mounted files */
typedef enum H5F_scope_t {
- H5F_SCOPE_LOCAL = 0, /*specified file handle only */
- H5F_SCOPE_GLOBAL = 1 /*entire virtual file */
+ H5F_SCOPE_LOCAL = 0, /*specified file handle only */
+ H5F_SCOPE_GLOBAL = 1 /*entire virtual file */
} H5F_scope_t;
/* Unlimited file size for H5Pset_external() */
-#define H5F_UNLIMITED ((hsize_t)(-1L))
+#define H5F_UNLIMITED ((hsize_t)(-1L))
/* How does file close behave?
* H5F_CLOSE_DEFAULT - Use the degree pre-defined by underlining VFL
* H5F_CLOSE_WEAK - file closes only after all opened objects are closed
* H5F_CLOSE_SEMI - if no opened objects, file is close; otherwise, file
- close fails
+ close fails
* H5F_CLOSE_STRONG - if there are opened objects, close them first, then
- close file
+ close file
*/
typedef enum H5F_close_degree_t {
H5F_CLOSE_DEFAULT = 0,
@@ -124,19 +124,19 @@ typedef enum H5F_close_degree_t {
/* Current "global" information about file */
typedef struct H5F_info2_t {
struct {
- unsigned version; /* Superblock version # */
- hsize_t super_size; /* Superblock size */
- hsize_t super_ext_size; /* Superblock extension size */
+ unsigned version; /* Superblock version # */
+ hsize_t super_size; /* Superblock size */
+ hsize_t super_ext_size; /* Superblock extension size */
} super;
struct {
- unsigned version; /* Version # of file free space management */
- hsize_t meta_size; /* Free space manager metadata size */
- hsize_t tot_space; /* Amount of free space in the file */
+ unsigned version; /* Version # of file free space management */
+ hsize_t meta_size; /* Free space manager metadata size */
+ hsize_t tot_space; /* Amount of free space in the file */
} free;
struct {
- unsigned version; /* Version # of shared object header info */
- hsize_t hdr_size; /* Shared object header message header size */
- H5_ih_info_t msgs_info; /* Shared object header message index & heap size */
+ unsigned version; /* Version # of shared object header info */
+ hsize_t hdr_size; /* Shared object header message header size */
+ H5_ih_info_t msgs_info; /* Shared object header message index & heap size */
} sohm;
} H5F_info2_t;
@@ -178,11 +178,13 @@ typedef enum H5F_libver_t {
H5F_LIBVER_ERROR = -1,
H5F_LIBVER_EARLIEST = 0, /* Use the earliest possible format for storing objects */
H5F_LIBVER_V18 = 1, /* Use the latest v18 format for storing objects */
- H5F_LIBVER_V110 = 2, /* Use the latest v10 format for storing objects */
+ H5F_LIBVER_V110 = 2, /* Use the latest v110 format for storing objects */
+ H5F_LIBVER_V112 = 3, /* Use the latest v112 format for storing objects */
+ H5F_LIBVER_V114 = 4, /* Use the latest v114 format for storing objects */
H5F_LIBVER_NBOUNDS
} H5F_libver_t;
-#define H5F_LIBVER_LATEST H5F_LIBVER_V110
+#define H5F_LIBVER_LATEST H5F_LIBVER_V114
/* File space handling strategy */
typedef enum H5F_fspace_strategy_t {
@@ -199,16 +201,16 @@ typedef enum H5F_fspace_strategy_t {
typedef enum H5F_file_space_type_t {
H5F_FILE_SPACE_DEFAULT = 0, /* Default (or current) free space strategy setting */
H5F_FILE_SPACE_ALL_PERSIST = 1, /* Persistent free space managers, aggregators, virtual file driver */
- H5F_FILE_SPACE_ALL = 2, /* Non-persistent free space managers, aggregators, virtual file driver */
- /* This is the library default */
+ H5F_FILE_SPACE_ALL = 2, /* Non-persistent free space managers, aggregators, virtual file driver */
+ /* This is the library default */
H5F_FILE_SPACE_AGGR_VFD = 3, /* Aggregators, Virtual file driver */
- H5F_FILE_SPACE_VFD = 4, /* Virtual file driver */
- H5F_FILE_SPACE_NTYPES /* must be last */
+ H5F_FILE_SPACE_VFD = 4, /* Virtual file driver */
+ H5F_FILE_SPACE_NTYPES /* must be last */
} H5F_file_space_type_t;
/* Data structure to report the collection of read retries for metadata items with checksum */
/* Used by public routine H5Fget_metadata_read_retry_info() */
-#define H5F_NUM_METADATA_READ_RETRY_TYPES 21
+#define H5F_NUM_METADATA_READ_RETRY_TYPES 21
typedef struct H5F_retry_info_t {
unsigned nbins;
uint32_t *retries[H5F_NUM_METADATA_READ_RETRY_TYPES];
@@ -297,8 +299,8 @@ typedef herr_t (*H5F_flush_cb_t)(hid_t object_id, void *udata);
*/
typedef struct H5F_vfd_swmr_config_t {
int32_t version;
- int32_t tick_len;
- int32_t max_lag;
+ uint32_t tick_len;
+ uint32_t max_lag;
hbool_t writer;
hbool_t flush_raw_data;
int32_t md_pages_reserved;
@@ -307,22 +309,26 @@ typedef struct H5F_vfd_swmr_config_t {
char log_file_path[H5F__MAX_VFD_SWMR_FILE_NAME_LEN + 1];
} H5F_vfd_swmr_config_t;
+/*********************/
+/* Public Prototypes */
+/*********************/
#ifdef __cplusplus
extern "C" {
#endif
-/* Functions in H5F.c */
-H5_DLL htri_t H5Fis_hdf5(const char *filename);
+H5_DLL htri_t H5Fis_accessible(const char *container_name, hid_t fapl_id);
H5_DLL hid_t H5Fcreate(const char *filename, unsigned flags,
- hid_t create_plist, hid_t access_plist);
+ hid_t create_plist, hid_t access_plist);
H5_DLL hid_t H5Fopen(const char *filename, unsigned flags,
- hid_t access_plist);
+ hid_t access_plist);
H5_DLL hid_t H5Freopen(hid_t file_id);
H5_DLL herr_t H5Fflush(hid_t object_id, H5F_scope_t scope);
H5_DLL herr_t H5Fclose(hid_t file_id);
+H5_DLL herr_t H5Fdelete(const char *filename, hid_t fapl_id);
H5_DLL hid_t H5Fget_create_plist(hid_t file_id);
H5_DLL hid_t H5Fget_access_plist(hid_t file_id);
-H5_DLL herr_t H5Fget_intent(hid_t file_id, unsigned * intent);
+H5_DLL herr_t H5Fget_intent(hid_t file_id, unsigned *intent);
+H5_DLL herr_t H5Fget_fileno(hid_t file_id, unsigned long *fileno);
H5_DLL ssize_t H5Fget_obj_count(hid_t file_id, unsigned types);
H5_DLL ssize_t H5Fget_obj_ids(hid_t file_id, unsigned types, size_t max_objs, hid_t *obj_id_list);
H5_DLL herr_t H5Fget_vfd_handle(hid_t file_id, hid_t fapl, void **file_handle);
@@ -334,9 +340,9 @@ H5_DLL herr_t H5Fget_eoa(hid_t file_id, haddr_t *eoa);
H5_DLL herr_t H5Fincrement_filesize(hid_t file_id, hsize_t increment);
H5_DLL ssize_t H5Fget_file_image(hid_t file_id, void * buf_ptr, size_t buf_len);
H5_DLL herr_t H5Fget_mdc_config(hid_t file_id,
- H5AC_cache_config_t * config_ptr);
+ H5AC_cache_config_t * config_ptr);
H5_DLL herr_t H5Fset_mdc_config(hid_t file_id,
- H5AC_cache_config_t * config_ptr);
+ H5AC_cache_config_t * config_ptr);
H5_DLL herr_t H5Fget_mdc_hit_rate(hid_t file_id, double * hit_rate_ptr);
H5_DLL herr_t H5Fget_mdc_size(hid_t file_id,
size_t * max_size_ptr,
@@ -362,6 +368,8 @@ H5_DLL herr_t H5Freset_page_buffering_stats(hid_t file_id);
H5_DLL herr_t H5Fget_page_buffering_stats(hid_t file_id, unsigned accesses[2],
unsigned hits[2], unsigned misses[2], unsigned evictions[2], unsigned bypasses[2]);
H5_DLL herr_t H5Fget_mdc_image_info(hid_t file_id, haddr_t *image_addr, hsize_t *image_size);
+H5_DLL herr_t H5Fget_dset_no_attrs_hint(hid_t file_id, hbool_t *minimize);
+H5_DLL herr_t H5Fset_dset_no_attrs_hint(hid_t file_id, hbool_t minimize);
/* VFD SWMR */
H5_DLL herr_t H5Fvfd_swmr_end_tick(hid_t file_id);
@@ -378,16 +386,16 @@ H5_DLL herr_t H5Fget_mpi_atomicity(hid_t file_id, hbool_t *flag);
#ifndef H5_NO_DEPRECATED_SYMBOLS
/* Macros */
-#define H5F_ACC_DEBUG (H5CHECK H5OPEN 0x0000u) /*print debug info (deprecated)*/
+#define H5F_ACC_DEBUG (H5CHECK H5OPEN 0x0000u) /*print debug info (deprecated)*/
/* Typedefs */
/* Current "global" information about file */
typedef struct H5F_info1_t {
- hsize_t super_ext_size; /* Superblock extension size */
+ hsize_t super_ext_size; /* Superblock extension size */
struct {
- hsize_t hdr_size; /* Shared object header message header size */
- H5_ih_info_t msgs_info; /* Shared object header message index & heap size */
+ hsize_t hdr_size; /* Shared object header message header size */
+ H5_ih_info_t msgs_info; /* Shared object header message index & heap size */
} sohm;
} H5F_info1_t;
@@ -395,6 +403,7 @@ typedef struct H5F_info1_t {
/* Function prototypes */
H5_DLL herr_t H5Fget_info1(hid_t obj_id, H5F_info1_t *finfo);
H5_DLL herr_t H5Fset_latest_format(hid_t file_id, hbool_t latest_format);
+H5_DLL htri_t H5Fis_hdf5(const char *filename);
#endif /* H5_NO_DEPRECATED_SYMBOLS */
diff --git a/src/H5Fquery.c b/src/H5Fquery.c
index 1dadd15..cae9429 100644
--- a/src/H5Fquery.c
+++ b/src/H5Fquery.c
@@ -75,6 +75,28 @@
/*-------------------------------------------------------------------------
+ * Function: H5F_shared_get_intent
+ *
+ * Purpose: Quick and dirty routine to retrieve the file's 'intent' flags
+ * (Mainly added to stop non-file routines from poking about in the
+ * H5F_shared_t data structure)
+ *
+ * Return: 'intent' on success/abort on failure (shouldn't fail)
+ *-------------------------------------------------------------------------
+ */
+unsigned
+H5F_shared_get_intent(const H5F_shared_t *f_sh)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ HDassert(f_sh);
+
+ FUNC_LEAVE_NOAPI(f_sh->flags)
+} /* end H5F_shared_get_intent() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5F_get_intent
*
* Purpose: Quick and dirty routine to retrieve the file's 'intent' flags
@@ -207,9 +229,9 @@ H5F_get_extpath(const H5F_t *f)
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(f);
- HDassert(f->extpath);
+ HDassert(f->shared->extpath);
- FUNC_LEAVE_NOAPI(f->extpath)
+ FUNC_LEAVE_NOAPI(f->shared->extpath)
} /* end H5F_get_extpath() */
@@ -221,7 +243,7 @@ H5F_get_extpath(const H5F_t *f)
* Return: 'shared' on success/abort on failure (shouldn't fail)
*-------------------------------------------------------------------------
*/
-H5F_file_t *
+H5F_shared_t *
H5F_get_shared(const H5F_t *f)
{
/* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
@@ -277,23 +299,23 @@ H5F_get_nopen_objs(const H5F_t *f)
/*-------------------------------------------------------------------------
- * Function: H5F_get_file_id
+ * Function: H5F_file_id_exists
*
- * Purpose: Retrieve the file's 'file_id' value
+ * Purpose: Determines if a file ID exists for this file struct
*
- * Return: 'file_id' on success/abort on failure (shouldn't fail)
+ * Return: TRUE/FALSE
*-------------------------------------------------------------------------
*/
-hid_t
-H5F_get_file_id(const H5F_t *f)
+hbool_t
+H5F_file_id_exists(const H5F_t *f)
{
/* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(f);
- FUNC_LEAVE_NOAPI(f->file_id)
-} /* end H5F_get_file_id() */
+ FUNC_LEAVE_NOAPI(f->id_exists)
+} /* end H5F_file_id_exists() */
/*-------------------------------------------------------------------------
@@ -514,6 +536,25 @@ H5F_sym_leaf_k(const H5F_t *f)
/*-------------------------------------------------------------------------
+ * Function: H5F_get_min_dset_ohdr
+ *
+ * Purpose: Get the setting flag for minimized dataset object headers
+ *
+ * Return: TRUE/FALSE as set in file
+ *-------------------------------------------------------------------------
+ */
+hbool_t
+H5F_get_min_dset_ohdr(const H5F_t *f)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ HDassert(f);
+
+ FUNC_LEAVE_NOAPI(f->shared->crt_dset_min_ohdr_flag)
+} /* end H5F_get_min_dset_ohdr */
+
+
+/*-------------------------------------------------------------------------
* Function: H5F_Kvalue
*
* Purpose: Replaced a macro to retrieve a B-tree key value for a certain
@@ -808,6 +849,27 @@ H5F_store_msg_crt_idx(const H5F_t *f)
/*-------------------------------------------------------------------------
+ * Function: H5F_shared_has_feature
+ *
+ * Purpose: Check if a file has a particular feature enabled
+ *
+ * Return: Success: Non-negative - TRUE or FALSE
+ * Failure: Negative (should not happen)
+ *-------------------------------------------------------------------------
+ */
+hbool_t
+H5F_shared_has_feature(const H5F_shared_t *f_sh, unsigned feature)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ HDassert(f_sh);
+
+ FUNC_LEAVE_NOAPI((hbool_t)(f_sh->lf->feature_flags & feature))
+} /* end H5F_shared_has_feature() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5F_has_feature
*
* Purpose: Check if a file has a particular feature enabled
@@ -885,6 +947,32 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5F_shared_get_eoa
+ *
+ * Purpose: Quick and dirty routine to retrieve the file's 'eoa' value
+ *
+ * Return: Non-negative on success/Negative on failure
+ *-------------------------------------------------------------------------
+ */
+haddr_t
+H5F_shared_get_eoa(const H5F_shared_t *f_sh, H5FD_mem_t type)
+{
+ haddr_t ret_value = HADDR_UNDEF; /* Return value */
+
+ FUNC_ENTER_NOAPI(HADDR_UNDEF)
+
+ HDassert(f_sh);
+
+ /* Dispatch to driver */
+ if(HADDR_UNDEF == (ret_value = H5FD_get_eoa(f_sh->lf, type)))
+ HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF, "driver get_eoa request failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_shared_get_eoa() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5F_get_eoa
*
* Purpose: Quick and dirty routine to retrieve the file's 'eoa' value
@@ -904,7 +992,7 @@ H5F_get_eoa(const H5F_t *f, H5FD_mem_t type)
/* Dispatch to driver */
if(HADDR_UNDEF == (ret_value = H5FD_get_eoa(f->shared->lf, type)))
- HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF, "driver get_eoa request failed")
+ HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF, "driver get_eoa request failed")
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -1007,7 +1095,7 @@ H5F_coll_md_read(const H5F_t *f)
HDassert(f);
- FUNC_LEAVE_NOAPI(f->coll_md_read)
+ FUNC_LEAVE_NOAPI(f->shared->coll_md_read)
} /* end H5F_coll_md_read() */
#endif /* H5_HAVE_PARALLEL */
@@ -1171,18 +1259,17 @@ H5F_get_point_of_no_return(const H5F_t *f)
FUNC_LEAVE_NOAPI(f->shared->point_of_no_return)
} /* end H5F_get_point_of_no_return() */
-
/*-------------------------------------------------------------------------
- * Function: H5F_get_first_alloc_dealloc
+ * Function: H5F_get_null_fsm_addr
*
- * Purpose: Retrieve the 'first alloc / dealloc' value for the file.
+ * Purpose: Retrieve the 'null_fsm_addr' value for the file.
*
- * Return: Success: Non-negative, the 'first_alloc_dealloc'
+ * Return: Success: Non-negative, the 'null_fsm_addr'
* Failure: (can't happen)
*-------------------------------------------------------------------------
*/
hbool_t
-H5F_get_first_alloc_dealloc(const H5F_t *f)
+H5F_get_null_fsm_addr(const H5F_t *f)
{
/* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
FUNC_ENTER_NOAPI_NOINIT_NOERR
@@ -1190,30 +1277,70 @@ H5F_get_first_alloc_dealloc(const H5F_t *f)
HDassert(f);
HDassert(f->shared);
- FUNC_LEAVE_NOAPI(f->shared->first_alloc_dealloc)
-} /* end H5F_get_first_alloc_dealloc() */
+ FUNC_LEAVE_NOAPI(f->shared->null_fsm_addr)
+} /* end H5F_get_null_fsm_addr() */
/*-------------------------------------------------------------------------
- * Function: H5F_get_eoa_pre_fsm_fsalloc
+ * Function: H5F_get_vol_cls
*
- * Purpose: Retrieve the 'EOA pre-FSM fsalloc' value for the file.
+ * Purpose: Get the VOL class for the file
+ *
+ * Return: VOL class pointer for file, can't fail
+ *
+ * Programmer: Quincey Koziol
+ * Saturday, August 17, 2019
*
- * Return: Success: Non-negative, the 'EOA pre-FSM fsalloc'
- * Failure: (can't happen)
*-------------------------------------------------------------------------
*/
-haddr_t
-H5F_get_eoa_pre_fsm_fsalloc(const H5F_t *f)
+const H5VL_class_t *
+H5F_get_vol_cls(const H5F_t *f)
{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(f);
HDassert(f->shared);
- FUNC_LEAVE_NOAPI(f->shared->eoa_pre_fsm_fsalloc)
-} /* end H5F_get_eoa_pre_fsm_fsalloc() */
+ FUNC_LEAVE_NOAPI(f->shared->vol_cls)
+} /* end H5F_get_vol_cls */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_get_cont_info
+ *
+ * Purpose: Get the VOL container info for the file
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Saturday, August 17, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F__get_cont_info(const H5F_t *f, H5VL_file_cont_info_t *info)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Sanity checks */
+ HDassert(f);
+ HDassert(f->shared);
+
+ /* Verify structure version */
+ if(info->version != H5VL_CONTAINER_INFO_VERSION)
+ HGOTO_ERROR(H5E_FILE, H5E_VERSION, FAIL, "wrong container info version #")
+
+ /* Set the container info fields */
+ info->feature_flags = 0; /* None currently defined */
+ info->token_size = H5F_SIZEOF_ADDR(f);
+ info->blob_id_size = H5HG_HEAP_ID_SIZE(f);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_get_cont_info */
/*-------------------------------------------------------------------------
diff --git a/src/H5Fsfile.c b/src/H5Fsfile.c
index ebc2ab2..9a9bbab 100644
--- a/src/H5Fsfile.c
+++ b/src/H5Fsfile.c
@@ -24,7 +24,7 @@
/* Struct for tracking "shared" file structs */
typedef struct H5F_sfile_node_t {
- H5F_file_t *shared; /* Pointer to "shared" file struct */
+ H5F_shared_t *shared; /* Pointer to "shared" file struct */
struct H5F_sfile_node_t *next; /* Pointer to next node */
} H5F_sfile_node_t;
@@ -96,9 +96,9 @@ H5F_sfile_assert_num(unsigned n)
*-------------------------------------------------------------------------
*/
herr_t
-H5F__sfile_add(H5F_file_t *shared)
+H5F__sfile_add(H5F_shared_t *shared)
{
- H5F_sfile_node_t *new_shared; /* New shared file node */
+ H5F_sfile_node_t *new_shared; /* New shared file node */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
@@ -135,11 +135,11 @@ done:
*
*-------------------------------------------------------------------------
*/
-H5F_file_t *
+H5F_shared_t *
H5F__sfile_search(H5FD_t *lf)
{
H5F_sfile_node_t *curr; /* Current shared file node */
- H5F_file_t *ret_value = NULL; /* Return value */
+ H5F_shared_t *ret_value = NULL; /* Return value */
FUNC_ENTER_PACKAGE_NOERR
@@ -175,7 +175,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5F__sfile_remove(H5F_file_t *shared)
+H5F__sfile_remove(H5F_shared_t *shared)
{
H5F_sfile_node_t *curr; /* Current shared file node */
H5F_sfile_node_t *last; /* Last shared file node */
diff --git a/src/H5Fsuper.c b/src/H5Fsuper.c
index 489cc21..f8e8f3f 100644
--- a/src/H5Fsuper.c
+++ b/src/H5Fsuper.c
@@ -76,10 +76,12 @@ H5FL_DEFINE(H5F_super_t);
static const unsigned HDF5_superblock_ver_bounds[] = {
HDF5_SUPERBLOCK_VERSION_DEF, /* H5F_LIBVER_EARLIEST */
HDF5_SUPERBLOCK_VERSION_2, /* H5F_LIBVER_V18 */
+ HDF5_SUPERBLOCK_VERSION_3, /* H5F_LIBVER_V110 */
+ HDF5_SUPERBLOCK_VERSION_3, /* H5F_LIBVER_V112 */
HDF5_SUPERBLOCK_VERSION_LATEST /* H5F_LIBVER_LATEST */
};
-
+
/*-------------------------------------------------------------------------
* Function: H5F__super_ext_create
*
@@ -132,7 +134,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5F__super_ext_create() */
-
+
/*-------------------------------------------------------------------------
* Function: H5F__super_ext_open
*
@@ -170,7 +172,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5F__super_ext_open() */
-
+
/*-------------------------------------------------------------------------
* Function: H5F__super_ext_close
*
@@ -223,14 +225,14 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5F__super_ext_close() */
-
+
/*-------------------------------------------------------------------------
* Function: H5F__update_super_ext_driver_msg
*
- * Purpose: Update the superblock extension file driver info message if
+ * Purpose: Update the superblock extension file driver info message if
* we are using a V 2 superblock. Observe that the function
* is a NO-OP if the file driver info message does not exist.
- * This is necessary, as the function is called whenever the
+ * This is necessary, as the function is called whenever the
* EOA is updated, and were it to create the file driver info
* message, it would find itself in an infinite recursion.
*
@@ -270,8 +272,8 @@ H5F__update_super_ext_driver_msg(H5F_t *f)
/* Check for driver info */
H5_CHECKED_ASSIGN(driver_size, size_t, H5FD_sb_size(f->shared->lf), hsize_t);
- /* Nothing to do unless there is both driver info and
- * the driver info superblock extension message has
+ /* Nothing to do unless there is both driver info and
+ * the driver info superblock extension message has
* already been created.
*/
if(driver_size > 0) {
@@ -287,7 +289,7 @@ H5F__update_super_ext_driver_msg(H5F_t *f)
/* Write the message to the superblock extension.
*
- * Note that the superblock extension and the
+ * Note that the superblock extension and the
* file driver info message must already exist.
*/
drvinfo.len = driver_size;
@@ -303,7 +305,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5F__update_super_ext_driver_msg() */
-
+
/*-------------------------------------------------------------------------
* Function: H5F__super_read
*
@@ -342,7 +344,7 @@ H5F__super_read(H5F_t *f, H5P_genplist_t *fa_plist, hbool_t initial_read)
FUNC_ENTER_PACKAGE_TAG(H5AC__SUPERBLOCK_TAG)
/* initialize the drvinfo to NULL -- we will overwrite this if there
- * is a driver information block
+ * is a driver information block
*/
f->shared->drvinfo = NULL;
@@ -434,7 +436,7 @@ H5F__super_read(H5F_t *f, H5P_genplist_t *fa_plist, hbool_t initial_read)
HGOTO_ERROR(H5E_FILE, H5E_BADTYPE, FAIL, "can't get property list")
/* Make certain we can read the fixed-size portion of the superblock */
- if(H5F__set_eoa(f, H5FD_MEM_SUPER,
+ if(H5F__set_eoa(f, H5FD_MEM_SUPER,
(haddr_t)(H5F_SUPERBLOCK_FIXED_SIZE + H5F_SUPERBLOCK_MINIMAL_VARLEN_SIZE)) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "set end of space allocation request failed")
@@ -454,12 +456,12 @@ H5F__super_read(H5F_t *f, H5P_genplist_t *fa_plist, hbool_t initial_read)
if(NULL == (sblock = (H5F_super_t *)H5AC_protect(f, H5AC_SUPERBLOCK, (haddr_t)0, &udata, rw_flags)))
HGOTO_ERROR(H5E_FILE, H5E_CANTPROTECT, FAIL, "unable to load superblock")
- /*
+ /*
* When opening a file with SWMR-write access, the library will first
- * check to ensure that superblock version 3 is used. Otherwise fail
+ * check to ensure that superblock version 3 is used. Otherwise fail
* file open.
*
- * Then the library will upgrade the file's low_bound depending on
+ * Then the library will upgrade the file's low_bound depending on
* superblock version as follows:
* --version 0 or 1: no change to low_bound
* --version 2: upgrade low_bound to at least V18
@@ -512,15 +514,12 @@ H5F__super_read(H5F_t *f, H5P_genplist_t *fa_plist, hbool_t initial_read)
#endif /* H5_HAVE_PARALLEL */
/* Check if superblock address is different from base address and adjust
- * base address and "end of address" address if so.
+ * base address and "end of file" address if so.
*/
if(!H5F_addr_eq(super_addr, sblock->base_addr)) {
- /* Check if the superblock moved earlier in the file */
- if(H5F_addr_lt(super_addr, sblock->base_addr))
- udata.stored_eof -= (sblock->base_addr - super_addr);
- else
- /* The superblock moved later in the file */
- udata.stored_eof += (super_addr - sblock->base_addr);
+ /* If the superblock moved in the file, adjust the EOF */
+ /* (Handles moving earlier & later) */
+ udata.stored_eof -= (sblock->base_addr - super_addr);
/* Adjust base address for offsets of the HDF5 data in the file */
sblock->base_addr = super_addr;
@@ -555,7 +554,7 @@ H5F__super_read(H5F_t *f, H5P_genplist_t *fa_plist, hbool_t initial_read)
/* Set the B-tree internal node values, etc */
if(H5P_set(c_plist, H5F_CRT_BTREE_RANK_NAME, udata.btree_k) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to set rank for btree internal nodes")
- HDmemcpy(sblock->btree_k, udata.btree_k, sizeof(unsigned) * (size_t)H5B_NUM_BTREE_ID);
+ H5MM_memcpy(sblock->btree_k, udata.btree_k, sizeof(unsigned) * (size_t)H5B_NUM_BTREE_ID);
} /* end if */
else {
/* Get the (default) B-tree internal node values, etc */
@@ -592,8 +591,8 @@ H5F__super_read(H5F_t *f, H5P_genplist_t *fa_plist, hbool_t initial_read)
* as the file can appear truncated if only part of it has been
* been flushed to disk by the SWMR writer process.
*/
- /* The EOF check is also skipped when the private property
- * H5F_ACS_SKIP_EOF_CHECK_NAME exists in the fapl.
+ /* The EOF check is also skipped when the private property
+ * H5F_ACS_SKIP_EOF_CHECK_NAME exists in the fapl.
* This property is enabled by the tool h5clear with these
* two options: (1) --filesize (2) --increment
*/
@@ -604,7 +603,7 @@ H5F__super_read(H5F_t *f, H5P_genplist_t *fa_plist, hbool_t initial_read)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get skip EOF check value")
if(H5F_INTENT(f) & H5F_ACC_SWMR_READ) {
- /*
+ /*
* When the file is opened for SWMR read access, skip the check if:
* --the file is already marked for SWMR writing and
* --the file has version 3 superblock for SWMR support
@@ -646,10 +645,10 @@ H5F__super_read(H5F_t *f, H5P_genplist_t *fa_plist, hbool_t initial_read)
drvrinfo_udata.f = f;
drvrinfo_udata.driver_addr = sblock->driver_addr;
- /* extend EOA so we can read at least the fixed sized
- * portion of the driver info block
+ /* extend EOA so we can read at least the fixed sized
+ * portion of the driver info block
*/
- if(H5FD_set_eoa(f->shared->lf, H5FD_MEM_SUPER, sblock->driver_addr + H5F_DRVINFOBLOCK_HDR_SIZE) < 0) /* will extend eoa later if required */
+ if(H5FD_set_eoa(f->shared->lf, H5FD_MEM_SUPER, sblock->driver_addr + H5F_DRVINFOBLOCK_HDR_SIZE) < 0) /* will extend eoa later if required */
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "set end of space allocation request failed")
/* Look up the driver info block */
@@ -662,7 +661,7 @@ H5F__super_read(H5F_t *f, H5P_genplist_t *fa_plist, hbool_t initial_read)
if(((rw_flags & H5AC__READ_ONLY_FLAG) == 0) && H5F_HAS_FEATURE(f, H5FD_FEAT_DIRTY_DRVRINFO_LOAD))
drvinfo_flags |= H5AC__DIRTIED_FLAG;
- /* set the pin entry flag so that the driver information block
+ /* set the pin entry flag so that the driver information block
* cache entry will be pinned in the cache.
*/
drvinfo_flags |= H5AC__PIN_ENTRY_FLAG;
@@ -770,20 +769,26 @@ H5F__super_read(H5F_t *f, H5P_genplist_t *fa_plist, hbool_t initial_read)
/* If message is NOT marked "unknown"--set up file space info */
if(!(flags & H5O_MSG_FLAG_WAS_UNKNOWN)) {
H5O_fsinfo_t fsinfo; /* File space info message from superblock extension */
- hbool_t null_fsm_addr = FALSE; /* Whether to drop free-space to the floor */
+ /* f->shared->null_fsm_addr: Whether to drop free-space to the floor */
/* The h5clear tool uses this property to tell the library
* to drop free-space to the floor
*/
if(H5P_exist_plist(fa_plist, H5F_ACS_NULL_FSM_ADDR_NAME) > 0)
- if(H5P_get(fa_plist, H5F_ACS_NULL_FSM_ADDR_NAME, &null_fsm_addr) < 0)
+ if(H5P_get(fa_plist, H5F_ACS_NULL_FSM_ADDR_NAME, &f->shared->null_fsm_addr) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get clearance for persisting fsm addr")
/* Retrieve the 'file space info' structure */
if(NULL == H5O_msg_read(&ext_loc, H5O_FSINFO_ID, &fsinfo))
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get free-space manager info message")
+ /* Version bounds check */
+ if(H5O_fsinfo_check_version(H5F_HIGH_BOUND(f), &fsinfo) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, FAIL, "File space info message's version out of bounds")
+
/* Update changed values */
+ if(f->shared->fs_version != fsinfo.version)
+ f->shared->fs_version = fsinfo.version;
if(f->shared->fs_strategy != fsinfo.strategy) {
f->shared->fs_strategy = fsinfo.strategy;
@@ -819,59 +824,66 @@ H5F__super_read(H5F_t *f, H5P_genplist_t *fa_plist, hbool_t initial_read)
/* Initialize page end meta threshold */
f->shared->pgend_meta_thres = fsinfo.pgend_meta_thres;
- if(f->shared->eoa_pre_fsm_fsalloc != fsinfo.eoa_pre_fsm_fsalloc)
- f->shared->eoa_pre_fsm_fsalloc = fsinfo.eoa_pre_fsm_fsalloc;
+ if(f->shared->eoa_fsm_fsalloc != fsinfo.eoa_pre_fsm_fsalloc)
+ f->shared->eoa_fsm_fsalloc = fsinfo.eoa_pre_fsm_fsalloc;
- /* f->shared->eoa_pre_fsm_fsalloc must always be HADDR_UNDEF
- * in the absence of persistent free space managers.
- */
- /* If the following two conditions are true:
+ /*
+ * If the following two conditions are true:
* (1) skipping EOF check (skip_eof_check)
- * (2) dropping free-space to the floor (null_fsm_addr)
- * skip the asserts as "eoa_pre_fsm_fsalloc" may be undefined
+ * (2) dropping free-space to the floor (f->shared->null_fsm_addr)
+ * skip the asserts as "eoa_fsm_fsalloc" may be undefined
* for a crashed file with persistent free space managers.
- * #1 and #2 are enabled when the tool h5clear --increment
+ * The above two conditions are enabled when the tool h5clear --increment
* option is used.
*/
- if(!skip_eof_check && !null_fsm_addr) {
- HDassert((!f->shared->fs_persist) || (f->shared->eoa_pre_fsm_fsalloc != HADDR_UNDEF));
- HDassert(!f->shared->first_alloc_dealloc);
- }
-
- /* As "eoa_pre_fsm_fsalloc" may be undefined for a crashed file
- * with persistent free space managers, therefore, set
- * "first_alloc_dealloc" when the condition
- * "dropping free-space to the floor is true.
- * This will ensure that no action is done to settle things on file
- * close via H5MF_settle_meta_data_fsm() and H5MF_settle_raw_data_fsm().
+ if(!skip_eof_check && !f->shared->null_fsm_addr)
+ HDassert((!f->shared->fs_persist) || (f->shared->eoa_fsm_fsalloc != HADDR_UNDEF));
+
+ /*
+ * A crashed file with persistent free-space managers may have
+ * undefined f->shared->eoa_fsm_fsalloc.
+ * eoa_fsm_fsalloc is the final eoa which is saved in the free-space
+ * info message's eoa_pre_fsm_fsalloc field for backward compatibility.
+ * If the tool h5clear sets to dropping free-space to the floor
+ * as indicated by f->shared->null_fsm_addr, we are not going to
+ * perform actions to settle things on file close in the routines
+ * H5MF_settle_meta_data_fsm() and H5MF_settle_raw_data_fsm().
+ *
+ * We remove the following check:
+ * if((f->shared->eoa_pre_fsm_fsalloc != HADDR_UNDEF || null_fsm_addr) &&
+ * (H5F_INTENT(f) & H5F_ACC_RDWR))
+ * f->shared->first_alloc_dealloc = TRUE;
+ *
+ * Because:
+ * --there is no more f->shared->eoa_pre_fsm_fsalloc and
+ * f->shared->first_alloc_dealloc
+ * --the check for null_fsm_addr is directly done in H5MF_settle_meta_data_fsm()
+ * and H5MF_settle_raw_data_fsm()
*/
- if((f->shared->eoa_pre_fsm_fsalloc != HADDR_UNDEF || null_fsm_addr) &&
- (H5F_INTENT(f) & H5F_ACC_RDWR))
- f->shared->first_alloc_dealloc = TRUE;
f->shared->fs_addr[0] = HADDR_UNDEF;
for(u = 1; u < NELMTS(f->shared->fs_addr); u++)
f->shared->fs_addr[u] = fsinfo.fs_addr[u - 1];
/* If the following two conditions are true:
- * (1) file is persisting free-space
- * (2) dropping free-space to the floor (null_fsm_addr)
- * nullify the addresses of the FSMs
+ * (1) file is persisting free-space
+ * (2) dropping free-space to the floor (f->shared->null_fsm_addr)
+ * nullify the addresses of the FSMs
*/
- if(f->shared->fs_persist && null_fsm_addr)
+ if(f->shared->fs_persist && f->shared->null_fsm_addr)
for(u = 0; u < NELMTS(fsinfo.fs_addr); u++)
f->shared->fs_addr[u] = fsinfo.fs_addr[u] = HADDR_UNDEF;
/* For fsinfo.mapped: remove the FSINFO message from the superblock extension
and write a new message to the extension */
- /* For null_fsm_addr: just update FSINFO message in the superblock extension */
- if(((fsinfo.mapped || null_fsm_addr) && (rw_flags & H5AC__READ_ONLY_FLAG) == 0)) {
+ /* For f->shared->null_fsm_addr: just update FSINFO message in the superblock extension */
+ if(((fsinfo.mapped || f->shared->null_fsm_addr) && (rw_flags & H5AC__READ_ONLY_FLAG) == 0)) {
/* Do the same kluge until we know for sure. VC */
#if 1 /* bug fix test code -- tidy this up if all goes well */ /* JRM */
/* KLUGE ALERT!!
*
- * H5F__super_ext_write_msg() expects f->shared->sblock to
+ * H5F__super_ext_write_msg() expects f->shared->sblock to
* be set -- verify that it is NULL, and then set it.
* Set it back to NULL when we are done.
*/
@@ -879,7 +891,7 @@ H5F__super_read(H5F_t *f, H5P_genplist_t *fa_plist, hbool_t initial_read)
f->shared->sblock = sblock;
#endif /* JRM */
- if(null_fsm_addr) {
+ if(f->shared->null_fsm_addr) {
if(H5F__super_ext_write_msg(f, H5O_FSINFO_ID, &fsinfo, FALSE, H5O_MSG_FLAG_MARK_IF_UNKNOWN) < 0)
HGOTO_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "error in writing fsinfo message to superblock extension")
}
@@ -908,12 +920,12 @@ H5F__super_read(H5F_t *f, H5P_genplist_t *fa_plist, hbool_t initial_read)
/* if the metadata cache image superblock extension message exists,
* read its contents and pass the data on to the metadata cache.
* Given this data, the cache will load and decode the metadata
- * cache image block, decoded it and load its contents into the
- * the cache on the test protect call.
+ * cache image block, decoded it and load its contents into the
+ * the cache on the test protect call.
*
- * Further, if the file is opened R/W, the metadata cache will
+ * Further, if the file is opened R/W, the metadata cache will
* delete the metadata cache image superblock extension and free
- * the cache image block. Don't do this now as f->shared
+ * the cache image block. Don't do this now as f->shared
* is not fully setup, which complicates matters.
*/
@@ -964,7 +976,7 @@ H5F__super_read(H5F_t *f, H5P_genplist_t *fa_plist, hbool_t initial_read)
#if 1 /* bug fix test code -- tidy this up if all goes well */ /* JRM */
/* KLUGE ALERT!!
*
- * H5F__super_ext_write_msg() expects f->shared->sblock to
+ * H5F__super_ext_write_msg() expects f->shared->sblock to
* be set -- verify that it is NULL, and then set it.
* Set it back to NULL when we are done.
*/
@@ -1008,10 +1020,10 @@ done:
if(sblock && H5AC_unprotect(f, H5AC_SUPERBLOCK, (haddr_t)0, sblock, sblock_flags) < 0)
HDONE_ERROR(H5E_FILE, H5E_CANTUNPROTECT, FAIL, "unable to close superblock")
- /* If we have failed, make sure no entries are left in the
+ /* If we have failed, make sure no entries are left in the
* metadata cache, so that it can be shut down and discarded.
*/
- if(ret_value < 0) {
+ if(ret_value < 0) {
/* Unpin and discard drvinfo cache entry */
if(f->shared->drvinfo) {
if(H5AC_unpin_entry(f->shared->drvinfo) < 0)
@@ -1037,7 +1049,7 @@ done:
FUNC_LEAVE_NOAPI_TAG(ret_value)
} /* end H5F__super_read() */
-
+
/*-------------------------------------------------------------------------
* Function: H5F__super_init
*
@@ -1101,10 +1113,10 @@ H5F__super_init(H5F_t *f)
if(!(f->shared->fs_strategy == H5F_FILE_SPACE_STRATEGY_DEF &&
f->shared->fs_persist == H5F_FREE_SPACE_PERSIST_DEF &&
f->shared->fs_threshold == H5F_FREE_SPACE_THRESHOLD_DEF &&
- f->shared->fs_page_size == H5F_FILE_SPACE_PAGE_SIZE_DEF))
+ f->shared->fs_page_size == H5F_FILE_SPACE_PAGE_SIZE_DEF))
non_default_fs_settings = TRUE;
- /*
+ /*
* When creating a file with write access, the library will:
* -- set superblock version to 0, 1 or 2 based on feature enabled
* -- no change to low_bound
@@ -1113,9 +1125,9 @@ H5F__super_init(H5F_t *f)
* -- set superblock version to 3
* -- upgrade low_bound to at least V110
*
- * Then the library will finalize superblock version to that allowed by
+ * Then the library will finalize superblock version to that allowed by
* low_bound if that is higher.
- * Lastly, the library will check to ensure the superblock version does not
+ * Lastly, the library will check to ensure the superblock version does not
* exceed the version allowed by high_bound. Otherwise fail file open.
*
* For details, please see RFC:Setting Bounds for Object Creation in HDF5 1.10.0.
@@ -1125,12 +1137,12 @@ H5F__super_init(H5F_t *f)
* the status_flags field in the superblock. The problem is discussed in
* jira issue SWMR-79 and also in the RFC: File Format Changes in HDF5 1.10.0.
* The file's low_bound is upgraded for SWMR so that the library will
- * use the best format versions available in 1.10.
- * Due to the possible upgrade, the fapl returned from H5Fget_access_plist()
+ * use the best format versions available in 1.10.
+ * Due to the possible upgrade, the fapl returned from H5Fget_access_plist()
* might indicate a low_bound higher than what the user originally set.
*/
- /*
+ /*
* Creating a file with SWMR-write access will
* upgrade superblock version and low_bound
*/
@@ -1141,10 +1153,10 @@ H5F__super_init(H5F_t *f)
/* Bump superblock version to create superblock extension for SOHM info */
} else if(f->shared->sohm_nindexes > 0)
super_vers = HDF5_SUPERBLOCK_VERSION_2;
- /*
- * Bump superblock version to create superblock extension for:
- * -- non-default file space strategy or
- * -- non-default persisting free-space or
+ /*
+ * Bump superblock version to create superblock extension for:
+ * -- non-default file space strategy or
+ * -- non-default persisting free-space or
* -- non-default free-space threshold or
* -- non-default page_size
*/
@@ -1221,7 +1233,7 @@ H5F__super_init(H5F_t *f)
/* Compute the size of the driver information block */
H5_CHECKED_ASSIGN(driver_size, size_t, H5FD_sb_size(f->shared->lf), hsize_t);
- /* The following code sets driver_size to the valued needed
+ /* The following code sets driver_size to the valued needed
* for the driver info block, and sets the driver info block
* address regardless of the version of the superblock.
*/
@@ -1262,7 +1274,7 @@ H5F__super_init(H5F_t *f)
/* Allocate space for the superblock */
if(HADDR_UNDEF == H5MF_alloc(f, H5FD_MEM_SUPER, superblock_size))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for superblock")
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for superblock")
/* set the drvinfo filed to NULL -- will overwrite this later if needed */
f->shared->drvinfo = NULL;
@@ -1313,7 +1325,7 @@ H5F__super_init(H5F_t *f)
* be tuned if more information is added to the superblock
* extension.
*/
- if(H5F__super_ext_create(f, &ext_loc) < 0)
+ if(H5F__super_ext_create(f, &ext_loc) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTCREATE, FAIL, "unable to create superblock extension")
ext_created = TRUE;
@@ -1377,12 +1389,17 @@ H5F__super_init(H5F_t *f)
fsinfo.eoa_pre_fsm_fsalloc = HADDR_UNDEF;
fsinfo.mapped = FALSE;
+ /* Set the version for the fsinfo message */
+ if(H5O_fsinfo_set_version(H5F_LOW_BOUND(f), H5F_HIGH_BOUND(f), &fsinfo) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set version of fsinfo")
+ f->shared->fs_version = fsinfo.version;
+
for(ptype = H5F_MEM_PAGE_SUPER; ptype < H5F_MEM_PAGE_NTYPES; H5_INC_ENUM(H5F_mem_page_t, ptype))
fsinfo.fs_addr[ptype - 1] = HADDR_UNDEF;
if(H5O_msg_create(&ext_loc, H5O_FSINFO_ID, H5O_MSG_FLAG_DONTSHARE | H5O_MSG_FLAG_MARK_IF_UNKNOWN, H5O_UPDATE_TIME, &fsinfo) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to update free-space info header message")
- } /* end if */
+ } /* end if */
} /* end if */
else {
/* Check for creating an "old-style" driver info block */
@@ -1465,7 +1482,7 @@ done:
FUNC_LEAVE_NOAPI_TAG(ret_value)
} /* end H5F__super_init() */
-
+
/*-------------------------------------------------------------------------
* Function: H5F_eoa_dirty
*
@@ -1495,8 +1512,8 @@ H5F_eoa_dirty(H5F_t *f)
if(H5F_super_dirty(f) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTMARKDIRTY, FAIL, "unable to mark superblock as dirty")
- /* If the driver information block exists, mark it dirty as well
- * so that the change in eoa will be reflected there as well if
+ /* If the driver information block exists, mark it dirty as well
+ * so that the change in eoa will be reflected there as well if
* appropriate.
*/
if(f->shared->drvinfo) {
@@ -1513,7 +1530,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5F_eoa_dirty() */
-
+
/*-------------------------------------------------------------------------
* Function: H5F_super_dirty
*
@@ -1547,7 +1564,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5F_super_dirty() */
-
+
/*-------------------------------------------------------------------------
* Function: H5F__super_free
*
@@ -1578,7 +1595,7 @@ H5F__super_free(H5F_super_t *sblock)
FUNC_LEAVE_NOAPI(SUCCEED)
} /* H5F__super_free() */
-
+
/*-------------------------------------------------------------------------
* Function: H5F__super_size
*
@@ -1607,7 +1624,7 @@ H5F__super_size(H5F_t *f, hsize_t *super_size, hsize_t *super_ext_size)
/* Set the superblock size */
if(super_size)
- *super_size = (hsize_t)H5F_SUPERBLOCK_SIZE(f->shared->sblock);
+ *super_size = (hsize_t)H5F_SUPERBLOCK_SIZE(f->shared->sblock);
/* Set the superblock extension size */
if(super_ext_size) {
@@ -1643,7 +1660,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5F__super_size() */
-
+
/*-------------------------------------------------------------------------
* Function: H5F__super_ext_write_msg()
*
@@ -1662,9 +1679,9 @@ H5F__super_ext_write_msg(H5F_t *f, unsigned id, void *mesg,
H5AC_ring_t orig_ring = H5AC_RING_INV; /* Original ring value */
hbool_t ext_created = FALSE; /* Whether superblock extension was created */
hbool_t ext_opened = FALSE; /* Whether superblock extension was opened */
- H5O_loc_t ext_loc; /* "Object location" for superblock extension */
- htri_t status; /* Indicate whether the message exists or not */
- herr_t ret_value = SUCCEED; /* Return value */
+ H5O_loc_t ext_loc; /* "Object location" for superblock extension */
+ htri_t status; /* Indicate whether the message exists or not */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
@@ -1728,7 +1745,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5F__super_ext_write_msg() */
-
+
/*-------------------------------------------------------------------------
* Function: H5F__super_ext_remove_msg
*
@@ -1744,11 +1761,11 @@ herr_t
H5F__super_ext_remove_msg(H5F_t *f, unsigned id)
{
H5AC_ring_t orig_ring = H5AC_RING_INV; /* Original ring value */
- H5O_loc_t ext_loc; /* "Object location" for superblock extension */
+ H5O_loc_t ext_loc; /* "Object location" for superblock extension */
hbool_t ext_opened = FALSE; /* Whether the superblock extension was opened */
- int null_count = 0; /* # of null messages */
+ int null_count = 0; /* # of null messages */
htri_t status; /* Indicate whether the message exists or not */
- herr_t ret_value = SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
@@ -1768,7 +1785,7 @@ H5F__super_ext_remove_msg(H5F_t *f, unsigned id)
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to check object header for message")
else if(status) {
/* message exists */
- H5O_hdr_info_t hdr_info; /* Object header info for superblock extension */
+ H5O_hdr_info_t hdr_info; /* Object header info for superblock extension */
/* Remove the message */
if(H5O_msg_remove(&ext_loc, id, H5O_ALL, TRUE) < 0)
diff --git a/src/H5Fsuper_cache.c b/src/H5Fsuper_cache.c
index a17fcc0..cf22ba7 100644
--- a/src/H5Fsuper_cache.c
+++ b/src/H5Fsuper_cache.c
@@ -273,7 +273,7 @@ H5F__drvrinfo_prefix_decode(H5O_drvinfo_t *drvrinfo, char *drv_name,
/* Driver name and/or version */
if(drv_name) {
- HDmemcpy(drv_name, (const char *)image, (size_t)8);
+ H5MM_memcpy(drv_name, (const char *)image, (size_t)8);
drv_name[8] = '\0';
image += 8; /* advance past name/version */
} /* end if */
@@ -686,7 +686,7 @@ H5F__cache_superblock_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_UNU
HDassert(sblock->cache_info.flush_me_last);
/* Encode the common portion of the file superblock for all versions */
- HDmemcpy(image, H5F_SIGNATURE, (size_t)H5F_SIGNATURE_LEN);
+ H5MM_memcpy(image, H5F_SIGNATURE, (size_t)H5F_SIGNATURE_LEN);
image += H5F_SIGNATURE_LEN;
*image++ = (uint8_t)sblock->super_vers;
@@ -1229,8 +1229,12 @@ H5F__cache_superblock_refresh(H5F_t *f, void * _thing, const void * _image,
HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "unexpected snode_btree_k")
/* File status flags (not really used yet) */
+ /* If the file has closed, the status flags will be zero.
+ * Allow this.
+ */
UINT32DECODE(image, status_flags);
- if ( status_flags != sblock->status_flags )
+ if ( ( status_flags != sblock->status_flags ) &&
+ ( status_flags != 0 ) )
HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "unexpected status_flags")
/*
@@ -1300,7 +1304,12 @@ H5F__cache_superblock_refresh(H5F_t *f, void * _thing, const void * _image,
/* File status flags (not really used yet) */
status_flags = *image++;
- if ( status_flags != sblock->status_flags )
+
+ /* If the file has closed, the status flags will be zero.
+ * Allow this.
+ */
+ if ( ( status_flags != sblock->status_flags ) &&
+ ( status_flags != 0 ) )
HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "unexpected status_flags")
/* Base, superblock extension, end of file & root group object
diff --git a/src/H5Ftest.c b/src/H5Ftest.c
index c148912..66c91d6 100644
--- a/src/H5Ftest.c
+++ b/src/H5Ftest.c
@@ -46,6 +46,7 @@
#include "H5Iprivate.h" /* IDs */
#include "H5SMpkg.h" /* Shared object header messages */
#include "H5MMprivate.h" /* Memory management */
+#include "H5VLprivate.h" /* Virtual Object Layer */
/****************/
@@ -112,7 +113,7 @@ H5F__get_sohm_mesg_count_test(hid_t file_id, unsigned type_id, size_t *mesg_coun
FUNC_ENTER_PACKAGE
/* Check arguments */
- if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ if(NULL == (file = (H5F_t *)H5VL_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file")
/* Push API context */
@@ -157,7 +158,7 @@ H5F__check_cached_stab_test(hid_t file_id)
FUNC_ENTER_PACKAGE
/* Check arguments */
- if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ if(NULL == (file = (H5F_t *)H5VL_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file")
/* Push API context */
@@ -198,7 +199,7 @@ H5F__get_maxaddr_test(hid_t file_id, haddr_t *maxaddr)
FUNC_ENTER_PACKAGE
/* Check arguments */
- if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ if(NULL == (file = (H5F_t *)H5VL_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file")
/* Retrieve maxaddr for file */
@@ -231,7 +232,7 @@ H5F__get_sbe_addr_test(hid_t file_id, haddr_t *sbe_addr)
FUNC_ENTER_PACKAGE
/* Check arguments */
- if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ if(NULL == (file = (H5F_t *)H5VL_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file")
/* Retrieve maxaddr for file */
@@ -241,7 +242,6 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5F__get_sbe_addr_test() */
-
/*
* VFD SWMR tests
*/
@@ -280,7 +280,7 @@ H5F__vfd_swmr_writer_create_open_flush_test(hid_t file_id, hbool_t file_create)
FUNC_ENTER_PACKAGE
/* Check arguments */
- if(NULL == (f = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ if(NULL == (f = (H5F_t *)H5VL_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file")
/* Open the metadata file */
@@ -557,7 +557,7 @@ H5F__vfd_swmr_writer_md_test(hid_t file_id, unsigned num_entries, H5FD_vfd_swmr_
HDmemset(&md_idx, 0, sizeof(H5FD_vfd_swmr_md_index));
/* Check arguments */
- if(NULL == (f = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ if(NULL == (f = (H5F_t *)H5VL_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file")
/* Update the metadata file with the input index */
@@ -592,3 +592,38 @@ done:
}
FUNC_LEAVE_NOAPI(ret_value)
} /* H5F__vfd_swmr_writer_md_test() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F__same_file_test
+ *
+ * Purpose: Check if two file IDs refer to the same underlying file.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * Oct 13, 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5F__same_file_test(hid_t file_id1, hid_t file_id2)
+{
+ H5F_t *file1, *file2; /* File info */
+ htri_t ret_value = FAIL; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Check arguments */
+ if(NULL == (file1 = (H5F_t *)H5VL_object_verify(file_id1, H5I_FILE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file")
+ if(NULL == (file2 = (H5F_t *)H5VL_object_verify(file_id2, H5I_FILE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file")
+
+ /* If they are using the same underlying "shared" file struct, they are the same file */
+ ret_value = (file1->shared == file2->shared);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F__same_file_test() */
+
diff --git a/src/H5Fvfd_swmr.c b/src/H5Fvfd_swmr.c
index b7bb17d..78f0dd6 100644
--- a/src/H5Fvfd_swmr.c
+++ b/src/H5Fvfd_swmr.c
@@ -54,6 +54,9 @@
/* Local Macros */
/****************/
+#define nanosecs_per_second 1000000000 /* nanoseconds per second */
+#define nanosecs_per_tenth_sec 100000000 /* nanoseconds per 0.1 second */
+
/* Remove an entry from the doubly linked list */
#define H5F__LL_REMOVE(entry_ptr, head_ptr, tail_ptr) \
{ \
@@ -221,10 +224,11 @@ H5F_vfd_swmr_init(H5F_t *f, hbool_t file_create)
HDassert(f->shared->vfd_swmr_config.writer);
+ SIMPLEQ_INIT(&f->shared->deferred_frees);
f->shared->vfd_swmr_writer = TRUE;
f->shared->tick_num = 1;
- if ( H5PB_vfd_swmr__set_tick(f) < 0 )
+ if ( H5PB_vfd_swmr__set_tick(f->shared) < 0 )
HGOTO_ERROR(H5E_FILE, H5E_SYSTEM, FAIL, \
"Can't update page buffer current tick")
@@ -392,15 +396,11 @@ H5F_vfd_swmr_close_or_flush(H5F_t *f, hbool_t closing)
"unable to close the free-space manager for the metadata file")
/* Free the delayed list */
- curr = f->shared->dl_head_ptr;
-
- while ( curr != NULL ) {
-
- next = curr->next;
- curr = H5FL_FREE(H5F_vfd_swmr_dl_entry_t, curr);
- curr = next;
-
- } /* end while */
+ for (curr = f->shared->dl_head_ptr;
+ curr != NULL && (next = curr->next, true);
+ curr = next) {
+ H5FL_FREE(H5F_vfd_swmr_dl_entry_t, curr);
+ }
f->shared->dl_head_ptr = f->shared->dl_tail_ptr = NULL;
@@ -546,7 +546,7 @@ H5F_update_vfd_swmr_metadata_file(H5F_t *f, uint32_t num_entries,
"unable to seek in the metadata file")
if ( HDwrite(f->shared->vfd_swmr_md_fd, index[i].entry_ptr,
- index[i].length) != index[i].length )
+ index[i].length) != (ssize_t)index[i].length )
HGOTO_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, \
"error in writing the page/multi-page entry to metadata file")
@@ -579,11 +579,10 @@ H5F_update_vfd_swmr_metadata_file(H5F_t *f, uint32_t num_entries,
*
* --remove the associated entries from the list
*/
- dl_entry = f->shared->dl_tail_ptr;
-
- while ( dl_entry != NULL ) {
-
- prev = dl_entry->prev;
+
+ for (dl_entry = f->shared->dl_tail_ptr;
+ dl_entry != NULL && (prev = dl_entry->prev, true);
+ dl_entry = prev) {
/* max_lag is at least 3 */
if ( ( f->shared->tick_num > f->shared->vfd_swmr_config.max_lag ) &&
@@ -607,10 +606,7 @@ H5F_update_vfd_swmr_metadata_file(H5F_t *f, uint32_t num_entries,
break;
}
-
- dl_entry = prev;
-
- } /* end while */
+ }
done:
@@ -660,85 +656,50 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5F_vfd_swmr_writer__delay_write(H5F_t *f, uint64_t page,
- uint64_t * delay_write_until_ptr)
+H5F_vfd_swmr_writer__delay_write(H5F_shared_t *shared, uint64_t page,
+ uint64_t *untilp)
{
- int32_t top = -1;
- int32_t bottom = 0;
- int32_t probe;
- uint64_t delay_write_until = 0;
+ uint64_t until;
H5FD_vfd_swmr_idx_entry_t * ie_ptr = NULL;
H5FD_vfd_swmr_idx_entry_t * idx = NULL;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
- HDassert(f);
- HDassert(f->shared);
- HDassert(f->shared->vfd_swmr);
- HDassert(f->shared->vfd_swmr_writer);
+ HDassert(shared);
+ HDassert(shared->vfd_swmr);
+ HDassert(shared->vfd_swmr_writer);
- idx = f->shared->mdf_idx;
+ idx = shared->mdf_idx;
- HDassert((idx) ||( f->shared->tick_num <= 1));
+ HDassert(idx != NULL || shared->tick_num <= 1);
/* do a binary search on the metadata file index to see if
- * it already contains an entry for *pbe_ptr.
+ * it already contains an entry for `page`.
*/
- ie_ptr = NULL;
-
- if ( idx ) {
-
- top = f->shared->mdf_idx_entries_used - 1;
- bottom = 0;
- }
-
- while ( top >= bottom ) {
-
- HDassert(idx);
-
- probe = (top + bottom) / 2;
-
- if ( idx[probe].hdf5_page_offset < page ) {
-
- bottom = probe + 1;
-
- } else if ( idx[probe].hdf5_page_offset > page ) {
-
- top = probe - 1;
-
- } else { /* found it */
-
- ie_ptr = idx + probe;
- bottom = top + 1; /* to exit loop */
- }
- }
-
- if ( ie_ptr ) {
-
- if ( ie_ptr->delayed_flush >= f->shared->tick_num ) {
-
- delay_write_until = ie_ptr->delayed_flush;
- }
+ if (idx == NULL) {
+ ie_ptr = NULL;
} else {
-
- delay_write_until = f->shared->tick_num +
- f->shared->vfd_swmr_config.max_lag;
+ ie_ptr = vfd_swmr_pageno_to_mdf_idx_entry(idx,
+ shared->mdf_idx_entries_used, page);
}
- if ( ( delay_write_until != 0 ) &&
- ( ! ( ( delay_write_until >= f->shared->tick_num ) &&
- ( delay_write_until <=
- (f->shared->tick_num + f->shared->vfd_swmr_config.max_lag) )
- )
- )
- )
+ if (ie_ptr == NULL)
+ until = shared->tick_num + shared->vfd_swmr_config.max_lag;
+ else if (ie_ptr->delayed_flush >= shared->tick_num)
+ until = ie_ptr->delayed_flush;
+ else
+ until = 0;
+
+ if (until != 0 &&
+ (until < shared->tick_num ||
+ shared->tick_num + shared->vfd_swmr_config.max_lag < until))
HGOTO_ERROR(H5E_PAGEBUF, H5E_SYSTEM, FAIL, \
"VFD SWMR write delay out of range")
- *delay_write_until_ptr = delay_write_until;
-
+ *untilp = until;
+
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -868,10 +829,10 @@ done:
herr_t
H5F_vfd_swmr_writer_end_of_tick(H5F_t *f)
{
- int32_t idx_entries_added = 0;
- int32_t idx_entries_modified = 0;
- int32_t idx_ent_not_in_tl = 0;
- int32_t idx_ent_not_in_tl_flushed = 0;
+ uint32_t idx_entries_added = 0;
+ uint32_t idx_entries_modified = 0;
+ uint32_t idx_ent_not_in_tl = 0;
+ uint32_t idx_ent_not_in_tl_flushed = 0;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
@@ -953,7 +914,7 @@ H5F_vfd_swmr_writer_end_of_tick(H5F_t *f)
* the metadata file index, adding or modifying entries as
* appropriate.
*/
- if ( H5PB_vfd_swmr__update_index(f, &idx_entries_added,
+ if ( H5PB_vfd_swmr__update_index(f->shared, &idx_entries_added,
&idx_entries_modified,
&idx_ent_not_in_tl,
&idx_ent_not_in_tl_flushed) < 0 )
@@ -1003,13 +964,13 @@ H5F_vfd_swmr_writer_end_of_tick(H5F_t *f)
#endif /* JRM */
/* 7) Release the page buffer tick list. */
- if ( H5PB_vfd_swmr__release_tick_list(f) < 0 )
+ if ( H5PB_vfd_swmr__release_tick_list(f->shared) < 0 )
HGOTO_ERROR(H5E_FILE, H5E_SYSTEM, FAIL, "can't release tick list")
/* 8) Release any delayed writes whose delay has expired */
- if ( H5PB_vfd_swmr__release_delayed_writes(f) < 0 )
+ if ( H5PB_vfd_swmr__release_delayed_writes(f->shared) < 0 )
HGOTO_ERROR(H5E_FILE, H5E_SYSTEM, FAIL, "can't release delayed writes")
@@ -1033,9 +994,9 @@ H5F_vfd_swmr_writer_end_of_tick(H5F_t *f)
HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to insert entry into the EOT queue")
#if 0 /* JRM */
- HDfprintf(stderr, "*** writer EOT %lld exiting. idx len = %d ***\n",
- f->shared->tick_num,
- (int32_t)(f->shared->mdf_idx_entries_used));
+ HDfprintf(stderr,
+ "*** writer EOT %" PRIu64 " exiting. idx len = %" PRIu32 " ***\n",
+ f->shared->tick_num, f->shared->mdf_idx_entries_used);
#endif /* JRM */
done:
@@ -1061,9 +1022,9 @@ done:
herr_t
H5F_vfd_swmr_writer__dump_index(H5F_t * f)
{
- int i;
- int32_t mdf_idx_len;
- int32_t mdf_idx_entries_used;
+ unsigned int i;
+ uint32_t mdf_idx_len;
+ uint32_t mdf_idx_entries_used;
H5FD_vfd_swmr_idx_entry_t * index = NULL;
herr_t ret_value = SUCCEED; /* Return value */
@@ -1080,13 +1041,15 @@ H5F_vfd_swmr_writer__dump_index(H5F_t * f)
mdf_idx_entries_used = f->shared->mdf_idx_entries_used;
HDfprintf(stderr, "\n\nDumping Index:\n\n");
- HDfprintf(stderr, "index len / entries used = %d / %d\n\n",
- mdf_idx_len, mdf_idx_entries_used);
+ HDfprintf(stderr,
+ "index len / entries used = %" PRIu32 " / %" PRIu32 "\n\n",
+ mdf_idx_len, mdf_idx_entries_used);
for ( i = 0; i < mdf_idx_entries_used; i++ ) {
- HDfprintf(stderr, "%d: %lld %lld %d\n", i, index[i].hdf5_page_offset,
- index[i].md_file_page_offset, index[i].length);
+ HDfprintf(stderr, "%u: %" PRIu64 " %" PRIu64 " %" PRIu32 "\n",
+ i, index[i].hdf5_page_offset, index[i].md_file_page_offset,
+ index[i].length);
}
done:
@@ -1141,11 +1104,11 @@ H5F_vfd_swmr_reader_end_of_tick(H5F_t *f)
int pass = 0;
uint64_t tmp_tick_num = 0;
H5FD_vfd_swmr_idx_entry_t * tmp_mdf_idx;
- int32_t entries_added = 0;
- int32_t entries_removed = 0;
- int32_t entries_changed = 0;
- int32_t tmp_mdf_idx_len;
- int32_t tmp_mdf_idx_entries_used;
+ uint32_t entries_added = 0;
+ uint32_t entries_removed = 0;
+ uint32_t entries_changed = 0;
+ uint32_t tmp_mdf_idx_len;
+ uint32_t tmp_mdf_idx_entries_used;
uint32_t mdf_idx_entries_used;
herr_t ret_value = SUCCEED; /* Return value */
@@ -1179,8 +1142,9 @@ H5F_vfd_swmr_reader_end_of_tick(H5F_t *f)
"error in retrieving tick_num from driver")
#if 0 /* JRM */
- HDfprintf(stderr, "--- reader EOT curr/new tick = %lld/%lld ---\n",
- tick_num_g, tmp_tick_num);
+ HDfprintf(stderr,
+ "--- reader EOT curr/new tick = %" PRIu64 "/%" PRIu64 " ---\n",
+ tick_num_g, tmp_tick_num);
#endif /* JRM */
if ( tmp_tick_num != f->shared->tick_num ) {
@@ -1193,7 +1157,7 @@ H5F_vfd_swmr_reader_end_of_tick(H5F_t *f)
f->shared->old_mdf_idx = f->shared->mdf_idx;
f->shared->old_mdf_idx_len = f->shared->mdf_idx_len;
- f->shared->old_mdf_idx_entries_used = (int32_t)f->shared->mdf_idx_entries_used;
+ f->shared->old_mdf_idx_entries_used = f->shared->mdf_idx_entries_used;
f->shared->mdf_idx = tmp_mdf_idx;
f->shared->mdf_idx_len = tmp_mdf_idx_len;
@@ -1207,7 +1171,7 @@ H5F_vfd_swmr_reader_end_of_tick(H5F_t *f)
"unable to allocate metadata file index")
- mdf_idx_entries_used = (uint32_t)(f->shared->mdf_idx_len);
+ mdf_idx_entries_used = f->shared->mdf_idx_len;
#if 0 /* JRM */
HDfprintf(stderr, "--- reader EOT mdf_idx_entries_used = %d ---\n",
@@ -1221,13 +1185,14 @@ H5F_vfd_swmr_reader_end_of_tick(H5F_t *f)
HGOTO_ERROR(H5E_ARGS, H5E_CANTGET, FAIL, \
"error in retrieving tick_num from driver")
- HDassert(mdf_idx_entries_used <= (uint32_t)(f->shared->mdf_idx_len));
+ HDassert(mdf_idx_entries_used <= f->shared->mdf_idx_len);
f->shared->mdf_idx_entries_used = mdf_idx_entries_used;
#if 0 /* JRM */
- HDfprintf(stderr, "--- reader EOT index used / len = %d/%d ---\n",
- f->shared->mdf_idx_entries_used, f->shared->mdf_idx_len);
+ HDfprintf(stderr,
+ "--- reader EOT index used / len = %" PRIu32 "/%" PRIu32 " ---\n",
+ f->shared->mdf_idx_entries_used, f->shared->mdf_idx_len);
#endif /* JRM */
@@ -1244,12 +1209,12 @@ H5F_vfd_swmr_reader_end_of_tick(H5F_t *f)
while ( pass <= 1 ) {
haddr_t page_addr;
- int32_t i = 0;
- int32_t j = 0;
+ uint32_t i = 0;
+ uint32_t j = 0;
H5FD_vfd_swmr_idx_entry_t * new_mdf_idx;
H5FD_vfd_swmr_idx_entry_t * old_mdf_idx;
- int32_t new_mdf_idx_entries_used;
- int32_t old_mdf_idx_entries_used;
+ uint32_t new_mdf_idx_entries_used;
+ uint32_t old_mdf_idx_entries_used;
new_mdf_idx = f->shared->mdf_idx;
new_mdf_idx_entries_used = f->shared->mdf_idx_entries_used;
@@ -1277,7 +1242,7 @@ H5F_vfd_swmr_reader_end_of_tick(H5F_t *f)
(new_mdf_idx[j].hdf5_page_offset *
f->shared->pb_ptr->page_size);
- if ( H5PB_remove_entry(f, page_addr) < 0 )
+ if ( H5PB_remove_entry(f->shared, page_addr) < 0 )
HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, \
"remove page buffer entry failed")
@@ -1313,7 +1278,7 @@ H5F_vfd_swmr_reader_end_of_tick(H5F_t *f)
page_addr = (haddr_t)(old_mdf_idx[i].hdf5_page_offset *
f->shared->pb_ptr->page_size);
- if ( H5PB_remove_entry(f, page_addr) < 0 )
+ if ( H5PB_remove_entry(f->shared, page_addr) < 0 )
HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, \
"remove page buffer entry failed")
@@ -1372,7 +1337,7 @@ H5F_vfd_swmr_reader_end_of_tick(H5F_t *f)
page_addr = (haddr_t)(old_mdf_idx[i].hdf5_page_offset *
f->shared->pb_ptr->page_size);
- if ( H5PB_remove_entry(f, page_addr) < 0 )
+ if ( H5PB_remove_entry(f->shared, page_addr) < 0 )
HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, \
"remove page buffer entry failed")
@@ -1393,9 +1358,9 @@ H5F_vfd_swmr_reader_end_of_tick(H5F_t *f)
} /* while ( pass <= 1 ) */
#if 0 /* JRM */
- HDfprintf(stderr,
- "--- reader EOT pre new tick index used/len = %d/ %d ---\n",
- f->shared->mdf_idx_entries_used, f->shared->mdf_idx_len);
+ HDfprintf(stderr, "--- reader EOT pre new tick index "
+ "used/len = %" PRIu32 "/ %" PRIu32 " ---\n",
+ f->shared->mdf_idx_entries_used, f->shared->mdf_idx_len);
#endif /* JRM */
/* At this point, we should have evicted or refreshed all stale
* page buffer and metadata cache entries.
@@ -1421,13 +1386,16 @@ H5F_vfd_swmr_reader_end_of_tick(H5F_t *f)
HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to insert entry into the EOT queue")
#if 0 /* JRM */
- HDfprintf(stderr, "--- reader EOT final index used / len = %d / %d ---\n",
- f->shared->mdf_idx_entries_used, f->shared->mdf_idx_len);
- HDfprintf(stderr, "--- reader EOT old index used / len = %d / %d ---\n",
- f->shared->old_mdf_idx_entries_used, f->shared->old_mdf_idx_len);
- HDfprintf(stderr, "--- reader EOT %lld exiting t/a/r/c = %d/%d/%d/%d---\n",
- f->shared->tick_num, (int32_t)(f->shared->mdf_idx_entries_used),
- entries_added, entries_removed, entries_changed);
+ HDfprintf(stderr, "--- reader EOT final index "
+ "used / len = %" PRIu32 " / %" PRIu32 " ---\n",
+ f->shared->mdf_idx_entries_used, f->shared->mdf_idx_len);
+ HDfprintf(stderr, "--- reader EOT old index "
+ "used / len = %" PRIu32 " / %" PRIu32 " ---\n",
+ f->shared->old_mdf_idx_entries_used, f->shared->old_mdf_idx_len);
+ HDfprintf(stderr, "--- reader EOT %" PRIu64 " exiting "
+ "t/a/r/c = %" PRIu32 "/%" PRIu32 "/%" PRIu32 "/%" PRIu32 "---\n",
+ f->shared->tick_num, f->shared->mdf_idx_entries_used,
+ entries_added, entries_removed, entries_changed);
#endif /* JRM */
done:
@@ -1458,14 +1426,16 @@ H5F_vfd_swmr_remove_entry_eot(H5F_t *f)
FUNC_ENTER_NOAPI_NOINIT_NOERR
/* Free the entry on the EOT queue that corresponds to f */
- curr = vfd_swmr_eot_queue_head_g;
- while(curr != NULL) {
- if(curr->vfd_swmr_file == f) {
- H5F__LL_REMOVE(curr, vfd_swmr_eot_queue_head_g, vfd_swmr_eot_queue_tail_g)
- curr = H5FL_FREE(H5F_vfd_swmr_eot_queue_entry_t, curr);
+
+ for (curr = vfd_swmr_eot_queue_head_g; curr != NULL; curr = curr->next) {
+ if (curr->vfd_swmr_file == f)
break;
- }
- curr = curr->next;
+ }
+
+ if (curr != NULL) {
+ H5F__LL_REMOVE(curr, vfd_swmr_eot_queue_head_g,
+ vfd_swmr_eot_queue_tail_g)
+ curr = H5FL_FREE(H5F_vfd_swmr_eot_queue_entry_t, curr);
}
if(vfd_swmr_eot_queue_head_g) {
@@ -1502,7 +1472,7 @@ H5F_vfd_swmr_insert_entry_eot(H5F_t *f)
/* Allocate an entry to be inserted onto the EOT queue */
if (NULL == (entry_ptr = H5FL_CALLOC(H5F_vfd_swmr_eot_queue_entry_t)))
- HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "unable to allocate the endo of tick queue entry")
+ HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "unable to allocate the end of tick queue entry")
/* Initialize the entry */
entry_ptr->vfd_swmr_writer = f->shared->vfd_swmr_writer;
@@ -1513,12 +1483,10 @@ H5F_vfd_swmr_insert_entry_eot(H5F_t *f)
entry_ptr->prev = NULL;
/* Found the position to insert the entry on the EOT queue */
- prec_ptr = vfd_swmr_eot_queue_tail_g;
-
- while (prec_ptr) {
- if(timespeccmp(&prec_ptr->end_of_tick, &entry_ptr->end_of_tick, >))
- prec_ptr = prec_ptr->prev;
- else
+ for (prec_ptr = vfd_swmr_eot_queue_tail_g;
+ prec_ptr != NULL;
+ prec_ptr = prec_ptr->prev) {
+ if (timespeccmp(&prec_ptr->end_of_tick, &entry_ptr->end_of_tick, <=))
break;
}
@@ -1554,24 +1522,25 @@ done:
herr_t
H5F_dump_eot_queue(void)
{
- int i = 0;
+ int i;
H5F_vfd_swmr_eot_queue_entry_t *curr;
FUNC_ENTER_NOAPI_NOINIT_NOERR
- if(vfd_swmr_eot_queue_head_g == NULL)
- HDfprintf(stderr, "EOT head is null\n");
-
- curr = vfd_swmr_eot_queue_head_g;
- while(curr != NULL) {
- ++i;
- HDfprintf(stderr, "%d: vfd_swmr_writer=%d tick_num=%lld, end_of_tick:%lld, %lld, vfd_swmr_file=0x%x\n",
- i, curr->vfd_swmr_writer, curr->tick_num,
- curr->end_of_tick.tv_sec, curr->end_of_tick.tv_nsec, curr->vfd_swmr_file);
-
- curr = curr->next;
+ for (i = 0, curr = vfd_swmr_eot_queue_head_g;
+ curr != NULL;
+ curr = curr->next, i++) {
+ HDfprintf(stderr, "%d: %s tick_num %" PRIu64
+ ", end_of_tick %jd.%09ld, vfd_swmr_file %p\n",
+ i, curr->vfd_swmr_writer ? "writer" : "not writer",
+ curr->tick_num,
+ curr->end_of_tick.tv_sec, curr->end_of_tick.tv_nsec,
+ curr->vfd_swmr_file);
}
+ if(i == 0)
+ HDfprintf(stderr, "EOT head is null\n");
+
FUNC_LEAVE_NOAPI(SUCCEED)
} /* H5F_dump_eot_queue() */
@@ -1602,12 +1571,12 @@ H5F__vfd_swmr_update_end_of_tick_and_tick_num(H5F_t *f, hbool_t incr_tick_num)
{
struct timespec curr; /* Current time in struct timespec */
struct timespec new_end_of_tick; /* new end_of_tick in struct timespec */
- long curr_nsecs; /* current time in nanoseconds */
- long tlen_nsecs; /* tick_len in nanoseconds */
+ int64_t curr_nsecs; /* current time in nanoseconds */
+ int64_t tlen_nsecs; /* tick_len in nanoseconds */
#if 0 /* JRM */
- long end_nsecs; /* end_of_tick in nanoseconds */
+ int64_t end_nsecs; /* end_of_tick in nanoseconds */
#endif /* JRM */
- long new_end_nsecs; /* new end_of_tick in nanoseconds */
+ int64_t new_end_nsecs; /* new end_of_tick in nanoseconds */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC
@@ -1619,10 +1588,10 @@ H5F__vfd_swmr_update_end_of_tick_and_tick_num(H5F_t *f, hbool_t incr_tick_num)
"can't get time via clock_gettime")
/* Convert curr to nsecs */
- curr_nsecs = curr.tv_sec * SECOND_TO_NANOSECS + curr.tv_nsec;
+ curr_nsecs = curr.tv_sec * nanosecs_per_second + curr.tv_nsec;
/* Convert tick_len to nanosecs */
- tlen_nsecs = f->shared->vfd_swmr_config.tick_len * TENTH_SEC_TO_NANOSECS;
+ tlen_nsecs = f->shared->vfd_swmr_config.tick_len * nanosecs_per_tenth_sec;
/*
* Update tick_num_g, f->shared->tick_num
@@ -1631,7 +1600,7 @@ H5F__vfd_swmr_update_end_of_tick_and_tick_num(H5F_t *f, hbool_t incr_tick_num)
f->shared->tick_num++;
- if ( H5PB_vfd_swmr__set_tick(f) < 0 )
+ if ( H5PB_vfd_swmr__set_tick(f->shared) < 0 )
HGOTO_ERROR(H5E_FILE, H5E_SYSTEM, FAIL, \
"Can't update page buffer current tick")
@@ -1649,13 +1618,12 @@ H5F__vfd_swmr_update_end_of_tick_and_tick_num(H5F_t *f, hbool_t incr_tick_num)
*/
new_end_nsecs = curr_nsecs + tlen_nsecs;
- new_end_of_tick.tv_nsec = new_end_nsecs % SECOND_TO_NANOSECS;
- new_end_of_tick.tv_sec = new_end_nsecs / SECOND_TO_NANOSECS;
+ new_end_of_tick.tv_nsec = (long)(new_end_nsecs % nanosecs_per_second);
+ new_end_of_tick.tv_sec = new_end_nsecs / nanosecs_per_second;
/* Update end_of_tick */
- HDmemcpy(&end_of_tick_g, &new_end_of_tick, sizeof(struct timespec));
- HDmemcpy(&f->shared->end_of_tick, &new_end_of_tick,
- sizeof(struct timespec));
+ end_of_tick_g = new_end_of_tick;
+ f->shared->end_of_tick = new_end_of_tick;
done:
@@ -1692,7 +1660,9 @@ H5F__vfd_swmr_construct_write_md_hdr(H5F_t *f, uint32_t num_entries)
uint8_t image[H5FD_MD_HEADER_SIZE]; /* Buffer for header */
uint8_t *p = NULL; /* Pointer to buffer */
uint32_t metadata_chksum; /* Computed metadata checksum value */
- unsigned hdr_size = H5FD_MD_HEADER_SIZE; /* Size of header and index */
+ /* Size of header and index */
+ const size_t hdr_size = H5FD_MD_HEADER_SIZE;
+ ssize_t nwritten;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC
@@ -1719,7 +1689,7 @@ H5F__vfd_swmr_construct_write_md_hdr(H5F_t *f, uint32_t num_entries)
UINT32ENCODE(p, metadata_chksum);
/* Sanity checks on header */
- HDassert((size_t)(p - image == hdr_size));
+ HDassert(p - image == (ptrdiff_t)hdr_size);
/* Set to beginning of the file */
if ( HDlseek(f->shared->vfd_swmr_md_fd, (HDoff_t)H5FD_MD_HEADER_OFF, SEEK_SET) < 0 )
@@ -1727,11 +1697,12 @@ H5F__vfd_swmr_construct_write_md_hdr(H5F_t *f, uint32_t num_entries)
HGOTO_ERROR(H5E_VFL, H5E_SEEKERROR, FAIL, \
"unable to seek in metadata file")
+ nwritten = HDwrite(f->shared->vfd_swmr_md_fd, image, hdr_size);
/* Write header to the metadata file */
- if ( HDwrite(f->shared->vfd_swmr_md_fd, image, hdr_size) != hdr_size )
-
+ if (nwritten != (ssize_t)hdr_size) {
HGOTO_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, \
"error in writing header to metadata file")
+ }
done:
@@ -1769,7 +1740,9 @@ H5F__vfd_swmr_construct_write_md_idx(H5F_t *f, uint32_t num_entries,
uint8_t *image = NULL; /* Pointer to buffer */
uint8_t *p = NULL; /* Pointer to buffer */
uint32_t metadata_chksum; /* Computed metadata checksum value */
- unsigned idx_size = H5FD_MD_INDEX_SIZE(num_entries); /* Size of index */
+ /* Size of index */
+ const size_t idx_size = H5FD_MD_INDEX_SIZE(num_entries);
+ ssize_t nwritten;
unsigned i; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
@@ -1814,7 +1787,7 @@ H5F__vfd_swmr_construct_write_md_idx(H5F_t *f, uint32_t num_entries,
UINT32ENCODE(p, metadata_chksum);
/* Sanity checks on index */
- HDassert((size_t)(p - image == idx_size));
+ HDassert(p - image == (ptrdiff_t)idx_size);
/* Verify the md file descriptor exists */
HDassert(f->shared->vfd_swmr_md_fd >= 0);
@@ -1825,12 +1798,13 @@ H5F__vfd_swmr_construct_write_md_idx(H5F_t *f, uint32_t num_entries,
HGOTO_ERROR(H5E_VFL, H5E_SEEKERROR, FAIL, \
"unable to seek in metadata file")
-
+
+ nwritten = HDwrite(f->shared->vfd_swmr_md_fd, image, idx_size);
/* Write index to the metadata file */
- if ( HDwrite(f->shared->vfd_swmr_md_fd, image, idx_size) != idx_size )
-
+ if (nwritten != (ssize_t)idx_size) {
HGOTO_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, \
"error in writing index to metadata file")
+ }
done:
@@ -1903,9 +1877,9 @@ H5F__idx_entry_cmp(const void *_entry1, const void *_entry2)
static herr_t
H5F__vfd_swmr_writer__create_index(H5F_t * f)
{
- int i;
+ unsigned int i;
size_t bytes_available;
- int32_t entries_in_index;
+ size_t entries_in_index;
size_t index_size;
H5FD_vfd_swmr_idx_entry_t * index = NULL;
herr_t ret_value = SUCCEED; /* Return value */
@@ -1925,11 +1899,11 @@ H5F__vfd_swmr_writer__create_index(H5F_t * f)
HDassert(bytes_available > 0);
- entries_in_index = (int32_t)(bytes_available / H5FD_MD_INDEX_ENTRY_SIZE);
+ entries_in_index = bytes_available / H5FD_MD_INDEX_ENTRY_SIZE;
HDassert(entries_in_index > 0);
- index_size = sizeof(H5FD_vfd_swmr_idx_entry_t) * (size_t)entries_in_index;
+ index_size = sizeof(H5FD_vfd_swmr_idx_entry_t) * entries_in_index;
index = (H5FD_vfd_swmr_idx_entry_t *)HDmalloc(index_size);
if ( index == NULL )
@@ -1951,8 +1925,10 @@ H5F__vfd_swmr_writer__create_index(H5F_t * f)
index[i].moved_to_hdf5_file = FALSE;
}
+ HDassert(entries_in_index <= UINT32_MAX);
+
f->shared->mdf_idx = index;
- f->shared->mdf_idx_len = entries_in_index;
+ f->shared->mdf_idx_len = (uint32_t)entries_in_index;
f->shared->mdf_idx_entries_used = 0;
done:
@@ -1998,9 +1974,9 @@ H5F__vfd_swmr_writer__wait_a_tick(H5F_t *f)
HDassert(f->shared->vfd_swmr);
HDassert(f->shared->vfd_swmr_writer);
- tick_in_nsec = f->shared->vfd_swmr_config.tick_len * TENTH_SEC_TO_NANOSECS;
- req.tv_nsec = (long)(tick_in_nsec % SECOND_TO_NANOSECS);
- req.tv_sec = (time_t)(tick_in_nsec / SECOND_TO_NANOSECS);
+ tick_in_nsec = f->shared->vfd_swmr_config.tick_len * nanosecs_per_tenth_sec;
+ req.tv_nsec = (long)(tick_in_nsec % nanosecs_per_second);
+ req.tv_sec = (time_t)(tick_in_nsec / nanosecs_per_second);
result = HDnanosleep(&req, &rem);
diff --git a/src/H5G.c b/src/H5G.c
index 361127f..fdf613c 100644
--- a/src/H5G.c
+++ b/src/H5G.c
@@ -87,6 +87,7 @@
#include "H5Gpkg.h" /* Groups */
#include "H5Iprivate.h" /* IDs */
#include "H5Pprivate.h" /* Property lists */
+#include "H5VLprivate.h" /* Virtual Object Layer */
/****************/
@@ -108,6 +109,9 @@
/* Local Prototypes */
/********************/
+/* Group close callback */
+static herr_t H5G__close_cb(H5VL_object_t *grp_vol_obj);
+
/*********************/
/* Package Variables */
@@ -131,7 +135,7 @@ static const H5I_class_t H5I_GROUP_CLS[1] = {{
H5I_GROUP, /* ID class value */
0, /* Class flags */
0, /* # of reserved IDs for class */
- (H5I_free_t)H5G_close /* Callback routine for closing objects of this class */
+ (H5I_free_t)H5G__close_cb /* Callback routine for closing objects of this class */
}};
/* Flag indicating "top" of interface has been initialized */
@@ -255,6 +259,38 @@ H5G_term_package(void)
/*-------------------------------------------------------------------------
+ * Function: H5G__close_cb
+ *
+ * Purpose: Called when the ref count reaches zero on the group's ID
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5G__close_cb(H5VL_object_t *grp_vol_obj)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity check */
+ HDassert(grp_vol_obj);
+
+ /* Close the group */
+ if(H5VL_group_close(grp_vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "unable to close group")
+
+ /* Free the VOL object */
+ if(H5VL_free_object(grp_vol_obj) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "unable to free VOL object")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5G__close_cb() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5Gcreate2
*
* Purpose: Creates a new group relative to LOC_ID, giving it the
@@ -281,16 +317,15 @@ hid_t
H5Gcreate2(hid_t loc_id, const char *name, hid_t lcpl_id, hid_t gcpl_id,
hid_t gapl_id)
{
- H5G_t *grp = NULL; /* Structure for new group */
- H5G_loc_t loc; /* Location to create group */
+ void *grp = NULL; /* Structure for new group */
+ H5VL_object_t *vol_obj = NULL; /* object token of loc_id */
+ H5VL_loc_params_t loc_params;
hid_t ret_value = H5I_INVALID_HID; /* Return value */
FUNC_ENTER_API(H5I_INVALID_HID)
H5TRACE5("i", "i*siii", loc_id, name, lcpl_id, gcpl_id, gapl_id);
/* Check arguments */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a location")
if(!name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "name parameter cannot be NULL")
if(!*name)
@@ -314,17 +349,25 @@ H5Gcreate2(hid_t loc_id, const char *name, hid_t lcpl_id, hid_t gcpl_id,
if(H5CX_set_apl(&gapl_id, H5P_CLS_GACC, loc_id, TRUE) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info")
+ /* Get the location object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier")
+
+ /* Set the location parameters */
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
/* Create the group */
- if(NULL == (grp = H5G__create_named(&loc, name, lcpl_id, gcpl_id)))
+ if(NULL == (grp = H5VL_group_create(vol_obj, &loc_params, name, lcpl_id, gcpl_id, gapl_id, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)))
HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, H5I_INVALID_HID, "unable to create group")
/* Get an atom for the group */
- if((ret_value = H5I_register(H5I_GROUP, grp, TRUE)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to atomize group handle")
+ if((ret_value = H5VL_register(H5I_GROUP, grp, vol_obj->connector, TRUE)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to atomize group handle")
done:
if(H5I_INVALID_HID == ret_value)
- if(grp && H5G_close(grp) < 0)
+ if(grp && H5VL_group_close(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, H5I_INVALID_HID, "unable to release group")
FUNC_LEAVE_API(ret_value)
@@ -366,18 +409,14 @@ done:
hid_t
H5Gcreate_anon(hid_t loc_id, hid_t gcpl_id, hid_t gapl_id)
{
- H5G_t *grp = NULL; /* Structure for new group */
- H5G_loc_t loc;
- H5G_obj_create_t gcrt_info; /* Information for group creation */
+ void *grp = NULL; /* Structure for new group */
+ H5VL_object_t *vol_obj = NULL; /* Object token for loc_id */
+ H5VL_loc_params_t loc_params;
hid_t ret_value = H5I_INVALID_HID; /* Return value */
FUNC_ENTER_API(H5I_INVALID_HID)
H5TRACE3("i", "iii", loc_id, gcpl_id, gapl_id);
- /* Check arguments */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a location")
-
/* Check group creation property list */
if(H5P_DEFAULT == gcpl_id)
gcpl_id = H5P_GROUP_CREATE_DEFAULT;
@@ -389,36 +428,26 @@ H5Gcreate_anon(hid_t loc_id, hid_t gcpl_id, hid_t gapl_id)
if(H5CX_set_apl(&gapl_id, H5P_CLS_GACC, loc_id, TRUE) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info")
- /* Set up group creation info */
- gcrt_info.gcpl_id = gcpl_id;
- gcrt_info.cache_type = H5G_NOTHING_CACHED;
- HDmemset(&gcrt_info.cache, 0, sizeof(gcrt_info.cache));
+ /* Set location struct fields */
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* Get the location object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier")
/* Create the group */
- if(NULL == (grp = H5G__create(loc.oloc->file, &gcrt_info)))
- HGOTO_ERROR(H5E_SYM, H5E_CANTCREATE, H5I_INVALID_HID, "unable to create group")
+ if(NULL == (grp = H5VL_group_create(vol_obj, &loc_params, NULL, H5P_LINK_CREATE_DEFAULT, gcpl_id, gapl_id, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)))
+ HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, H5I_INVALID_HID, "unable to create group")
/* Get an atom for the group */
- if((ret_value = H5I_register(H5I_GROUP, grp, TRUE)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register group")
+ if((ret_value = H5VL_register(H5I_GROUP, grp, vol_obj->connector, TRUE)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to atomize group handle")
done:
- /* Release the group's object header, if it was created */
- if(grp) {
- H5O_loc_t *oloc; /* Object location for group */
-
- /* Get the new group's object location */
- if(NULL == (oloc = H5G_oloc(grp)))
- HDONE_ERROR(H5E_SYM, H5E_CANTGET, H5I_INVALID_HID, "unable to get object location of group")
-
- /* Decrement refcount on group's object header in memory */
- if(H5O_dec_rc_by_loc(oloc) < 0)
- HDONE_ERROR(H5E_SYM, H5E_CANTDEC, H5I_INVALID_HID, "unable to decrement refcount on newly created object")
- } /* end if */
-
/* Cleanup on failure */
if(H5I_INVALID_HID == ret_value)
- if(grp && H5G_close(grp) < 0)
+ if(grp && H5VL_group_close(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, H5I_INVALID_HID, "unable to release group")
FUNC_LEAVE_API(ret_value)
@@ -443,16 +472,15 @@ done:
hid_t
H5Gopen2(hid_t loc_id, const char *name, hid_t gapl_id)
{
- H5G_t *grp = NULL; /* Group opened */
- H5G_loc_t loc; /* Location of parent for group */
- hid_t ret_value = H5I_INVALID_HID; /* Return value */
+ void *grp = NULL; /* Group opened */
+ H5VL_object_t *vol_obj = NULL; /* object token of loc_id */
+ H5VL_loc_params_t loc_params;
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
FUNC_ENTER_API(H5I_INVALID_HID)
H5TRACE3("i", "i*si", loc_id, name, gapl_id);
/* Check args */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a location")
if(!name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "name parameter cannot be NULL")
if(!*name)
@@ -462,17 +490,24 @@ H5Gopen2(hid_t loc_id, const char *name, hid_t gapl_id)
if(H5CX_set_apl(&gapl_id, H5P_CLS_GACC, loc_id, FALSE) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info")
+ /* Get the location object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier")
+
/* Open the group */
- if(NULL == (grp = H5G__open_name(&loc, name)))
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ if(NULL == (grp = H5VL_group_open(vol_obj, &loc_params, name, gapl_id, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)))
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open group")
/* Register an ID for the group */
- if((ret_value = H5I_register(H5I_GROUP, grp, TRUE)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register group")
+ if((ret_value = H5VL_register(H5I_GROUP, grp, vol_obj->connector, TRUE)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register group")
done:
if(H5I_INVALID_HID == ret_value)
- if(grp && H5G_close(grp) < 0)
+ if(grp && H5VL_group_close(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, H5I_INVALID_HID, "unable to release group")
FUNC_LEAVE_API(ret_value)
@@ -495,18 +530,18 @@ done:
hid_t
H5Gget_create_plist(hid_t group_id)
{
- H5G_t *group = NULL;
- hid_t ret_value = H5I_INVALID_HID; /* Return value */
+ H5VL_object_t *vol_obj = NULL;
+ hid_t ret_value = H5I_INVALID_HID;
FUNC_ENTER_API(H5I_INVALID_HID)
H5TRACE1("i", "i", group_id);
/* Check args */
- if(NULL == (group = (H5G_t *)H5I_object_verify(group_id, H5I_GROUP)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(group_id, H5I_GROUP)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a group ID")
/* Get the group creation property list for the group */
- if((ret_value = H5G_get_create_plist(group)) < 0)
+ if(H5VL_group_get(vol_obj, H5VL_GROUP_GET_GCPL, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &ret_value) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5I_INVALID_HID, "can't get group's creation property list")
done:
@@ -526,8 +561,9 @@ done:
herr_t
H5Gget_info(hid_t loc_id, H5G_info_t *group_info)
{
- H5I_type_t id_type; /* Type of ID */
- H5G_loc_t loc; /* Location of group */
+ H5VL_object_t *vol_obj;
+ H5I_type_t id_type; /* Type of ID */
+ H5VL_loc_params_t loc_params;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -541,11 +577,13 @@ H5Gget_info(hid_t loc_id, H5G_info_t *group_info)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "group_info parameter cannot be NULL")
/* Get group location */
- if(H5G_loc(loc_id, &loc) < 0)
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
/* Retrieve the group's information */
- if(H5G__obj_info(loc.oloc, group_info) < 0)
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = id_type;
+ if(H5VL_group_get(vol_obj, H5VL_GROUP_GET_INFO, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &loc_params, group_info) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to get group info")
done:
@@ -567,15 +605,14 @@ herr_t
H5Gget_info_by_name(hid_t loc_id, const char *name, H5G_info_t *group_info,
hid_t lapl_id)
{
- H5G_loc_t loc; /* Location of group */
- herr_t ret_value = SUCCEED; /* Return value */
+ H5VL_object_t *vol_obj;
+ H5VL_loc_params_t loc_params;
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE4("e", "i*s*xi", loc_id, name, group_info, lapl_id);
/* Check args */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "name parameter cannot be NULL")
if(!*name)
@@ -587,8 +624,18 @@ H5Gget_info_by_name(hid_t loc_id, const char *name, H5G_info_t *group_info,
if(H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, FALSE) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTSET, FAIL, "can't set access property list info")
+ /* Get the location object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Set up location parameters */
+ loc_params.type = H5VL_OBJECT_BY_NAME;
+ loc_params.loc_data.loc_by_name.name = name;
+ loc_params.loc_data.loc_by_name.lapl_id = lapl_id;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
/* Retrieve the group's information */
- if(H5G__get_info_by_name(&loc, name, group_info/*out*/) < 0)
+ if(H5VL_group_get(vol_obj, H5VL_GROUP_GET_INFO, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &loc_params, group_info) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve group info")
done:
@@ -610,7 +657,8 @@ herr_t
H5Gget_info_by_idx(hid_t loc_id, const char *group_name, H5_index_t idx_type,
H5_iter_order_t order, hsize_t n, H5G_info_t *group_info, hid_t lapl_id)
{
- H5G_loc_t loc; /* Location of group */
+ H5VL_object_t *vol_obj;
+ H5VL_loc_params_t loc_params;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -618,8 +666,6 @@ H5Gget_info_by_idx(hid_t loc_id, const char *group_name, H5_index_t idx_type,
lapl_id);
/* Check args */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!group_name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "group_name parameter cannot be NULL")
if(!*group_name)
@@ -635,8 +681,21 @@ H5Gget_info_by_idx(hid_t loc_id, const char *group_name, H5_index_t idx_type,
if(H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, FALSE) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTSET, FAIL, "can't set access property list info")
+ /* Get the location object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Set location parameters */
+ loc_params.type = H5VL_OBJECT_BY_IDX;
+ loc_params.loc_data.loc_by_idx.name = group_name;
+ loc_params.loc_data.loc_by_idx.idx_type = idx_type;
+ loc_params.loc_data.loc_by_idx.order = order;
+ loc_params.loc_data.loc_by_idx.n = n;
+ loc_params.loc_data.loc_by_idx.lapl_id = lapl_id;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
/* Retrieve the group's information */
- if(H5G__get_info_by_idx(&loc, group_name, idx_type, order, n, group_info/*out*/) < 0)
+ if(H5VL_group_get(vol_obj, H5VL_GROUP_GET_INFO, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &loc_params, group_info) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve group info")
done:
@@ -663,7 +722,7 @@ H5Gclose(hid_t group_id)
H5TRACE1("e", "i", group_id);
/* Check args */
- if(NULL == H5I_object_verify(group_id,H5I_GROUP))
+ if(NULL == H5I_object_verify(group_id, H5I_GROUP))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group")
/* Decrement the counter on the group atom. It will be freed if the count
@@ -692,22 +751,22 @@ done:
herr_t
H5Gflush(hid_t group_id)
{
- H5G_t *grp; /* Group for this operation */
- herr_t ret_value = SUCCEED; /* Return value */
+ H5VL_object_t *vol_obj; /* Group for this operation */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE1("e", "i", group_id);
/* Check args */
- if(NULL == (grp = (H5G_t *)H5I_object_verify(group_id, H5I_GROUP)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(group_id, H5I_GROUP)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group ID")
/* Set up collective metadata if appropriate */
if(H5CX_set_loc(group_id) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTSET, FAIL, "can't set collective metadata read info")
- /* Flush metadata to file */
- if(H5O_flush_common(&grp->oloc, group_id) < 0)
+ /* Flush group's metadata to file */
+ if(H5VL_group_specific(vol_obj, H5VL_GROUP_FLUSH, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, group_id) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTFLUSH, FAIL, "unable to flush group")
done:
@@ -730,14 +789,14 @@ done:
herr_t
H5Grefresh(hid_t group_id)
{
- H5G_t *grp; /* Group for this operation */
- herr_t ret_value = SUCCEED; /* Return value */
-
+ H5VL_object_t *vol_obj; /* Group for this operation */
+ herr_t ret_value = SUCCEED; /* Return value */
+
FUNC_ENTER_API(FAIL)
H5TRACE1("e", "i", group_id);
/* Check args */
- if(NULL == (grp = (H5G_t *)H5I_object_verify(group_id, H5I_GROUP)))
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(group_id, H5I_GROUP)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group ID")
/* Set up collective metadata if appropriate */
@@ -745,7 +804,7 @@ H5Grefresh(hid_t group_id)
HGOTO_ERROR(H5E_SYM, H5E_CANTSET, FAIL, "can't set collective metadata read info")
/* Refresh group's metadata */
- if((H5O_refresh_metadata(group_id, grp->oloc)) < 0)
+ if(H5VL_group_specific(vol_obj, H5VL_GROUP_REFRESH, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, group_id) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, FAIL, "unable to refresh group")
done:
diff --git a/src/H5Gbtree2.c b/src/H5Gbtree2.c
index 721d591..71e0b2d 100644
--- a/src/H5Gbtree2.c
+++ b/src/H5Gbtree2.c
@@ -35,6 +35,7 @@
#include "H5private.h" /* Generic Functions */
#include "H5Eprivate.h" /* Error handling */
#include "H5Gpkg.h" /* Groups */
+#include "H5MMprivate.h" /* Memory management */
/****************/
@@ -206,7 +207,7 @@ H5G_dense_btree2_name_store(void *_nrecord, const void *_udata)
/* Copy user information info native record */
nrecord->hash = udata->common.name_hash;
- HDmemcpy(nrecord->id, udata->id, (size_t)H5G_DENSE_FHEAP_ID_LEN);
+ H5MM_memcpy(nrecord->id, udata->id, (size_t)H5G_DENSE_FHEAP_ID_LEN);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* H5G_dense_btree2_name_store() */
@@ -305,7 +306,7 @@ H5G_dense_btree2_name_encode(uint8_t *raw, const void *_nrecord, void H5_ATTR_UN
/* Encode the record's fields */
UINT32ENCODE(raw, nrecord->hash)
- HDmemcpy(raw, nrecord->id, (size_t)H5G_DENSE_FHEAP_ID_LEN);
+ H5MM_memcpy(raw, nrecord->id, (size_t)H5G_DENSE_FHEAP_ID_LEN);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* H5G_dense_btree2_name_encode() */
@@ -333,7 +334,7 @@ H5G_dense_btree2_name_decode(const uint8_t *raw, void *_nrecord, void H5_ATTR_UN
/* Decode the record's fields */
UINT32DECODE(raw, nrecord->hash)
- HDmemcpy(nrecord->id, raw, (size_t)H5G_DENSE_FHEAP_ID_LEN);
+ H5MM_memcpy(nrecord->id, raw, (size_t)H5G_DENSE_FHEAP_ID_LEN);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* H5G_dense_btree2_name_decode() */
@@ -393,7 +394,7 @@ H5G_dense_btree2_corder_store(void *_nrecord, const void *_udata)
/* Copy user information info native record */
nrecord->corder = udata->common.corder;
- HDmemcpy(nrecord->id, udata->id, (size_t)H5G_DENSE_FHEAP_ID_LEN);
+ H5MM_memcpy(nrecord->id, udata->id, (size_t)H5G_DENSE_FHEAP_ID_LEN);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* H5G_dense_btree2_corder_store() */
@@ -469,7 +470,7 @@ H5G_dense_btree2_corder_encode(uint8_t *raw, const void *_nrecord, void H5_ATTR_
/* Encode the record's fields */
INT64ENCODE(raw, nrecord->corder)
- HDmemcpy(raw, nrecord->id, (size_t)H5G_DENSE_FHEAP_ID_LEN);
+ H5MM_memcpy(raw, nrecord->id, (size_t)H5G_DENSE_FHEAP_ID_LEN);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* H5G_dense_btree2_corder_encode() */
@@ -497,7 +498,7 @@ H5G_dense_btree2_corder_decode(const uint8_t *raw, void *_nrecord, void H5_ATTR_
/* Decode the record's fields */
INT64DECODE(raw, nrecord->corder)
- HDmemcpy(nrecord->id, raw, (size_t)H5G_DENSE_FHEAP_ID_LEN);
+ H5MM_memcpy(nrecord->id, raw, (size_t)H5G_DENSE_FHEAP_ID_LEN);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* H5G_dense_btree2_corder_decode() */
diff --git a/src/H5Gcache.c b/src/H5Gcache.c
index 6641034..ec5b512 100644
--- a/src/H5Gcache.c
+++ b/src/H5Gcache.c
@@ -36,6 +36,7 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5Gpkg.h" /* Groups */
#include "H5MFprivate.h" /* File memory management */
+#include "H5MMprivate.h" /* Memory management */
#include "H5WBprivate.h" /* Wrapped Buffers */
@@ -288,7 +289,7 @@ H5G__cache_node_serialize(const H5F_t *f, void *_image, size_t len,
HDassert(len == sym->node_size);
/* magic number */
- HDmemcpy(image, H5G_NODE_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ H5MM_memcpy(image, H5G_NODE_MAGIC, (size_t)H5_SIZEOF_MAGIC);
image += H5_SIZEOF_MAGIC;
/* version number */
diff --git a/src/H5Gcompact.c b/src/H5Gcompact.c
index b32ce39..7e2b324 100644
--- a/src/H5Gcompact.c
+++ b/src/H5Gcompact.c
@@ -572,71 +572,3 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5G__compact_lookup_by_idx() */
-#ifndef H5_NO_DEPRECATED_SYMBOLS
-
-/*-------------------------------------------------------------------------
- * Function: H5G__compact_get_type_by_idx
- *
- * Purpose: Returns the type of objects in the group by giving index.
- *
- * Return: Success: Non-negative
- * Failure: Negative
- *
- * Programmer: Quincey Koziol
- * Sep 12, 2005
- *
- *-------------------------------------------------------------------------
- */
-H5G_obj_t
-H5G__compact_get_type_by_idx(H5O_loc_t *oloc, const H5O_linfo_t *linfo,
- hsize_t idx)
-{
- H5G_link_table_t ltable = {0, NULL}; /* Link table */
- H5G_obj_t ret_value = H5G_UNKNOWN; /* Return value */
-
- FUNC_ENTER_PACKAGE
-
- /* Sanity check */
- HDassert(oloc);
-
- /* Build table of all link messages */
- if(H5G__compact_build_table(oloc, linfo, H5_INDEX_NAME, H5_ITER_INC, &ltable) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, H5G_UNKNOWN, "can't create link message table")
-
- /* Check for going out of bounds */
- if(idx >= ltable.nlinks)
- HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, H5G_UNKNOWN, "index out of bound")
-
- /* Determine type of object */
- if(ltable.lnks[idx].type == H5L_TYPE_SOFT)
- ret_value = H5G_LINK;
- else if(ltable.lnks[idx].type >= H5L_TYPE_UD_MIN)
- ret_value = H5G_UDLINK;
- else if(ltable.lnks[idx].type == H5L_TYPE_HARD){
- H5O_loc_t tmp_oloc; /* Temporary object location */
- H5O_type_t obj_type; /* Type of object at location */
-
- /* Build temporary object location */
- tmp_oloc.file = oloc->file;
- tmp_oloc.addr = ltable.lnks[idx].u.hard.addr;
-
- /* Get the type of the object */
- if(H5O_obj_type(&tmp_oloc, &obj_type) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5G_UNKNOWN, "can't get object type")
-
- /* Map to group object type */
- if(H5G_UNKNOWN == (ret_value = H5G_map_obj_type(obj_type)))
- HGOTO_ERROR(H5E_SYM, H5E_BADTYPE, H5G_UNKNOWN, "can't determine object type")
- } else {
- HGOTO_ERROR(H5E_SYM, H5E_BADTYPE, H5G_UNKNOWN, "unknown link type")
- } /* end else */
-
-done:
- /* Release link table */
- if(ltable.lnks && H5G__link_release_table(&ltable) < 0)
- HDONE_ERROR(H5E_SYM, H5E_CANTFREE, H5G_UNKNOWN, "unable to release link table")
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5G__compact_get_type_by_idx() */
-#endif /* H5_NO_DEPRECATED_SYMBOLS */
-
diff --git a/src/H5Gdense.c b/src/H5Gdense.c
index d2bcad1..a2ef55c 100644
--- a/src/H5Gdense.c
+++ b/src/H5Gdense.c
@@ -1777,80 +1777,3 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5G__dense_delete() */
-#ifndef H5_NO_DEPRECATED_SYMBOLS
-
-/*-------------------------------------------------------------------------
- * Function: H5G__dense_get_type_by_idx
- *
- * Purpose: Returns the type of objects in the group by giving index.
- *
- * Note: This routine assumes a lookup on the link name index in
- * increasing order and isn't currently set up to be as
- * flexible as other routines in this code module, because
- * the H5Gget_objtype_by_idx that it's supporting is
- * deprecated.
- *
- * Return: Success: Non-negative, object type
- * Failure: Negative
- *
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Sep 19 2006
- *
- *-------------------------------------------------------------------------
- */
-H5G_obj_t
-H5G__dense_get_type_by_idx(H5F_t *f, H5O_linfo_t *linfo, hsize_t idx)
-{
- H5G_link_table_t ltable = {0, NULL}; /* Table of links */
- H5G_obj_t ret_value = H5G_UNKNOWN; /* Return value */
-
- FUNC_ENTER_PACKAGE
-
- /*
- * Check arguments.
- */
- HDassert(f);
- HDassert(linfo);
-
- /* Build the table of links for this group */
- if(H5G__dense_build_table(f, linfo, H5_INDEX_NAME, H5_ITER_INC, &ltable) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5G_UNKNOWN, "error building table of links")
-
- /* Check for going out of bounds */
- if(idx >= ltable.nlinks)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5G_UNKNOWN, "index out of bound")
-
- /* Determine type of object */
- if(ltable.lnks[idx].type == H5L_TYPE_SOFT)
- ret_value = H5G_LINK;
- else if(ltable.lnks[idx].type >= H5L_TYPE_UD_MIN)
- ret_value = H5G_UDLINK;
- else if(ltable.lnks[idx].type == H5L_TYPE_HARD) {
- H5O_loc_t tmp_oloc; /* Temporary object location */
- H5O_type_t obj_type; /* Type of object at location */
-
- /* Build temporary object location */
- tmp_oloc.file = f;
- tmp_oloc.addr = ltable.lnks[idx].u.hard.addr;
-
- /* Get the type of the object */
- if(H5O_obj_type(&tmp_oloc, &obj_type) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5G_UNKNOWN, "can't get object type")
-
- /* Map to group object type */
- if(H5G_UNKNOWN == (ret_value = H5G_map_obj_type(obj_type)))
- HGOTO_ERROR(H5E_SYM, H5E_BADTYPE, H5G_UNKNOWN, "can't determine object type")
- } else {
- HGOTO_ERROR(H5E_SYM, H5E_BADTYPE, H5G_UNKNOWN, "unknown link type")
- } /* end else */
-
-done:
- /* Release link table */
- if(ltable.lnks && H5G__link_release_table(&ltable) < 0)
- HDONE_ERROR(H5E_SYM, H5E_CANTFREE, H5G_UNKNOWN, "unable to release link table")
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5G__dense_get_type_by_idx() */
-#endif /* H5_NO_DEPRECATED_SYMBOLS */
-
diff --git a/src/H5Gdeprec.c b/src/H5Gdeprec.c
index f8f668c..fcb16d3 100644
--- a/src/H5Gdeprec.c
+++ b/src/H5Gdeprec.c
@@ -43,6 +43,9 @@
#include "H5Iprivate.h" /* IDs */
#include "H5Lprivate.h" /* Links */
#include "H5Pprivate.h" /* Property lists */
+#include "H5VLprivate.h" /* Virtual Object Layer */
+
+#include "H5VLnative_private.h" /* Native VOL connector */
/****************/
@@ -71,17 +74,9 @@ typedef struct {
/********************/
/* Local Prototypes */
/********************/
-
-static herr_t H5G__link(hid_t cur_loc_id, const char *cur_name, H5G_link_t type,
- hid_t new_loc_id, const char *new_name, hid_t lcpl_id);
-static herr_t H5G__move(hid_t src_loc_id, const char *src_name,
- hid_t dst_loc_id, const char *dst_name, hid_t lcpl_id);
static herr_t H5G__get_objinfo_cb(H5G_loc_t *grp_loc/*in*/, const char *name,
const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/,
H5G_own_loc_t *own_loc/*out*/);
-static herr_t H5G__get_objinfo(const H5G_loc_t *loc, const char *name,
- hbool_t follow_link, H5G_stat_t *statbuf/*out*/);
-static H5G_obj_t H5G__obj_get_type_by_idx(H5O_loc_t *oloc, hsize_t idx);
#endif /* H5_NO_DEPRECATED_SYMBOLS */
@@ -136,6 +131,9 @@ H5G_map_obj_type(H5O_type_t obj_type)
ret_value = H5G_TYPE;
break;
+ case H5O_TYPE_MAP:
+ /* Maps not supported in native VOL connector */
+
case H5O_TYPE_UNKNOWN:
case H5O_TYPE_NTYPES:
default:
@@ -174,17 +172,17 @@ H5G_map_obj_type(H5O_type_t obj_type)
hid_t
H5Gcreate1(hid_t loc_id, const char *name, size_t size_hint)
{
- H5G_loc_t loc; /* Location to create group */
- H5G_t *grp = NULL; /* New group created */
+ void *grp = NULL; /* New group created */
+ H5VL_object_t *vol_obj; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
hid_t tmp_gcpl = H5I_INVALID_HID; /* Temporary group creation property list */
+ hid_t lcpl_id = H5P_LINK_CREATE_DEFAULT;
hid_t ret_value = H5I_INVALID_HID; /* Return value */
FUNC_ENTER_API(H5I_INVALID_HID)
H5TRACE3("i", "i*sz", loc_id, name, size_hint);
/* Check arguments */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a location")
if(!name || !*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "no name given")
@@ -221,13 +219,21 @@ H5Gcreate1(hid_t loc_id, const char *name, size_t size_hint)
if(H5CX_set_loc(loc_id) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTSET, H5I_INVALID_HID, "can't set collective metadata read info")
+ /* Set location parameters */
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* get the location object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier")
+
/* Create the group */
- if(NULL == (grp = H5G__create_named(&loc, name, H5P_LINK_CREATE_DEFAULT, tmp_gcpl)))
+ if(NULL == (grp = H5VL_group_create(vol_obj, &loc_params, name, lcpl_id, tmp_gcpl, H5P_GROUP_ACCESS_DEFAULT, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)))
HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, H5I_INVALID_HID, "unable to create group")
/* Get an atom for the group */
- if((ret_value = H5I_register(H5I_GROUP, grp, TRUE)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register group")
+ if((ret_value = H5VL_register(H5I_GROUP, grp, vol_obj->connector, TRUE)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register group")
done:
if(H5I_INVALID_HID != tmp_gcpl && tmp_gcpl != H5P_GROUP_CREATE_DEFAULT)
@@ -235,7 +241,7 @@ done:
HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, H5I_INVALID_HID, "unable to release property list")
if(H5I_INVALID_HID == ret_value)
- if(grp && H5G_close(grp) < 0)
+ if(grp && H5VL_group_close(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, H5I_INVALID_HID, "unable to release group")
FUNC_LEAVE_API(ret_value)
@@ -262,30 +268,37 @@ done:
hid_t
H5Gopen1(hid_t loc_id, const char *name)
{
- H5G_t *grp = NULL; /* Group opened */
- H5G_loc_t loc; /* Location of parent for group */
- hid_t ret_value = H5I_INVALID_HID; /* Return value */
+ void *grp = NULL; /* Group opened */
+ H5VL_object_t *vol_obj = NULL; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
FUNC_ENTER_API(H5I_INVALID_HID)
H5TRACE2("i", "i*s", loc_id, name);
/* Check args */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a location")
if(!name || !*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "no name")
+ /* Set location parameters */
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* get the location object */
+ if (NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier")
+
/* Open the group */
- if(NULL == (grp = H5G__open_name(&loc, name)))
+ if(NULL == (grp = H5VL_group_open(vol_obj, &loc_params, name, H5P_DEFAULT, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)))
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open group")
/* Get an atom for the group */
- if((ret_value = H5I_register(H5I_GROUP, grp, TRUE)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register group")
+ if((ret_value = H5VL_register(H5I_GROUP, grp, vol_obj->connector, TRUE)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register group")
done:
if(H5I_INVALID_HID == ret_value)
- if(grp && H5G_close(grp) < 0)
+ if(grp && H5VL_group_close(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, H5I_INVALID_HID, "unable to release group")
FUNC_LEAVE_API(ret_value)
@@ -303,6 +316,7 @@ done:
herr_t
H5Glink(hid_t cur_loc_id, H5G_link_t type, const char *cur_name, const char *new_name)
{
+ hid_t lcpl_id = H5P_LINK_CREATE_DEFAULT;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -319,8 +333,52 @@ H5Glink(hid_t cur_loc_id, H5G_link_t type, const char *cur_name, const char *new
HGOTO_ERROR(H5E_SYM, H5E_CANTSET, FAIL, "can't set collective metadata read info")
/* Create link */
- if(H5G__link(cur_loc_id, cur_name, type, H5L_SAME_LOC, new_name, H5P_LINK_CREATE_DEFAULT) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "couldn't create link")
+ if(type == H5L_TYPE_HARD) {
+ H5VL_object_t *vol_obj; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params1;
+ H5VL_loc_params_t loc_params2;
+ H5VL_object_t tmp_vol_obj; /* Temporary object token of */
+
+ loc_params1.type = H5VL_OBJECT_BY_NAME;
+ loc_params1.obj_type = H5I_get_type(cur_loc_id);
+ loc_params1.loc_data.loc_by_name.name = cur_name;
+ loc_params1.loc_data.loc_by_name.lapl_id = H5P_DEFAULT;
+
+ loc_params2.type = H5VL_OBJECT_BY_NAME;
+ loc_params2.loc_data.loc_by_name.name = new_name;
+ loc_params2.loc_data.loc_by_name.lapl_id = H5P_DEFAULT;
+
+ /* get the location object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(cur_loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Construct a temporary VOL object */
+ tmp_vol_obj.data = NULL;
+ tmp_vol_obj.connector = vol_obj->connector;
+
+ /* Create the link through the VOL */
+ if(H5VL_link_create(H5VL_LINK_CREATE_HARD, &tmp_vol_obj, &loc_params2, lcpl_id, H5P_DEFAULT, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, vol_obj->data, &loc_params1) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create link")
+ } /* end if */
+ else if(type == H5L_TYPE_SOFT) {
+ H5VL_object_t *vol_obj; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
+
+ loc_params.type = H5VL_OBJECT_BY_NAME;
+ loc_params.loc_data.loc_by_name.name = new_name;
+ loc_params.loc_data.loc_by_name.lapl_id = H5P_DEFAULT;
+ loc_params.obj_type = H5I_get_type(cur_loc_id);
+
+ /* get the location object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(cur_loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Create the link through the VOL */
+ if(H5VL_link_create(H5VL_LINK_CREATE_SOFT, vol_obj, &loc_params, lcpl_id, H5P_DEFAULT, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, cur_name) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create link")
+ } /* end else-if */
+ else
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Not a valid link type")
done:
FUNC_LEAVE_API(ret_value)
@@ -339,6 +397,7 @@ herr_t
H5Glink2(hid_t cur_loc_id, const char *cur_name, H5G_link_t type,
hid_t new_loc_id, const char *new_name)
{
+ hid_t lcpl_id = H5P_LINK_CREATE_DEFAULT;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -354,84 +413,61 @@ H5Glink2(hid_t cur_loc_id, const char *cur_name, H5G_link_t type,
if(H5CX_set_loc(cur_loc_id) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTSET, FAIL, "can't set collective metadata read info")
- /* Create link */
- if(H5G__link(cur_loc_id, cur_name, type, new_loc_id, new_name, H5P_LINK_CREATE_DEFAULT) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "couldn't create link")
-
-done:
- FUNC_LEAVE_API(ret_value)
-} /* end H5Glink2() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5G__link
- *
- * Purpose: Internal routine to create a new link.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * Monday, December 18, 2017
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5G__link(hid_t cur_loc_id, const char *cur_name, H5G_link_t type,
- hid_t new_loc_id, const char *new_name, hid_t lcpl_id)
-{
- H5G_loc_t new_loc; /* Information about new link's group */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_STATIC
-
/* Create the appropriate kind of link */
if(type == H5L_TYPE_HARD) {
- H5G_loc_t cur_loc, *cur_loc_p; /* Information about current link's group */
- H5G_loc_t *new_loc_p; /* Information about new link's group */
-
- /* Finish checking arguments */
- if(cur_loc_id == H5L_SAME_LOC && new_loc_id == H5L_SAME_LOC)
- HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "source and destination should not be both H5L_SAME_LOC")
- if(cur_loc_id != H5L_SAME_LOC && H5G_loc(cur_loc_id, &cur_loc) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_BADTYPE, FAIL, "not a location")
- if(new_loc_id != H5L_SAME_LOC && H5G_loc(new_loc_id, &new_loc) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_BADTYPE, FAIL, "not a location")
-
- /* Set up current & new location pointers */
- cur_loc_p = &cur_loc;
- new_loc_p = &new_loc;
- if(cur_loc_id == H5L_SAME_LOC)
- cur_loc_p = new_loc_p;
- else if(new_loc_id == H5L_SAME_LOC)
- new_loc_p = cur_loc_p;
- else if(cur_loc_p->oloc->file != new_loc_p->oloc->file)
- HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "source and destination should be in the same file.")
-
- /* Create the link */
- if(H5L_create_hard(cur_loc_p, cur_name, new_loc_p, new_name, lcpl_id) < 0)
+ H5VL_object_t *vol_obj1; /* Object token of loc_id */
+ H5VL_object_t *vol_obj2; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params1;
+ H5VL_loc_params_t loc_params2;
+
+ loc_params1.type = H5VL_OBJECT_BY_NAME;
+ loc_params1.obj_type = H5I_get_type(cur_loc_id);
+ loc_params1.loc_data.loc_by_name.name = cur_name;
+ loc_params1.loc_data.loc_by_name.lapl_id = H5P_DEFAULT;
+
+ loc_params2.type = H5VL_OBJECT_BY_NAME;
+ loc_params2.obj_type = H5I_get_type(new_loc_id);
+ loc_params2.loc_data.loc_by_name.name = new_name;
+ loc_params2.loc_data.loc_by_name.lapl_id = H5P_DEFAULT;
+
+ /* get the location object */
+ if(NULL == (vol_obj1 = (H5VL_object_t *)H5I_object(cur_loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+ if(NULL == (vol_obj2 = (H5VL_object_t *)H5I_object(new_loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Create the link through the VOL */
+ if(H5VL_link_create(H5VL_LINK_CREATE_HARD, vol_obj2, &loc_params2, lcpl_id, H5P_DEFAULT, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, vol_obj1->data, &loc_params1) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create link")
- }
+ } /* end if */
else if(type == H5L_TYPE_SOFT) {
- /* Soft links only need one location, the new_loc_id, but it's possible
- * that new_loc_id is H5L_SAME_LOC
- */
+ H5VL_object_t *vol_obj; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
+
+ /* Soft links only need one location, the new_loc_id, but it's possible that
+ * new_loc_id is H5L_SAME_LOC */
if(new_loc_id == H5L_SAME_LOC)
new_loc_id = cur_loc_id;
- /* Finish checking arguments */
- if(H5G_loc(new_loc_id, &new_loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
+ loc_params.type = H5VL_OBJECT_BY_NAME;
+ loc_params.loc_data.loc_by_name.name = new_name;
+ loc_params.loc_data.loc_by_name.lapl_id = H5P_DEFAULT;
+ loc_params.obj_type = H5I_get_type(new_loc_id);
- /* Create the link */
- if(H5L_create_soft(cur_name, &new_loc, new_name, lcpl_id) < 0)
+ /* get the location object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(new_loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Create the link through the VOL */
+ if(H5VL_link_create(H5VL_LINK_CREATE_SOFT, vol_obj, &loc_params, lcpl_id, H5P_DEFAULT, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, cur_name) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create link")
- }
+ } /* end else-if */
else
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a valid link type")
done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5G__link() */
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Glink2() */
/*-------------------------------------------------------------------------
@@ -444,7 +480,10 @@ done:
herr_t
H5Gmove(hid_t src_loc_id, const char *src_name, const char *dst_name)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5VL_object_t *vol_obj; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params1;
+ H5VL_loc_params_t loc_params2;
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE3("e", "i*s*s", src_loc_id, src_name, dst_name);
@@ -453,8 +492,21 @@ H5Gmove(hid_t src_loc_id, const char *src_name, const char *dst_name)
if(H5CX_set_loc(src_loc_id) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTSET, FAIL, "can't set collective metadata read info")
+ loc_params1.type = H5VL_OBJECT_BY_NAME;
+ loc_params1.obj_type = H5I_get_type(src_loc_id);
+ loc_params1.loc_data.loc_by_name.name = src_name;
+ loc_params1.loc_data.loc_by_name.lapl_id = H5P_DEFAULT;
+
+ loc_params2.type = H5VL_OBJECT_BY_NAME;
+ loc_params2.loc_data.loc_by_name.name = dst_name;
+ loc_params2.loc_data.loc_by_name.lapl_id = H5P_DEFAULT;
+
+ /* get the location object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(src_loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
/* Move the link */
- if(H5G__move(src_loc_id, src_name, H5L_SAME_LOC, dst_name, H5P_LINK_CREATE_DEFAULT) < 0)
+ if(H5VL_link_move(vol_obj, &loc_params1, NULL, &loc_params2, H5P_DEFAULT, H5P_DEFAULT, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTMOVE, FAIL, "couldn't move link")
done:
@@ -473,21 +525,42 @@ herr_t
H5Gmove2(hid_t src_loc_id, const char *src_name, hid_t dst_loc_id,
const char *dst_name)
{
+ H5VL_object_t *vol_obj1 = NULL; /* Object token of src_id */
+ H5VL_loc_params_t loc_params1;
+ H5VL_object_t *vol_obj2 = NULL; /* Object token of dst_id */
+ H5VL_loc_params_t loc_params2;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE4("e", "i*si*s", src_loc_id, src_name, dst_loc_id, dst_name);
- /* Check arguments */
- if(src_loc_id == H5L_SAME_LOC && dst_loc_id == H5L_SAME_LOC)
- HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "source and destination should not both be H5L_SAME_LOC")
-
/* Set up collective metadata if appropriate */
if(H5CX_set_loc(dst_loc_id) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTSET, FAIL, "can't set collective metadata read info")
+ /* Set location parameter for source object */
+ loc_params1.type = H5VL_OBJECT_BY_NAME;
+ loc_params1.loc_data.loc_by_name.name = src_name;
+ loc_params1.loc_data.loc_by_name.lapl_id = H5P_DEFAULT;
+ loc_params1.obj_type = H5I_get_type(src_loc_id);
+
+ /* Set location parameter for destination object */
+ loc_params2.type = H5VL_OBJECT_BY_NAME;
+ loc_params2.loc_data.loc_by_name.name = dst_name;
+ loc_params2.loc_data.loc_by_name.lapl_id = H5P_DEFAULT;
+ loc_params2.obj_type = H5I_get_type(dst_loc_id);
+
+ if(H5L_SAME_LOC != src_loc_id)
+ /* get the location object */
+ if(NULL == (vol_obj1 = (H5VL_object_t *)H5I_object(src_loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+ if(H5L_SAME_LOC != dst_loc_id)
+ /* get the location object */
+ if(NULL == (vol_obj2 = (H5VL_object_t *)H5I_object(dst_loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
/* Move the link */
- if(H5G__move(src_loc_id, src_name, dst_loc_id, dst_name, H5P_LINK_CREATE_DEFAULT) < 0)
+ if(H5VL_link_move(vol_obj1, &loc_params1, vol_obj2, &loc_params2, H5P_DEFAULT, H5P_DEFAULT, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTMOVE, FAIL, "unable to move link")
done:
@@ -496,60 +569,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5G__move
- *
- * Purpose: Renames an object within an HDF5 file and moves it to a new
- * group. The original name SRC is unlinked from the group graph
- * and then inserted with the new name DST (which can specify a
- * new path for the object) as an atomic operation. The names
- * are interpreted relative to SRC_LOC_ID and
- * DST_LOC_ID, which are either file IDs or group ID.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * Monday, November 6, 2006
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5G__move(hid_t src_loc_id, const char *src_name, hid_t dst_loc_id,
- const char *dst_name, hid_t lcpl_id)
-{
- H5G_loc_t src_loc, *src_loc_p; /* Group info for source location */
- H5G_loc_t dst_loc, *dst_loc_p; /* Group info for destination location */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_STATIC
-
- /* Check arguments */
- if(src_loc_id != H5L_SAME_LOC && H5G_loc(src_loc_id, &src_loc) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_BADTYPE, FAIL, "not a location")
- if(dst_loc_id != H5L_SAME_LOC && H5G_loc(dst_loc_id, &dst_loc) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_BADTYPE, FAIL, "not a location")
- if(!src_name || !*src_name)
- HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "no current name specified")
- if(!dst_name || !*dst_name)
- HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "no destination name specified")
-
- /* Set up src & dst location pointers */
- src_loc_p = &src_loc;
- dst_loc_p = &dst_loc;
- if(src_loc_id == H5L_SAME_LOC)
- src_loc_p = dst_loc_p;
- else if(dst_loc_id == H5L_SAME_LOC)
- dst_loc_p = src_loc_p;
-
- /* Move the link */
- if(H5L_move(src_loc_p, src_name, dst_loc_p, dst_name, FALSE, lcpl_id) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTMOVE, FAIL, "unable to move link")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5G__move() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5Gunlink
*
* Purpose: Removes a link. The new API is H5Ldelete/H5Ldelete_by_idx.
@@ -559,15 +578,14 @@ done:
herr_t
H5Gunlink(hid_t loc_id, const char *name)
{
- H5G_loc_t loc; /* Group's location */
+ H5VL_object_t *vol_obj; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE2("e", "i*s", loc_id, name);
/* Check arguments */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!name || !*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name")
@@ -575,8 +593,17 @@ H5Gunlink(hid_t loc_id, const char *name)
if(H5CX_set_loc(loc_id) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTSET, FAIL, "can't set collective metadata read info")
+ loc_params.type = H5VL_OBJECT_BY_NAME;
+ loc_params.obj_type = H5I_get_type(loc_id);
+ loc_params.loc_data.loc_by_name.name = name;
+ loc_params.loc_data.loc_by_name.lapl_id = H5P_LINK_ACCESS_DEFAULT;
+
+ /* Get the location object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
/* Delete the link */
- if(H5L_delete(&loc, name) < 0)
+ if(H5VL_link_specific(vol_obj, &loc_params, H5VL_LINK_DELETE, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "couldn't delete link")
done:
@@ -595,15 +622,14 @@ done:
herr_t
H5Gget_linkval(hid_t loc_id, const char *name, size_t size, char *buf/*out*/)
{
- H5G_loc_t loc; /* Group's location */
+ H5VL_object_t *vol_obj; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE4("e", "i*szx", loc_id, name, size, buf);
/* Check arguments */
- if(H5G_loc(loc_id, &loc))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!name || !*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified")
@@ -611,9 +637,18 @@ H5Gget_linkval(hid_t loc_id, const char *name, size_t size, char *buf/*out*/)
if(H5CX_set_loc(loc_id) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTSET, FAIL, "can't set collective metadata read info")
+ loc_params.type = H5VL_OBJECT_BY_NAME;
+ loc_params.obj_type = H5I_get_type(loc_id);
+ loc_params.loc_data.loc_by_name.name = name;
+ loc_params.loc_data.loc_by_name.lapl_id = H5P_LINK_ACCESS_DEFAULT;
+
+ /* Get the location object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
/* Get the link value */
- if(H5L_get_val(&loc, name, buf, size) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "couldn't get link info")
+ if(H5VL_link_get(vol_obj, &loc_params, H5VL_LINK_GET_VAL, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, buf, size) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to get link value")
done:
FUNC_LEAVE_API(ret_value)
@@ -640,14 +675,13 @@ done:
herr_t
H5Gset_comment(hid_t loc_id, const char *name, const char *comment)
{
- H5G_loc_t loc; /* Group's location */
- herr_t ret_value = SUCCEED; /* Return value */
+ H5VL_object_t *vol_obj; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE3("e", "i*s*s", loc_id, name, comment);
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!name || !*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified")
@@ -655,8 +689,18 @@ H5Gset_comment(hid_t loc_id, const char *name, const char *comment)
if(H5CX_set_loc(loc_id) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTSET, FAIL, "can't set collective metadata read info")
+ /* Fill in location struct fields */
+ loc_params.type = H5VL_OBJECT_BY_NAME;
+ loc_params.loc_data.loc_by_name.name = name;
+ loc_params.loc_data.loc_by_name.lapl_id = H5P_LINK_ACCESS_DEFAULT;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* Get the location object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
/* Set the comment */
- if(H5G_loc_set_comment(&loc, name, comment) < 0)
+ if(H5VL_object_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_OBJECT_SET_COMMENT, &loc_params, comment) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTSET, FAIL, "unable to set comment value")
done:
@@ -690,26 +734,39 @@ done:
int
H5Gget_comment(hid_t loc_id, const char *name, size_t bufsize, char *buf)
{
- H5G_loc_t loc; /* Group's location */
+ H5VL_object_t *vol_obj; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
+ ssize_t op_ret; /* Return value from operation */
int ret_value; /* Return value */
- FUNC_ENTER_API(FAIL)
+ FUNC_ENTER_API(-1)
H5TRACE4("Is", "i*sz*s", loc_id, name, bufsize, buf);
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!name || !*name)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified")
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, -1, "no name specified")
if(bufsize > 0 && !buf)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no buffer specified")
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, -1, "no buffer specified")
/* Set up collective metadata if appropriate */
if(H5CX_set_loc(loc_id) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTSET, FAIL, "can't set collective metadata read info")
+ HGOTO_ERROR(H5E_SYM, H5E_CANTSET, -1, "can't set collective metadata read info")
+
+ /* Fill in location struct fields */
+ loc_params.type = H5VL_OBJECT_BY_NAME;
+ loc_params.loc_data.loc_by_name.name = name;
+ loc_params.loc_data.loc_by_name.lapl_id = H5P_LINK_ACCESS_DEFAULT;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* Get the location object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, -1, "invalid location identifier")
/* Get the comment */
- if((ret_value = (int)H5G_loc_get_comment(&loc, name, buf, bufsize)) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to get comment value")
+ if(H5VL_object_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_OBJECT_GET_COMMENT, &loc_params, buf, bufsize, &op_ret) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, -1, "unable to get comment value")
+
+ /* Set return value */
+ ret_value = (int)op_ret;
done:
FUNC_LEAVE_API(ret_value)
@@ -744,18 +801,17 @@ herr_t
H5Giterate(hid_t loc_id, const char *name, int *idx_p, H5G_iterate_t op,
void *op_data)
{
- H5G_loc_t loc; /* Location of object */
+ H5VL_object_t *vol_obj; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
H5G_link_iterate_t lnk_op; /* Link operator */
hsize_t last_obj; /* Index of last object looked at */
- hsize_t idx; /* Internal location to hold index */
+ hsize_t idx; /* Internal location to hold index */
herr_t ret_value; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE5("e", "i*s*Isx*x", loc_id, name, idx_p, op, op_data);
/* Check args */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location ID")
if(!name || !*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified")
if(idx_p && *idx_p < 0)
@@ -771,9 +827,19 @@ H5Giterate(hid_t loc_id, const char *name, int *idx_p, H5G_iterate_t op,
lnk_op.op_type = H5G_LINK_OP_OLD;
lnk_op.op_func.op_old = op;
- /* Call private function */
- if((ret_value = H5G_iterate(&loc, name, H5_INDEX_NAME, H5_ITER_INC, idx, &last_obj, &lnk_op, op_data)) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "group iteration failed")
+ /* Fill out location struct */
+ loc_params.type = H5VL_OBJECT_BY_NAME;
+ loc_params.loc_data.loc_by_name.name = name;
+ loc_params.loc_data.loc_by_name.lapl_id = H5P_LINK_ACCESS_DEFAULT;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* Get the object pointer */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADTYPE, (-1), "invalid identifier")
+
+ /* Call private iteration function, through VOL callback */
+ if((ret_value = H5VL_group_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_GROUP_ITERATE_OLD, &loc_params, idx, &last_obj, &lnk_op, op_data)) < 0)
+ HERROR(H5E_SYM, H5E_BADITER, "error iterating over group's links");
/* Set the index we stopped at */
if(idx_p)
@@ -803,29 +869,35 @@ done:
herr_t
H5Gget_num_objs(hid_t loc_id, hsize_t *num_objs)
{
- H5G_loc_t loc; /* Location of object */
+ H5VL_object_t *vol_obj; /* Object token of loc_id */
+ H5I_type_t id_type; /* Type of ID */
+ H5VL_loc_params_t loc_params;
H5G_info_t grp_info; /* Group information */
- H5O_type_t obj_type; /* Type of object at location */
- herr_t ret_value = SUCCEED;
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE2("e", "i*h", loc_id, num_objs);
/* Check args */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location ID")
- if(H5O_obj_type(loc.oloc, &obj_type) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_CANTGET, FAIL, "can't get object type")
- if(obj_type != H5O_TYPE_GROUP)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group")
+ id_type = H5I_get_type(loc_id);
+ if(!(H5I_GROUP == id_type || H5I_FILE == id_type))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid group (or file) ID")
if(!num_objs)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "bad pointer to # of objects")
- /* Retrieve information about the group */
- if(H5G__obj_info(loc.oloc, &grp_info) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTCOUNT, FAIL, "can't determine # of objects")
+ /* Fill in location struct fields */
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = id_type;
+
+ /* Get group location */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
- /* Set the number of objects [sic: links] in the group */
+ /* Retrieve the group's information */
+ if(H5VL_group_get(vol_obj, H5VL_GROUP_GET_INFO, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &loc_params, &grp_info) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to get group info")
+
+ /* Set the number of objects [i.e. links] in the group */
*num_objs = grp_info.nlinks;
done:
@@ -852,26 +924,40 @@ done:
*/
herr_t
H5Gget_objinfo(hid_t loc_id, const char *name, hbool_t follow_link,
- H5G_stat_t *statbuf/*out*/)
+ H5G_stat_t *statbuf/*out*/)
{
- H5G_loc_t loc; /* Group's location */
- herr_t ret_value = SUCCEED; /* Return value */
+ H5VL_object_t *vol_obj = NULL; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_API(FAIL)
+ FUNC_ENTER_API(FAIL);
H5TRACE4("e", "i*sbx", loc_id, name, follow_link, statbuf);
/* Check arguments */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
- if(!name || !*name)
+ if (!name || !*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified")
- /* Get info */
- if(H5G__get_objinfo(&loc, name, follow_link, statbuf) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "cannot stat object")
+ /* Set up collective metadata if appropriate */
+ if (H5CX_set_loc(loc_id) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTSET, FAIL, "can't set collective metadata read info");
+
+ /* Retrieve object info */
+ /* Fill out location struct */
+ loc_params.type = H5VL_OBJECT_BY_NAME;
+ loc_params.loc_data.loc_by_name.name = name;
+ loc_params.loc_data.loc_by_name.lapl_id = H5P_LINK_ACCESS_DEFAULT;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* Get the location object */
+ if (NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier");
+
+ /* Retrieve the object's information */
+ if (H5VL_group_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_GROUP_GET_OBJINFO, &loc_params, (unsigned)follow_link, statbuf) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get info for object: '%s'", name);
done:
- FUNC_LEAVE_API(ret_value)
+ FUNC_LEAVE_API(ret_value);
} /* end H5Gget_objinfo() */
@@ -895,44 +981,44 @@ H5G__get_objinfo_cb(H5G_loc_t H5_ATTR_UNUSED *grp_loc/*in*/, const char *name, c
H5G_trav_goi_t *udata = (H5G_trav_goi_t *)_udata; /* User data passed in */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_STATIC
+ FUNC_ENTER_STATIC;
/* Check if the name in this group resolved to a valid link */
- if(lnk == NULL && obj_loc == NULL)
- HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "'%s' doesn't exist", name)
+ if (lnk == NULL && obj_loc == NULL)
+ HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "'%s' doesn't exist", name);
- /* Only modify user's buffer if it's available */
- if(udata->statbuf) {
+ /* Only modify user's buffer if it's available */
+ if (udata->statbuf) {
H5G_stat_t *statbuf = udata->statbuf; /* Convenience pointer for statbuf */
/* Common code to retrieve the file's fileno */
- if(H5F_get_fileno((obj_loc ? obj_loc : grp_loc)->oloc->file, &statbuf->fileno[0]) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "unable to read fileno")
+ if (H5F_get_fileno((obj_loc ? obj_loc : grp_loc)->oloc->file, &statbuf->fileno[0]) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "unable to read fileno");
/* Info for soft and UD links is gotten by H5L_get_info. If we have
* a hard link, follow it and get info on the object
*/
- if(udata->follow_link || !lnk || (lnk->type == H5L_TYPE_HARD)) {
+ if (udata->follow_link || !lnk || (lnk->type == H5L_TYPE_HARD)) {
H5O_info_t oinfo; /* Object information */
/* Go retrieve the object information */
/* (don't need index & heap info) */
HDassert(obj_loc);
- if(H5O_get_info(obj_loc->oloc, &oinfo, H5O_INFO_BASIC|H5O_INFO_TIME|H5O_INFO_HDR) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to get object info")
+ if (H5O_get_info(obj_loc->oloc, &oinfo, H5O_INFO_BASIC|H5O_INFO_TIME|H5O_INFO_HDR) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to get object info");
/* Get mapped object type */
statbuf->type = H5G_map_obj_type(oinfo.type);
- /* Get object number (i.e. address) for object */
- statbuf->objno[0] = (unsigned long)(oinfo.addr);
+ /* Get object number (i.e. address) for object */
+ statbuf->objno[0] = (unsigned long)(oinfo.addr);
#if H5_SIZEOF_UINT64_T > H5_SIZEOF_LONG
- statbuf->objno[1] = (unsigned long)(oinfo.addr >> 8 * sizeof(long));
+ statbuf->objno[1] = (unsigned long)(oinfo.addr >> 8 * sizeof(long));
#else
- statbuf->objno[1] = 0;
+ statbuf->objno[1] = 0;
#endif
/* Get # of hard links pointing to object */
- statbuf->nlink = oinfo.rc;
+ statbuf->nlink = oinfo.rc;
/* Get modification time for object */
statbuf->mtime = oinfo.ctime;
@@ -942,15 +1028,15 @@ H5G__get_objinfo_cb(H5G_loc_t H5_ATTR_UNUSED *grp_loc/*in*/, const char *name, c
statbuf->ohdr.free = oinfo.hdr.space.free;
statbuf->ohdr.nmesgs = oinfo.hdr.nmesgs;
statbuf->ohdr.nchunks = oinfo.hdr.nchunks;
- } /* end if */
- } /* end if */
+ }
+ }
done:
/* Indicate that this callback didn't take ownership of the group *
* location for the object */
*own_loc = H5G_OWN_NONE;
- FUNC_LEAVE_NOAPI(ret_value)
+ FUNC_LEAVE_NOAPI(ret_value);
} /* end H5G__get_objinfo_cb() */
@@ -970,21 +1056,21 @@ done:
*
*-------------------------------------------------------------------------
*/
-static herr_t
+herr_t
H5G__get_objinfo(const H5G_loc_t *loc, const char *name, hbool_t follow_link,
H5G_stat_t *statbuf/*out*/)
{
H5G_trav_goi_t udata; /* User data for callback */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_STATIC
+ FUNC_ENTER_PACKAGE;
/* Sanity checks */
HDassert(loc);
HDassert(name && *name);
- /* Reset stat buffer, if one was given */
- if(statbuf)
+ /* Reset stat buffer */
+ if (statbuf)
HDmemset(statbuf, 0, sizeof(H5G_stat_t));
/* Set up user data for retrieving information */
@@ -993,12 +1079,11 @@ H5G__get_objinfo(const H5G_loc_t *loc, const char *name, hbool_t follow_link,
udata.loc_file = loc->oloc->file;
/* Traverse the group hierarchy to locate the object to get info about */
- if(H5G_traverse(loc, name, (unsigned)(follow_link ? H5G_TARGET_NORMAL : H5G_TARGET_SLINK|H5G_TARGET_UDLINK),
- H5G__get_objinfo_cb, &udata) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_EXISTS, FAIL, "name doesn't exist")
+ if (H5G_traverse(loc, name, (unsigned)(follow_link ? H5G_TARGET_NORMAL : (H5G_TARGET_SLINK | H5G_TARGET_UDLINK)), H5G__get_objinfo_cb, &udata) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_EXISTS, FAIL, "name doesn't exist");
/* If we're pointing at a soft or UD link, get the real link length and type */
- if(statbuf && follow_link == 0) {
+ if (statbuf && follow_link == 0) {
H5L_info_t linfo; /* Link information buffer */
herr_t ret;
@@ -1006,21 +1091,23 @@ H5G__get_objinfo(const H5G_loc_t *loc, const char *name, hbool_t follow_link,
* because the object is ".", just treat the object as a hard link. */
H5E_BEGIN_TRY {
ret = H5L_get_info(loc, name, &linfo);
- } H5E_END_TRY
+ } H5E_END_TRY;
- if(ret >= 0 && linfo.type != H5L_TYPE_HARD) {
+ if (ret >= 0 && linfo.type != H5L_TYPE_HARD) {
statbuf->linklen = linfo.u.val_size;
- if(linfo.type == H5L_TYPE_SOFT)
+ if (linfo.type == H5L_TYPE_SOFT) {
statbuf->type = H5G_LINK;
- else { /* UD link. H5L_get_info checked for invalid link classes */
+ }
+ else {
+ /* UD link. H5L_get_info checked for invalid link classes */
HDassert(linfo.type >= H5L_TYPE_UD_MIN && linfo.type <= H5L_TYPE_MAX);
statbuf->type = H5G_UDLINK;
- } /* end else */
- } /* end if */
- } /* end if */
+ }
+ }
+ }
done:
- FUNC_LEAVE_NOAPI(ret_value)
+ FUNC_LEAVE_NOAPI(ret_value);
} /* end H5G__get_objinfo() */
@@ -1050,24 +1137,33 @@ done:
ssize_t
H5Gget_objname_by_idx(hid_t loc_id, hsize_t idx, char *name, size_t size)
{
- H5G_loc_t loc; /* Object location */
- H5O_type_t obj_type; /* Type of object at location */
- ssize_t ret_value;
+ H5VL_object_t *vol_obj; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
+ ssize_t ret_value; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE4("Zs", "ih*sz", loc_id, idx, name, size);
- /* Check args */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location ID")
- if(H5O_obj_type(loc.oloc, &obj_type) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_CANTGET, FAIL, "can't get object type")
- if(obj_type != H5O_TYPE_GROUP)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group")
+ /* Set up collective metadata if appropriate */
+ if(H5CX_set_loc(loc_id) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTSET, (-1), "can't set collective metadata read info")
+
+ /* Fill in location struct fields */
+ loc_params.type = H5VL_OBJECT_BY_IDX;
+ loc_params.loc_data.loc_by_idx.name = ".";
+ loc_params.loc_data.loc_by_idx.idx_type = H5_INDEX_NAME;
+ loc_params.loc_data.loc_by_idx.order = H5_ITER_INC;
+ loc_params.loc_data.loc_by_idx.n = idx;
+ loc_params.loc_data.loc_by_idx.lapl_id = H5P_LINK_ACCESS_DEFAULT;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* Get the location object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "invalid location identifier")
/* Call internal function */
- if((ret_value = H5G_obj_get_name_by_idx(loc.oloc, H5_INDEX_NAME, H5_ITER_INC, idx, name, size)) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get object name")
+ if(H5VL_link_get(vol_obj, &loc_params, H5VL_LINK_GET_NAME, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, name, size, &ret_value) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, (-1), "can't get object name")
done:
FUNC_LEAVE_API(ret_value)
@@ -1092,82 +1188,39 @@ done:
H5G_obj_t
H5Gget_objtype_by_idx(hid_t loc_id, hsize_t idx)
{
- H5G_loc_t loc; /* Object location */
- H5G_obj_t ret_value;
+ H5VL_object_t *vol_obj; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
+ H5O_info_t oinfo; /* Object info (contains object type) */
+ unsigned fields; /* Which fields in object info to populate */
+ H5G_obj_t ret_value; /* Return value */
FUNC_ENTER_API(H5G_UNKNOWN)
H5TRACE2("Go", "ih", loc_id, idx);
- /* Check args */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5G_UNKNOWN, "not a location ID")
+ /* Set location parameters */
+ loc_params.type = H5VL_OBJECT_BY_IDX;
+ loc_params.loc_data.loc_by_idx.name = ".";
+ loc_params.loc_data.loc_by_idx.idx_type = H5_INDEX_NAME;
+ loc_params.loc_data.loc_by_idx.order = H5_ITER_INC;
+ loc_params.loc_data.loc_by_idx.n = idx;
+ loc_params.loc_data.loc_by_idx.lapl_id = H5P_LINK_ACCESS_DEFAULT;
+ loc_params.obj_type = H5I_get_type(loc_id);
- /* Call internal function*/
- if(H5G_UNKNOWN == (ret_value = H5G__obj_get_type_by_idx(loc.oloc, idx)))
- HGOTO_ERROR(H5E_SYM, H5E_BADTYPE, H5G_UNKNOWN, "can't get object type")
+ /* Get the location object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5G_UNKNOWN, "invalid location identifier")
-done:
- FUNC_LEAVE_API(ret_value)
-} /* end H5Gget_objtype_by_idx() */
+ /* Retrieve the object's basic information (which includes its type) */
+ fields = H5O_INFO_BASIC;
+ if(H5VL_object_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_OBJECT_GET_INFO, &loc_params, &oinfo, fields) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_BADTYPE, H5G_UNKNOWN, "can't get object info")
-
-/*-------------------------------------------------------------------------
- * Function: H5G__obj_get_type_by_idx
- *
- * Purpose: Private function for H5Gget_objtype_by_idx.
- * Returns the type of objects in the group by giving index.
- *
- * Return: Success: H5G_GROUP(1), H5G_DATASET(2), H5G_TYPE(3)
- *
- * Failure: Negative
- *
- * Programmer: Raymond Lu
- * Nov 20, 2002
- *
- *-------------------------------------------------------------------------
- */
-static H5G_obj_t
-H5G__obj_get_type_by_idx(H5O_loc_t *oloc, hsize_t idx)
-{
- H5O_linfo_t linfo; /* Link info message */
- htri_t linfo_exists; /* Whether the link info message exists */
- H5O_type_t obj_type; /* Type of object at location */
- H5G_obj_t ret_value = H5G_UNKNOWN; /* Return value */
-
- FUNC_ENTER_STATIC_TAG(oloc->addr)
-
- /* Sanity check */
- HDassert(oloc);
-
- /* Check args */
- if(H5O_obj_type(oloc, &obj_type) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5G_UNKNOWN, "can't get object type")
- if(obj_type != H5O_TYPE_GROUP)
- HGOTO_ERROR(H5E_SYM, H5E_BADTYPE, H5G_UNKNOWN, "not a group")
-
- /* Attempt to get the link info for this group */
- if((linfo_exists = H5G__obj_get_linfo(oloc, &linfo)) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5G_UNKNOWN, "can't check for link info message")
- if(linfo_exists) {
- if(H5F_addr_defined(linfo.fheap_addr)) {
- /* Get the object's name from the dense link storage */
- if((ret_value = H5G__dense_get_type_by_idx(oloc->file, &linfo, idx)) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5G_UNKNOWN, "can't locate type")
- } /* end if */
- else {
- /* Get the object's type from the link messages */
- if((ret_value = H5G__compact_get_type_by_idx(oloc, &linfo, idx)) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5G_UNKNOWN, "can't locate type")
- } /* end else */
- } /* end if */
- else {
- /* Get the object's type from the symbol table */
- if((ret_value = H5G__stab_get_type_by_idx(oloc, idx)) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5G_UNKNOWN, "can't locate type")
- } /* end else */
+ /* Map to group object type */
+ if(H5G_UNKNOWN == (ret_value = H5G_map_obj_type(oinfo.type)))
+ HGOTO_ERROR(H5E_SYM, H5E_BADTYPE, H5G_UNKNOWN, "can't determine object type")
done:
- FUNC_LEAVE_NOAPI_TAG(ret_value)
-} /* end H5G__obj_get_type_by_idx() */
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Gget_objtype_by_idx() */
#endif /* H5_NO_DEPRECATED_SYMBOLS */
diff --git a/src/H5Gent.c b/src/H5Gent.c
index baee35c..19aef10 100644
--- a/src/H5Gent.c
+++ b/src/H5Gent.c
@@ -32,6 +32,7 @@
#include "H5FLprivate.h" /* Free Lists */
#include "H5Gpkg.h" /* Groups */
#include "H5HLprivate.h" /* Local Heaps */
+#include "H5MMprivate.h" /* Memory management */
/****************/
@@ -331,7 +332,7 @@ H5G__ent_copy(H5G_entry_t *dst, const H5G_entry_t *src, H5_copy_depth_t depth)
HDassert(depth == H5_COPY_SHALLOW || depth == H5_COPY_DEEP);
/* Copy the top level information */
- HDmemcpy(dst, src, sizeof(H5G_entry_t));
+ H5MM_memcpy(dst, src, sizeof(H5G_entry_t));
/* Deep copy the names */
if(depth == H5_COPY_DEEP) {
diff --git a/src/H5Gint.c b/src/H5Gint.c
index 7e2f279..049c696 100644
--- a/src/H5Gint.c
+++ b/src/H5Gint.c
@@ -578,7 +578,7 @@ H5G_oloc(H5G_t *grp)
*-------------------------------------------------------------------------
*/
H5G_name_t *
-H5G_nameof(H5G_t *grp)
+H5G_nameof(const H5G_t *grp)
{
/* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
FUNC_ENTER_NOAPI_NOINIT_NOERR
@@ -807,7 +807,7 @@ H5G_iterate(H5G_loc_t *loc, const char *group_name,
*/
if(NULL == (grp = H5G__open_name(loc, group_name)))
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group")
- if((gid = H5I_register(H5I_GROUP, grp, TRUE)) < 0)
+ if((gid = H5VL_wrap_register(H5I_GROUP, grp, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register group")
/* Set up user data for callback */
@@ -1069,7 +1069,7 @@ H5G_visit(H5G_loc_t *loc, const char *group_name, H5_index_t idx_type,
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group")
/* Register an ID for the starting group */
- if((gid = H5I_register(H5I_GROUP, grp, TRUE)) < 0)
+ if((gid = H5VL_wrap_register(H5I_GROUP, grp, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register group")
/* Get the location of the starting group */
diff --git a/src/H5Glink.c b/src/H5Glink.c
index 82a2dcf..04ccbc5 100644
--- a/src/H5Glink.c
+++ b/src/H5Glink.c
@@ -402,15 +402,14 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5G__link_sort_table
+ * Function: H5G__link_sort_table
*
* Purpose: Sort table containing a list of links for a group
*
- * Return: Success: Non-negative
- * Failure: Negative
+ * Return: SUCCEED/FAIL
*
- * Programmer: Quincey Koziol
- * Nov 20, 2006
+ * Programmer: Quincey Koziol
+ * Nov 20, 2006
*
*-------------------------------------------------------------------------
*/
@@ -418,11 +417,20 @@ herr_t
H5G__link_sort_table(H5G_link_table_t *ltable, H5_index_t idx_type,
H5_iter_order_t order)
{
+ herr_t ret_value = SUCCEED;
+
FUNC_ENTER_PACKAGE_NOERR
/* Sanity check */
HDassert(ltable);
+ /* Can't sort when empty since the links table will be NULL */
+ if(0 == ltable->nlinks)
+ HGOTO_DONE(ret_value);
+
+ /* This should never be NULL if the number of links is non-zero */
+ HDassert(ltable->lnks);
+
/* Pick appropriate sorting routine */
if(idx_type == H5_INDEX_NAME) {
if(order == H5_ITER_INC)
@@ -442,6 +450,7 @@ H5G__link_sort_table(H5G_link_table_t *ltable, H5_index_t idx_type,
HDassert(order == H5_ITER_NATIVE);
} /* end else */
+done:
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5G__link_sort_table() */
diff --git a/src/H5Gloc.c b/src/H5Gloc.c
index 2f935e8..40d56c6 100644
--- a/src/H5Gloc.c
+++ b/src/H5Gloc.c
@@ -137,29 +137,25 @@ static herr_t H5G__loc_get_comment_cb(H5G_loc_t *grp_loc, const char *name,
/*-------------------------------------------------------------------------
- * Function: H5G_loc
+ * Function: H5G_loc_real
*
- * Purpose: Given an object ID return a location for the object.
+ * Purpose: Utility routine to get object location
*
* Returns: SUCCEED/FAIL
*
*-------------------------------------------------------------------------
*/
herr_t
-H5G_loc(hid_t loc_id, H5G_loc_t *loc)
+H5G_loc_real(void *obj, H5I_type_t type, H5G_loc_t *loc)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
- switch(H5I_get_type(loc_id)) {
+ switch(type) {
case H5I_FILE:
{
- H5F_t *f = NULL;
-
- /* Get the file struct */
- if(NULL == (f = (H5F_t *)H5I_object(loc_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file ID")
+ H5F_t *f = (H5F_t *)obj;
/* Construct a group location for root group of the file */
if(H5G_root_loc(f, loc) < 0)
@@ -169,10 +165,8 @@ H5G_loc(hid_t loc_id, H5G_loc_t *loc)
case H5I_GROUP:
{
- H5G_t *group = NULL;
+ H5G_t *group = (H5G_t *)obj;
- if(NULL == (group = (H5G_t *)H5I_object(loc_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid group ID")
if(NULL == (loc->oloc = H5G_oloc(group)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get object location of group")
if(NULL == (loc->path = H5G_nameof(group)))
@@ -184,8 +178,9 @@ H5G_loc(hid_t loc_id, H5G_loc_t *loc)
{
H5T_t *dt = NULL;
- if(NULL == (dt = (H5T_t *)H5I_object(loc_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid type ID")
+ /* Get the actual datatype object if the VOL object is set */
+ dt = H5T_get_actual_type((H5T_t *)obj);
+
if(NULL == (loc->oloc = H5T_oloc(dt)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get object location of datatype")
if(NULL == (loc->path = H5T_nameof(dt)))
@@ -195,10 +190,8 @@ H5G_loc(hid_t loc_id, H5G_loc_t *loc)
case H5I_DATASET:
{
- H5D_t *dset = NULL;
+ H5D_t *dset = (H5D_t *)obj;
- if(NULL == (dset = (H5D_t *)H5I_object(loc_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid data ID")
if(NULL == (loc->oloc = H5D_oloc(dset)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get object location of dataset")
if(NULL == (loc->path = H5D_nameof(dset)))
@@ -208,10 +201,8 @@ H5G_loc(hid_t loc_id, H5G_loc_t *loc)
case H5I_ATTR:
{
- H5A_t *attr = NULL;
+ H5A_t *attr = (H5A_t *)obj;
- if(NULL == (attr = (H5A_t *)H5I_object(loc_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid attribute ID")
if(NULL == (loc->oloc = H5A_oloc(attr)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get object location of attribute")
if(NULL == (loc->path = H5A_nameof(attr)))
@@ -219,12 +210,12 @@ H5G_loc(hid_t loc_id, H5G_loc_t *loc)
break;
}
- case H5I_REFERENCE:
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get group location of reference")
-
case H5I_DATASPACE:
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get group location of dataspace")
+ case H5I_MAP:
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "maps not supported in native VOL connector")
+
case H5I_GENPROP_CLS:
case H5I_GENPROP_LST:
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get group location of property list")
@@ -237,6 +228,12 @@ H5G_loc(hid_t loc_id, H5G_loc_t *loc)
case H5I_VFL:
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get group location of a virtual file driver (VFD)")
+ case H5I_VOL:
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get group location of a virtual object layer (VOL) connector")
+
+ case H5I_SPACE_SEL_ITER:
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get group location of a dataspace selection iterator")
+
case H5I_UNINIT:
case H5I_BADID:
case H5I_NTYPES:
@@ -246,6 +243,36 @@ H5G_loc(hid_t loc_id, H5G_loc_t *loc)
done:
FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5G_loc_real() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_loc
+ *
+ * Purpose: Given an object ID return a location for the object.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_loc(hid_t loc_id, H5G_loc_t *loc)
+{
+ void *obj = NULL; /* VOL object */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Get the object from the VOL */
+ if(NULL == (obj = H5VL_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Fill in the struct */
+ if(H5G_loc_real(obj, H5I_get_type(loc_id), loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "unable to fill in location struct")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5G_loc() */
diff --git a/src/H5Gname.c b/src/H5Gname.c
index 31ed0f1..86a0c2f 100644
--- a/src/H5Gname.c
+++ b/src/H5Gname.c
@@ -522,7 +522,7 @@ H5G_name_copy(H5G_name_t *dst, const H5G_name_t *src, H5_copy_depth_t depth)
HDassert(depth == H5_COPY_SHALLOW || depth == H5_COPY_DEEP);
/* Copy the top level information */
- HDmemcpy(dst, src, sizeof(H5G_name_t));
+ H5MM_memcpy(dst, src, sizeof(H5G_name_t));
/* Deep copy the names */
if(depth == H5_COPY_DEEP) {
@@ -584,21 +584,9 @@ H5G_get_name(const H5G_loc_t *loc, char *name/*out*/, size_t size,
*cached = TRUE;
} /* end if */
else if(!loc->path->obj_hidden) {
- hid_t file;
-
- /* Retrieve file ID for name search */
- if((file = H5F_get_id(loc->oloc->file, FALSE)) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get file ID")
-
/* Search for name of object */
- if((len = H5G_get_name_by_addr(file, loc->oloc, name, size)) < 0) {
- H5I_dec_ref(file);
+ if((len = H5G_get_name_by_addr(loc->oloc->file, loc->oloc, name, size)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't determine name")
- } /* end if */
-
- /* Close file ID used for search */
- if(H5I_dec_ref(file) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTCLOSEFILE, FAIL, "can't determine name")
/* Indicate that the name is _not_ cached, if requested */
/* (Currently only used for testing - QAK, 2010/07/26) */
@@ -828,18 +816,22 @@ H5G_name_replace_cb(void *obj_ptr, hid_t obj_id, void *key)
obj_path = H5T_nameof((H5T_t *)obj_ptr);
break;
+ case H5I_MAP:
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "maps not supported in native VOL connector")
+
case H5I_UNINIT:
case H5I_BADID:
case H5I_FILE:
case H5I_DATASPACE:
case H5I_ATTR:
- case H5I_REFERENCE:
case H5I_VFL:
+ case H5I_VOL:
case H5I_GENPROP_CLS:
case H5I_GENPROP_LST:
case H5I_ERROR_CLASS:
case H5I_ERROR_MSG:
case H5I_ERROR_STACK:
+ case H5I_SPACE_SEL_ITER:
case H5I_NTYPES:
default:
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "unknown data object")
@@ -1123,6 +1115,9 @@ H5G_name_replace(const H5O_link_t *lnk, H5G_names_op_t op, H5F_t *src_file,
search_datatype = TRUE;
break;
+ case H5O_TYPE_MAP:
+ HGOTO_ERROR(H5E_SYM, H5E_BADTYPE, FAIL, "maps not supported in native VOL connector")
+
case H5O_TYPE_UNKNOWN:
case H5O_TYPE_NTYPES:
/* Search and replace names through datatype IDs */
@@ -1281,8 +1276,7 @@ done:
*-------------------------------------------------------------------------
*/
ssize_t
-H5G_get_name_by_addr(hid_t file, const H5O_loc_t *loc,
- char *name, size_t size)
+H5G_get_name_by_addr(H5F_t *f, const H5O_loc_t *loc, char *name, size_t size)
{
H5G_gnba_iter_t udata; /* User data for iteration */
H5G_loc_t root_loc; /* Root group's location */
@@ -1295,8 +1289,8 @@ H5G_get_name_by_addr(hid_t file, const H5O_loc_t *loc,
FUNC_ENTER_NOAPI((-1))
- /* Construct the link info for the file's root group */
- if(H5G_loc(file, &root_loc) < 0)
+ /* Construct a group location for root group of the file */
+ if(H5G_root_loc(f, &root_loc) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTGET, (-1), "can't get root group's location")
/* Check for root group being the object looked for */
diff --git a/src/H5Gnode.c b/src/H5Gnode.c
index 72b3633..b79b7d2 100644
--- a/src/H5Gnode.c
+++ b/src/H5Gnode.c
@@ -672,7 +672,7 @@ H5G__node_insert(H5F_t *f, haddr_t addr, void H5_ATTR_UNUSED *_lt_key,
if(NULL == (snrt = (H5G_node_t *)H5AC_protect(f, H5AC_SNODE, *new_node_p, f, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_INS_ERROR, "unable to split symbol table node")
- HDmemcpy(snrt->entry, sn->entry + H5F_SYM_LEAF_K(f),
+ H5MM_memcpy(snrt->entry, sn->entry + H5F_SYM_LEAF_K(f),
H5F_SYM_LEAF_K(f) * sizeof(H5G_entry_t));
snrt->nsyms = H5F_SYM_LEAF_K(f);
snrt_flags |= H5AC__DIRTIED_FLAG;
@@ -1262,7 +1262,7 @@ H5G__node_copy(H5F_t *f, const void H5_ATTR_UNUSED *_lt_key, haddr_t addr,
char *link_name; /* Pointer to value of soft link */
/* Make a temporary copy, so that it will not change the info in the cache */
- HDmemcpy(&tmp_src_ent, src_ent, sizeof(H5G_entry_t));
+ H5MM_memcpy(&tmp_src_ent, src_ent, sizeof(H5G_entry_t));
/* Set up group location for soft link to start in */
H5G_name_reset(&grp_path);
diff --git a/src/H5Goh.c b/src/H5Goh.c
index ec3d30d..f29529b 100644
--- a/src/H5Goh.c
+++ b/src/H5Goh.c
@@ -27,6 +27,7 @@
#include "H5Gpkg.h" /* Groups */
#include "H5Iprivate.h" /* IDs */
#include "H5Opkg.h" /* Object headers */
+#include "H5VLprivate.h" /* Virtual Object Layer */
/****************/
@@ -46,7 +47,7 @@
static void *H5O__group_get_copy_file_udata(void);
static void H5O__group_free_copy_file_udata(void *udata);
static htri_t H5O__group_isa(const H5O_t *loc);
-static hid_t H5O__group_open(const H5G_loc_t *obj_loc, hbool_t app_ref);
+static void *H5O__group_open(const H5G_loc_t *obj_loc, H5I_type_t *opened_type);
static void *H5O__group_create(H5F_t *f, void *_crt_info, H5G_loc_t *obj_loc);
static H5O_loc_t *H5O__group_get_oloc(hid_t obj_id);
static herr_t H5O__group_bh_info(const H5O_loc_t *loc, H5O_t *oh,
@@ -197,36 +198,36 @@ done:
*
* Purpose: Open a group at a particular location
*
- * Return: Success: Open object identifier
- * Failure: Negative
+ * Return: Success: Pointer to group data
+ * Failure: NULL
*
* Programmer: Quincey Koziol
* Monday, November 6, 2006
*
*-------------------------------------------------------------------------
*/
-static hid_t
-H5O__group_open(const H5G_loc_t *obj_loc, hbool_t app_ref)
+static void *
+H5O__group_open(const H5G_loc_t *obj_loc, H5I_type_t *opened_type)
{
- H5G_t *grp = NULL; /* Group opened */
- hid_t ret_value = H5I_INVALID_HID; /* Return value */
+ H5G_t *grp = NULL; /* Group opened */
+ void *ret_value = NULL; /* Return value */
FUNC_ENTER_STATIC
HDassert(obj_loc);
+ *opened_type = H5I_GROUP;
+
/* Open the group */
if(NULL == (grp = H5G_open(obj_loc)))
- HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group")
+ HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, NULL, "unable to open group")
- /* Register an ID for the group */
- if((ret_value = H5I_register(H5I_GROUP, grp, app_ref)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register group")
+ ret_value = (void *)grp;
done:
- if(ret_value < 0)
+ if(NULL == ret_value)
if(grp && H5G_close(grp) < 0)
- HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "unable to release group")
+ HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, NULL, "unable to release group")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O__group_open() */
@@ -303,7 +304,7 @@ H5O__group_get_oloc(hid_t obj_id)
FUNC_ENTER_STATIC
/* Get the group */
- if(NULL == (grp = (H5G_t *)H5I_object(obj_id)))
+ if(NULL == (grp = (H5G_t *)H5VL_object(obj_id)))
HGOTO_ERROR(H5E_OHDR, H5E_BADATOM, NULL, "couldn't get object from ID")
/* Get the group's object header location */
diff --git a/src/H5Gpkg.h b/src/H5Gpkg.h
index 836213d..f475bde 100644
--- a/src/H5Gpkg.h
+++ b/src/H5Gpkg.h
@@ -381,9 +381,6 @@ H5_DLL herr_t H5G__stab_lookup_by_idx(const H5O_loc_t *grp_oloc, H5_iter_order_t
#ifndef H5_STRICT_FORMAT_CHECKS
H5_DLL herr_t H5G__stab_valid(H5O_loc_t *grp_oloc, H5O_stab_t *alt_stab);
#endif /* H5_STRICT_FORMAT_CHECKS */
-#ifndef H5_NO_DEPRECATED_SYMBOLS
-H5_DLL H5G_obj_t H5G__stab_get_type_by_idx(H5O_loc_t *oloc, hsize_t idx);
-#endif /* H5_NO_DEPRECATED_SYMBOLS */
/*
@@ -448,10 +445,6 @@ H5_DLL htri_t H5G__compact_lookup(const H5O_loc_t *grp_oloc, const char *name,
H5_DLL herr_t H5G__compact_lookup_by_idx(const H5O_loc_t *oloc,
const H5O_linfo_t *linfo, H5_index_t idx_type, H5_iter_order_t order,
hsize_t n, H5O_link_t *lnk);
-#ifndef H5_NO_DEPRECATED_SYMBOLS
-H5_DLL H5G_obj_t H5G__compact_get_type_by_idx(H5O_loc_t *oloc,
- const H5O_linfo_t *linfo, hsize_t idx);
-#endif /* H5_NO_DEPRECATED_SYMBOLS */
/* Functions that understand "dense" link storage */
H5_DLL herr_t H5G__dense_build_table(H5F_t *f, const H5O_linfo_t *linfo,
@@ -476,10 +469,6 @@ H5_DLL herr_t H5G__dense_remove_by_idx(H5F_t *f, const H5O_linfo_t *linfo,
H5RS_str_t *grp_full_path_r, H5_index_t idx_type, H5_iter_order_t order,
hsize_t n);
H5_DLL herr_t H5G__dense_delete(H5F_t *f, H5O_linfo_t *linfo, hbool_t adj_link);
-#ifndef H5_NO_DEPRECATED_SYMBOLS
-H5_DLL H5G_obj_t H5G__dense_get_type_by_idx(H5F_t *f, H5O_linfo_t *linfo,
- hsize_t idx);
-#endif /* H5_NO_DEPRECATED_SYMBOLS */
/* Functions that understand group objects */
H5_DLL herr_t H5G__obj_create(H5F_t *f, H5G_obj_create_t *gcrt_info,
@@ -494,6 +483,10 @@ H5_DLL herr_t H5G__obj_iterate(const H5O_loc_t *grp_oloc,
H5_DLL herr_t H5G__obj_info(const H5O_loc_t *oloc, H5G_info_t *grp_info);
H5_DLL htri_t H5G__obj_lookup(const H5O_loc_t *grp_oloc, const char *name,
H5O_link_t *lnk);
+#ifndef H5_NO_DEPRECATED_SYMBOLS
+H5_DLL herr_t H5G__get_objinfo(const H5G_loc_t *loc, const char *name,
+ hbool_t follow_link, H5G_stat_t *statbuf/*out*/);
+#endif /* H5_NO_DEPRECATED_SYMBOLS */
/*
* These functions operate on group hierarchy names.
diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h
index c56b1c8..f149f29 100644
--- a/src/H5Gprivate.h
+++ b/src/H5Gprivate.h
@@ -187,7 +187,7 @@ typedef struct H5G_entry_t H5G_entry_t;
* call.
*/
H5_DLL struct H5O_loc_t *H5G_oloc(H5G_t *grp);
-H5_DLL H5G_name_t * H5G_nameof(H5G_t *grp);
+H5_DLL H5G_name_t * H5G_nameof(const H5G_t *grp);
H5_DLL H5F_t *H5G_fileof(H5G_t *grp);
H5_DLL H5G_t *H5G_open(const H5G_loc_t *loc);
H5_DLL herr_t H5G_close(H5G_t *grp);
@@ -261,13 +261,14 @@ H5_DLL herr_t H5G_name_copy(H5G_name_t *dst, const H5G_name_t *src, H5_copy_dept
H5_DLL herr_t H5G_name_free(H5G_name_t *name);
H5_DLL ssize_t H5G_get_name(const H5G_loc_t *loc, char *name/*out*/, size_t size,
hbool_t *cached);
-H5_DLL ssize_t H5G_get_name_by_addr(hid_t fid, const struct H5O_loc_t *loc,
+H5_DLL ssize_t H5G_get_name_by_addr(H5F_t *f, const struct H5O_loc_t *loc,
char* name, size_t size);
H5_DLL H5RS_str_t *H5G_build_fullpath_refstr_str(H5RS_str_t *path_r, const char *name);
/*
* These functions operate on group "locations"
*/
+H5_DLL herr_t H5G_loc_real(void *obj, H5I_type_t type, H5G_loc_t *loc);
H5_DLL herr_t H5G_loc(hid_t loc_id, H5G_loc_t *loc);
H5_DLL herr_t H5G_loc_copy(H5G_loc_t *dst, const H5G_loc_t *src, H5_copy_depth_t depth);
H5_DLL herr_t H5G_loc_find(const H5G_loc_t *loc, const char *name,
diff --git a/src/H5Gpublic.h b/src/H5Gpublic.h
index ab6f200..170b74d 100644
--- a/src/H5Gpublic.h
+++ b/src/H5Gpublic.h
@@ -37,10 +37,6 @@
/* Public Macros */
/*****************/
-#ifdef __cplusplus
-extern "C" {
-#endif
-
/*******************/
/* Public Typedefs */
/*******************/
@@ -62,6 +58,7 @@ typedef struct H5G_info_t {
hbool_t mounted; /* Whether group has a file mounted on it */
} H5G_info_t;
+
/********************/
/* Public Variables */
/********************/
@@ -70,6 +67,10 @@ typedef struct H5G_info_t {
/*********************/
/* Public Prototypes */
/*********************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
H5_DLL hid_t H5Gcreate2(hid_t loc_id, const char *name, hid_t lcpl_id,
hid_t gcpl_id, hid_t gapl_id);
H5_DLL hid_t H5Gcreate_anon(hid_t loc_id, hid_t gcpl_id, hid_t gapl_id);
diff --git a/src/H5Gstab.c b/src/H5Gstab.c
index 9072b97..e8d38b9 100644
--- a/src/H5Gstab.c
+++ b/src/H5Gstab.c
@@ -1103,118 +1103,3 @@ done:
} /* end H5G__stab_valid */
#endif /* H5_STRICT_FORMAT_CHECKS */
-#ifndef H5_NO_DEPRECATED_SYMBOLS
-
-/*-------------------------------------------------------------------------
- * Function: H5G_stab_get_type_by_idx_cb
- *
- * Purpose: Callback for B-tree iteration 'by index' info query to
- * retrieve the type of an object
- *
- * Return: Success: Non-negative
- * Failure: Negative
- *
- * Programmer: Quincey Koziol
- * Nov 7, 2006
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5G_stab_get_type_by_idx_cb(const H5G_entry_t *ent, void *_udata)
-{
- H5G_bt_it_gtbi_t *udata = (H5G_bt_it_gtbi_t *)_udata;
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT
-
- /* Sanity check */
- HDassert(ent);
- HDassert(udata);
-
- /* Check for a soft link */
- switch(ent->type) {
- case H5G_CACHED_SLINK:
- udata->type = H5G_LINK;
- break;
-
- case H5G_CACHED_ERROR:
- case H5G_NOTHING_CACHED:
- case H5G_CACHED_STAB:
- case H5G_NCACHED:
- default:
- {
- H5O_loc_t tmp_oloc; /* Temporary object location */
- H5O_type_t obj_type; /* Type of object at location */
-
- /* Build temporary object location */
- tmp_oloc.file = udata->f;
- HDassert(H5F_addr_defined(ent->header));
- tmp_oloc.addr = ent->header;
-
- /* Get the type of the object */
- if(H5O_obj_type(&tmp_oloc, &obj_type) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get object type")
- udata->type = H5G_map_obj_type(obj_type);
- }
- break;
- } /* end switch */
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5G_stab_get_type_by_idx_cb */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5G__stab_get_type_by_idx
- *
- * Purpose: Private function for H5Gget_objtype_by_idx.
- * Returns the type of objects in the group by giving index.
- *
- * Return: Success: H5G_GROUP(1), H5G_DATASET(2), H5G_TYPE(3)
- *
- * Failure: UNKNOWN
- *
- * Programmer: Raymond Lu
- * Nov 20, 2002
- *
- *-------------------------------------------------------------------------
- */
-H5G_obj_t
-H5G__stab_get_type_by_idx(H5O_loc_t *oloc, hsize_t idx)
-{
- H5O_stab_t stab; /* Info about local heap & B-tree */
- H5G_bt_it_gtbi_t udata; /* User data for B-tree callback */
- H5G_obj_t ret_value = H5G_UNKNOWN; /* Return value */
-
- FUNC_ENTER_PACKAGE_TAG(oloc->addr)
-
- /* Sanity check */
- HDassert(oloc);
-
- /* Get the B-tree & local heap info */
- if(NULL == H5O_msg_read(oloc, H5O_STAB_ID, &stab))
- HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5G_UNKNOWN, "unable to determine local heap address")
-
- /* Set iteration information */
- udata.common.idx = idx;
- udata.common.num_objs = 0;
- udata.common.op = H5G_stab_get_type_by_idx_cb;
- udata.f = oloc->file;
- udata.type = H5G_UNKNOWN;
-
- /* Iterate over the group members */
- if(H5B_iterate(oloc->file, H5B_SNODE, stab.btree_addr, H5G__node_by_idx, &udata) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5G_UNKNOWN, "iteration operator failed")
-
- /* If we don't know the type now, we almost certainly went out of bounds */
- if(udata.type == H5G_UNKNOWN)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5G_UNKNOWN, "index out of bound")
-
- /* Set the return value */
- ret_value = udata.type;
-
-done:
- FUNC_LEAVE_NOAPI_TAG(ret_value)
-} /* end H5G__stab_get_type_by_idx() */
-#endif /* H5_NO_DEPRECATED_SYMBOLS */
-
diff --git a/src/H5Gtest.c b/src/H5Gtest.c
index 1899606..f9ab6f2 100644
--- a/src/H5Gtest.c
+++ b/src/H5Gtest.c
@@ -35,6 +35,8 @@
#include "H5Gpkg.h" /* Groups */
#include "H5HLprivate.h" /* Local Heaps */
#include "H5Iprivate.h" /* IDs */
+#include "H5VLprivate.h" /* Virtual Object Layer */
+
/****************/
/* Local Macros */
@@ -102,7 +104,7 @@ H5G__is_empty_test(hid_t gid)
FUNC_ENTER_PACKAGE
/* Get group structure */
- if(NULL == (grp = (H5G_t *)H5I_object_verify(gid, H5I_GROUP)))
+ if(NULL == (grp = (H5G_t *)H5VL_object_verify(gid, H5I_GROUP)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group")
/* Set API context */
@@ -222,7 +224,7 @@ H5G__has_links_test(hid_t gid, unsigned *nmsgs)
FUNC_ENTER_PACKAGE
/* Get group structure */
- if(NULL == (grp = (H5G_t *)H5I_object_verify(gid, H5I_GROUP)))
+ if(NULL == (grp = (H5G_t *)H5VL_object_verify(gid, H5I_GROUP)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group")
/* Set API context */
@@ -289,7 +291,7 @@ H5G__has_stab_test(hid_t gid)
FUNC_ENTER_PACKAGE
/* Get group structure */
- if(NULL == (grp = (H5G_t *)H5I_object_verify(gid, H5I_GROUP)))
+ if(NULL == (grp = (H5G_t *)H5VL_object_verify(gid, H5I_GROUP)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group")
/* Set API context */
@@ -348,7 +350,7 @@ H5G__is_new_dense_test(hid_t gid)
FUNC_ENTER_PACKAGE
/* Get group structure */
- if(NULL == (grp = (H5G_t *)H5I_object_verify(gid, H5I_GROUP)))
+ if(NULL == (grp = (H5G_t *)H5VL_object_verify(gid, H5I_GROUP)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group")
/* Set API context */
@@ -427,7 +429,7 @@ H5G__new_dense_info_test(hid_t gid, hsize_t *name_count, hsize_t *corder_count)
FUNC_ENTER_PACKAGE
/* Get group structure */
- if(NULL == (grp = (H5G_t *)H5I_object_verify(gid, H5I_GROUP)))
+ if(NULL == (grp = (H5G_t *)H5VL_object_verify(gid, H5I_GROUP)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group")
/* Set API context */
@@ -515,7 +517,7 @@ H5G__lheap_size_test(hid_t gid, size_t *lheap_size)
FUNC_ENTER_PACKAGE
/* Get group structure */
- if(NULL == (grp = (H5G_t *)H5I_object_verify(gid, H5I_GROUP)))
+ if(NULL == (grp = (H5G_t *)H5VL_object_verify(gid, H5I_GROUP)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group")
/* Set API context */
@@ -576,7 +578,7 @@ H5G__user_path_test(hid_t obj_id, char *user_path, size_t *user_path_len, unsign
HDassert(obj_hidden);
/* Get pointer to object for ID */
- if(NULL == (obj_ptr = H5I_object(obj_id)))
+ if(NULL == (obj_ptr = H5VL_object(obj_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get object for ID")
/* Set API context */
@@ -602,18 +604,22 @@ H5G__user_path_test(hid_t obj_id, char *user_path, size_t *user_path_len, unsign
obj_path = H5T_nameof((H5T_t *)obj_ptr);
break;
+ case H5I_MAP:
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "maps not supported in native VOL connector")
+
case H5I_UNINIT:
case H5I_BADID:
case H5I_FILE:
case H5I_DATASPACE:
case H5I_ATTR:
- case H5I_REFERENCE:
case H5I_VFL:
+ case H5I_VOL:
case H5I_GENPROP_CLS:
case H5I_GENPROP_LST:
case H5I_ERROR_CLASS:
case H5I_ERROR_MSG:
case H5I_ERROR_STACK:
+ case H5I_SPACE_SEL_ITER:
case H5I_NTYPES:
default:
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "unknown data object type")
@@ -829,7 +835,7 @@ H5G__verify_cached_stabs_test(hid_t gid)
HDassert(gid >= 0);
/* Check args */
- if(NULL == (grp = (H5G_t *)H5I_object_verify(gid, H5I_GROUP)))
+ if(NULL == (grp = (H5G_t *)H5VL_object_verify(gid, H5I_GROUP)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group")
/* Set up metadata tagging */
diff --git a/src/H5Gtraverse.c b/src/H5Gtraverse.c
index e412e7c..492b5b9 100644
--- a/src/H5Gtraverse.c
+++ b/src/H5Gtraverse.c
@@ -197,7 +197,7 @@ H5G__traverse_ud(const H5G_loc_t *grp_loc/*in,out*/, const H5O_link_t *lnk,
/* Create a group ID to pass to the user-defined callback */
if(NULL == (grp = H5G_open(&grp_loc_copy)))
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group")
- if((cur_grp = H5I_register(H5I_GROUP, grp, FALSE)) < 0)
+ if((cur_grp = H5VL_wrap_register(H5I_GROUP, grp, FALSE)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTREGISTER, FAIL, "unable to register group")
/* User-defined callback function */
@@ -555,7 +555,7 @@ H5G__traverse_real(const H5G_loc_t *_loc, const char *name, unsigned target,
* Copy the component name into a null-terminated buffer so
* we can pass it down to the other symbol table functions.
*/
- HDmemcpy(comp, name, nchars);
+ H5MM_memcpy(comp, name, nchars);
comp[nchars] = '\0';
/*
@@ -670,7 +670,7 @@ H5G__traverse_real(const H5G_loc_t *_loc, const char *name, unsigned target,
/* Only keep the creation order information from the parent
* group's link info
*/
- HDmemcpy(&tmp_linfo, &def_linfo, sizeof(H5O_linfo_t));
+ H5MM_memcpy(&tmp_linfo, &def_linfo, sizeof(H5O_linfo_t));
tmp_linfo.track_corder = par_linfo.track_corder;
tmp_linfo.index_corder = par_linfo.index_corder;
linfo = &tmp_linfo;
diff --git a/src/H5HF.c b/src/H5HF.c
index 3df7e7b..5d52ca4 100644
--- a/src/H5HF.c
+++ b/src/H5HF.c
@@ -42,6 +42,8 @@
#include "H5FOprivate.h" /* File objects */
#include "H5HFpkg.h" /* Fractal heaps */
#include "H5MFprivate.h" /* File memory management */
+#include "H5MMprivate.h" /* Memory management */
+
/****************/
/* Local Macros */
@@ -104,7 +106,7 @@ H5HF_op_read(const void *obj, size_t obj_len, void *op_data)
FUNC_ENTER_NOAPI_NOINIT_NOERR
/* Perform "read", using memcpy() */
- HDmemcpy(op_data, obj, obj_len);
+ H5MM_memcpy(op_data, obj, obj_len);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5HF_op_read() */
@@ -129,7 +131,7 @@ H5HF_op_write(const void *obj, size_t obj_len, void *op_data)
FUNC_ENTER_NOAPI_NOINIT_NOERR
/* Perform "write", using memcpy() */
- HDmemcpy((void *)obj, op_data, obj_len); /* Casting away const OK -QAK */
+ H5MM_memcpy((void *)obj, op_data, obj_len); /* Casting away const OK -QAK */
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5HF_op_write() */
diff --git a/src/H5HFcache.c b/src/H5HFcache.c
index 19d2282..be41c6b 100644
--- a/src/H5HFcache.c
+++ b/src/H5HFcache.c
@@ -775,7 +775,7 @@ H5HF__cache_hdr_serialize(const H5F_t *f, void *_image, size_t len,
hdr->f = f;
/* Magic number */
- HDmemcpy(image, H5HF_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ H5MM_memcpy(image, H5HF_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
image += H5_SIZEOF_MAGIC;
/* Version # */
@@ -1365,7 +1365,7 @@ H5HF__cache_iblock_serialize(const H5F_t *f, void *_image, size_t len,
hdr->f = f;
/* Magic number */
- HDmemcpy(image, H5HF_IBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ H5MM_memcpy(image, H5HF_IBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
image += H5_SIZEOF_MAGIC;
/* Version # */
@@ -1680,7 +1680,7 @@ H5HF__cache_dblock_verify_chksum(const void *_image, size_t len, void *_udata)
/* Set up parameters for filter pipeline */
nbytes = len;
filter_mask = udata->filter_mask;
- HDmemcpy(read_buf, image, len);
+ H5MM_memcpy(read_buf, image, len);
/* Push direct block data through I/O filter pipeline */
if(H5Z_pipeline(&(hdr->pline), H5Z_FLAG_REVERSE, &filter_mask, H5Z_ENABLE_EDC, filter_cb, &nbytes, &len, &read_buf) < 0)
@@ -1727,7 +1727,7 @@ H5HF__cache_dblock_verify_chksum(const void *_image, size_t len, void *_udata)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
/* Copy un-filtered data into block's buffer */
- HDmemcpy(udata->dblk, read_buf, len);
+ H5MM_memcpy(udata->dblk, read_buf, len);
} /* end if */
done:
@@ -1832,7 +1832,7 @@ H5HF__cache_dblock_deserialize(const void *_image, size_t len, void *_udata,
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, NULL, "memory allocation failed for pipeline buffer")
/* Copy compressed image into buffer */
- HDmemcpy(read_buf, image, len);
+ H5MM_memcpy(read_buf, image, len);
/* Push direct block data through I/O filter pipeline */
nbytes = len;
@@ -1844,7 +1844,7 @@ H5HF__cache_dblock_deserialize(const void *_image, size_t len, void *_udata,
HDassert(nbytes == dblock->size);
/* Copy un-filtered data into block's buffer */
- HDmemcpy(dblock->blk, read_buf, dblock->size);
+ H5MM_memcpy(dblock->blk, read_buf, dblock->size);
} /* end if */
} /* end if */
else {
@@ -1859,7 +1859,7 @@ H5HF__cache_dblock_deserialize(const void *_image, size_t len, void *_udata,
/* Copy image to dblock->blk */
HDassert(dblock->size == len);
- HDmemcpy(dblock->blk, image, dblock->size);
+ H5MM_memcpy(dblock->blk, image, dblock->size);
} /* end else */
/* Start decoding direct block */
@@ -2149,7 +2149,7 @@ H5HF__cache_dblock_pre_serialize(H5F_t *f, void *_thing,
image = dblock->blk;
/* Magic number */
- HDmemcpy(image, H5HF_DBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ H5MM_memcpy(image, H5HF_DBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
image += H5_SIZEOF_MAGIC;
/* Version # */
@@ -2204,7 +2204,7 @@ H5HF__cache_dblock_pre_serialize(H5F_t *f, void *_thing,
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "memory allocation failed for pipeline buffer")
/* Copy the direct block's image into the buffer to compress */
- HDmemcpy(write_buf, dblock->blk, write_size);
+ H5MM_memcpy(write_buf, dblock->blk, write_size);
/* Push direct block data through I/O filter pipeline */
nbytes = write_size;
@@ -2463,7 +2463,7 @@ H5HF__cache_dblock_serialize(const H5F_t *f, void *image, size_t len,
HDassert(dblock->write_size == len);
/* Copy the image from *(dblock->write_buf) to *image */
- HDmemcpy(image, dblock->write_buf, dblock->write_size);
+ H5MM_memcpy(image, dblock->write_buf, dblock->write_size);
/* Free *(dblock->write_buf) if it was allocated by the
* pre-serialize function
diff --git a/src/H5HFdbg.c b/src/H5HFdbg.c
index fc437dc..22de0c4 100644
--- a/src/H5HFdbg.c
+++ b/src/H5HFdbg.c
@@ -483,7 +483,7 @@ H5HF_dblock_debug_cb(H5FS_section_info_t *_sect, void *_udata)
/* Flag overlaps */
if (overlap)
- fprintf(udata->stream, "***THAT FREE BLOCK OVERLAPPED A PREVIOUS ONE!\n");
+ HDfprintf(udata->stream, "***THAT FREE BLOCK OVERLAPPED A PREVIOUS ONE!\n");
else
udata->amount_free += len;
} /* end if */
diff --git a/src/H5HFhdr.c b/src/H5HFhdr.c
index b014017..5750a03 100644
--- a/src/H5HFhdr.c
+++ b/src/H5HFhdr.c
@@ -36,6 +36,7 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5HFpkg.h" /* Fractal heaps */
#include "H5MFprivate.h" /* File memory management */
+#include "H5MMprivate.h" /* Memory management */
#include "H5VMprivate.h" /* Vectors and arrays */
/****************/
@@ -387,7 +388,7 @@ H5HF_hdr_create(H5F_t *f, const H5HF_create_t *cparam)
/* Set the creation parameters for the heap */
hdr->max_man_size = cparam->max_man_size;
hdr->checksum_dblocks = cparam->checksum_dblocks;
- HDmemcpy(&(hdr->man_dtable.cparam), &(cparam->managed), sizeof(H5HF_dtable_cparam_t));
+ H5MM_memcpy(&(hdr->man_dtable.cparam), &(cparam->managed), sizeof(H5HF_dtable_cparam_t));
/* Set root table address to indicate that the heap is empty currently */
hdr->man_dtable.table_addr = HADDR_UNDEF;
diff --git a/src/H5HFhuge.c b/src/H5HFhuge.c
index 6e475ad..d496d62 100644
--- a/src/H5HFhuge.c
+++ b/src/H5HFhuge.c
@@ -355,7 +355,7 @@ HDfprintf(stderr, "%s: obj_size = %Zu\n", FUNC, obj_size);
write_size = obj_size;
if(NULL == (write_buf = H5MM_malloc(write_size)))
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "memory allocation failed for pipeline buffer")
- HDmemcpy(write_buf, obj, write_size);
+ H5MM_memcpy(write_buf, obj, write_size);
/* Push direct block data through I/O filter pipeline */
nbytes = write_size;
@@ -794,7 +794,7 @@ H5HF__huge_op_real(H5HF_hdr_t *hdr, const uint8_t *id, hbool_t is_read,
/* Copy object to user's buffer if there's filters on heap data */
/* (if there's no filters, the object was read directly into the user's buffer) */
if(hdr->filter_len > 0)
- HDmemcpy(op_data, read_buf, (size_t)obj_size);
+ H5MM_memcpy(op_data, read_buf, (size_t)obj_size);
} /* end if */
else {
/* Call the user's 'op' callback */
diff --git a/src/H5HFman.c b/src/H5HFman.c
index 7f90f49..e5b5cb8 100644
--- a/src/H5HFman.c
+++ b/src/H5HFman.c
@@ -183,7 +183,7 @@ H5HF__man_insert(H5HF_hdr_t *hdr, size_t obj_size, const void *obj, void *_id)
p = dblock->blk + blk_off;
/* Copy the object's data into the heap */
- HDmemcpy(p, obj, obj_size);
+ H5MM_memcpy(p, obj, obj_size);
p += obj_size;
/* Sanity check */
diff --git a/src/H5HFprivate.h b/src/H5HFprivate.h
index 587a8fc..4eec1c1 100644
--- a/src/H5HFprivate.h
+++ b/src/H5HFprivate.h
@@ -25,9 +25,6 @@
#ifndef _H5HFprivate_H
#define _H5HFprivate_H
-/* Include package's public header */
-#include "H5HFpublic.h"
-
/* Private headers needed by this file */
#include "H5Fprivate.h" /* File access */
#include "H5Oprivate.h" /* Object headers */
diff --git a/src/H5HFsection.c b/src/H5HFsection.c
index 36e966e..f5ac8e5 100644
--- a/src/H5HFsection.c
+++ b/src/H5HFsection.c
@@ -3082,7 +3082,7 @@ H5HF__sect_indirect_reduce_row(H5HF_hdr_t *hdr, H5HF_free_section_t *row_sect,
HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "allocation failed for row section pointer array")
/* Transfer row sections between current & peer sections */
- HDmemcpy(&peer_sect->u.indirect.dir_rows[0],
+ H5MM_memcpy(&peer_sect->u.indirect.dir_rows[0],
&sect->u.indirect.dir_rows[0],
(sizeof(H5HF_free_section_t *) * peer_dir_nrows));
HDmemmove(&sect->u.indirect.dir_rows[0],
@@ -3321,7 +3321,7 @@ H5HF__sect_indirect_reduce(H5HF_hdr_t *hdr, H5HF_free_section_t *sect,
HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "allocation failed for indirect section pointer array")
/* Transfer child indirect sections between current & peer sections */
- HDmemcpy(&peer_sect->u.indirect.indir_ents[0],
+ H5MM_memcpy(&peer_sect->u.indirect.indir_ents[0],
&sect->u.indirect.indir_ents[sect->u.indirect.indir_nents - peer_nentries],
(sizeof(H5HF_free_section_t *) * peer_nentries));
sect->u.indirect.indir_nents -= (peer_nentries + 1); /* Transferred blocks, plus child entry */
@@ -3636,7 +3636,7 @@ H5HF__sect_indirect_merge_row(H5HF_hdr_t *hdr, H5HF_free_section_t *row_sect1,
sect1->u.indirect.dir_rows = new_dir_rows;
/* Transfer the second section's rows to first section */
- HDmemcpy(&sect1->u.indirect.dir_rows[sect1->u.indirect.dir_nrows],
+ H5MM_memcpy(&sect1->u.indirect.dir_rows[sect1->u.indirect.dir_nrows],
&sect2->u.indirect.dir_rows[src_row2],
(sizeof(H5HF_free_section_t *) * nrows_moved2));
@@ -3682,7 +3682,7 @@ H5HF__sect_indirect_merge_row(H5HF_hdr_t *hdr, H5HF_free_section_t *row_sect1,
sect1->u.indirect.indir_ents = new_indir_ents;
/* Transfer the second section's entries to first section */
- HDmemcpy(&sect1->u.indirect.indir_ents[sect1->u.indirect.indir_nents],
+ H5MM_memcpy(&sect1->u.indirect.indir_ents[sect1->u.indirect.indir_nents],
&sect2->u.indirect.indir_ents[0],
(sizeof(H5HF_free_section_t *) * sect2->u.indirect.indir_nents));
} /* end else */
diff --git a/src/H5HFtest.c b/src/H5HFtest.c
index 1b1f688..6f174bb 100644
--- a/src/H5HFtest.c
+++ b/src/H5HFtest.c
@@ -32,6 +32,8 @@
#include "H5private.h" /* Generic Functions */
#include "H5Eprivate.h" /* Error handling */
#include "H5HFpkg.h" /* Fractal heaps */
+#include "H5MMprivate.h" /* Memory management */
+
/****************/
/* Local Macros */
@@ -100,7 +102,7 @@ H5HF_get_cparam_test(const H5HF_t *fh, H5HF_create_t *cparam)
else
H5_CHECKED_ASSIGN(cparam->id_len, uint16_t, fh->hdr->id_len, unsigned);
cparam->max_man_size = fh->hdr->max_man_size;
- HDmemcpy(&(cparam->managed), &(fh->hdr->man_dtable.cparam), sizeof(H5HF_dtable_cparam_t));
+ H5MM_memcpy(&(cparam->managed), &(fh->hdr->man_dtable.cparam), sizeof(H5HF_dtable_cparam_t));
H5O_msg_copy(H5O_PLINE_ID, &(fh->hdr->pline), &(cparam->pline));
FUNC_LEAVE_NOAPI(SUCCEED)
diff --git a/src/H5HFtiny.c b/src/H5HFtiny.c
index 5cf1c08..0c27180 100644
--- a/src/H5HFtiny.c
+++ b/src/H5HFtiny.c
@@ -35,6 +35,7 @@
#include "H5private.h" /* Generic Functions */
#include "H5Eprivate.h" /* Error handling */
#include "H5HFpkg.h" /* Fractal heaps */
+#include "H5MMprivate.h" /* Memory management */
/****************/
@@ -176,7 +177,7 @@ HDfprintf(stderr, "%s: obj_size = %Zu\n", FUNC, obj_size);
*id++ = enc_obj_size & H5HF_TINY_MASK_EXT_2;
} /* end else */
- HDmemcpy(id, obj, obj_size);
+ H5MM_memcpy(id, obj, obj_size);
HDmemset(id + obj_size, 0, (hdr->id_len - ((size_t)1 + (size_t)hdr->tiny_len_extended + obj_size)));
/* Update statistics about heap */
diff --git a/src/H5HG.c b/src/H5HG.c
index b9d8dc3..231294b 100644
--- a/src/H5HG.c
+++ b/src/H5HG.c
@@ -168,7 +168,7 @@ H5HG__create(H5F_t *f, size_t size)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, HADDR_UNDEF, "memory allocation failed")
/* Initialize the header */
- HDmemcpy(heap->chunk, H5HG_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ H5MM_memcpy(heap->chunk, H5HG_MAGIC, (size_t)H5_SIZEOF_MAGIC);
p = heap->chunk + H5_SIZEOF_MAGIC;
*p++ = H5HG_VERSION;
*p++ = 0; /*reserved*/
@@ -553,7 +553,7 @@ H5HG_insert(H5F_t *f, size_t size, void *obj, H5HG_t *hobj/*out*/)
/* Copy data into the heap */
if(size > 0) {
- HDmemcpy(heap->obj[idx].begin + H5HG_SIZEOF_OBJHDR(f), obj, size);
+ H5MM_memcpy(heap->obj[idx].begin + H5HG_SIZEOF_OBJHDR(f), obj, size);
#ifdef OLD_WAY
/* Don't bother zeroing out the rest of the info in the heap -QAK */
HDmemset(heap->obj[idx].begin + H5HG_SIZEOF_OBJHDR(f) + size, 0,
@@ -618,7 +618,7 @@ H5HG_read(H5F_t *f, H5HG_t *hobj, void *object/*out*/, size_t *buf_size)
/* Allocate a buffer for the object read in, if the user didn't give one */
if(!object && NULL == (object = H5MM_malloc(size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- HDmemcpy(object, p, size);
+ H5MM_memcpy(object, p, size);
/*
* Advance the heap in the CWFS list. We might have done this already
@@ -785,7 +785,14 @@ H5HG_remove (H5F_t *f, H5HG_t *hobj)
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect global heap")
HDassert(hobj->idx < heap->nused);
- HDassert(heap->obj[hobj->idx].begin);
+
+ /* When the application selects the same location to rewrite the VL element by using H5Sselect_elements,
+ * it can happen that the entry has been removed by first rewrite. Here we simply skip the removal of
+ * the entry and let the second rewrite happen (see HDFFV-10635). In the future, it'd be nice to handle
+ * this situation in H5T_conv_vlen in H5Tconv.c instead of this level (HDFFV-10648). */
+ if(heap->obj[hobj->idx].nrefs == 0 && heap->obj[hobj->idx].size == 0 && !heap->obj[hobj->idx].begin)
+ HGOTO_DONE(ret_value)
+
obj_start = heap->obj[hobj->idx].begin;
/* Include object header size */
need = H5HG_ALIGN(heap->obj[hobj->idx].size) + H5HG_SIZEOF_OBJHDR(f);
diff --git a/src/H5HGcache.c b/src/H5HGcache.c
index 658c122..ac294ba 100644
--- a/src/H5HGcache.c
+++ b/src/H5HGcache.c
@@ -272,7 +272,7 @@ H5HG__cache_heap_deserialize(const void *_image, size_t len, void *_udata,
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* Copy the image buffer into the newly allocate chunk */
- HDmemcpy(heap->chunk, _image, len);
+ H5MM_memcpy(heap->chunk, _image, len);
/* Deserialize the heap's header */
if(H5HG__hdr_deserialize(heap, (const uint8_t *)heap->chunk, f) < 0)
@@ -449,7 +449,7 @@ H5HG__cache_heap_serialize(const H5F_t *f, void *image, size_t len,
HDassert(heap->chunk);
/* copy the image into the buffer */
- HDmemcpy(image, heap->chunk, len);
+ H5MM_memcpy(image, heap->chunk, len);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5HG__cache_heap_serialize() */
diff --git a/src/H5HGpkg.h b/src/H5HGpkg.h
index 4ed9b10..3119de4 100644
--- a/src/H5HGpkg.h
+++ b/src/H5HGpkg.h
@@ -117,7 +117,7 @@ typedef struct H5HG_obj_t {
} H5HG_obj_t;
/* Forward declarations for fields */
-struct H5F_file_t;
+struct H5F_shared_t;
struct H5HG_heap_t {
H5AC_info_t cache_info; /* Information for H5AC cache functions, _must_ be */
@@ -130,7 +130,7 @@ struct H5HG_heap_t {
/* If this value is >65535 then all indices */
/* have been used at some time and the */
/* correct new index should be searched for */
- struct H5F_file_t *shared; /* shared file */
+ struct H5F_shared_t *shared; /* shared file */
H5HG_obj_t *obj; /*array of object descriptions */
};
diff --git a/src/H5HGprivate.h b/src/H5HGprivate.h
index a7d7a80..4841847 100644
--- a/src/H5HGprivate.h
+++ b/src/H5HGprivate.h
@@ -18,9 +18,6 @@
#ifndef _H5HGprivate_H
#define _H5HGprivate_H
-/* Include package's public header */
-#include "H5HGpublic.h"
-
/* Private headers needed by this file. */
#include "H5Fprivate.h" /* File access */
@@ -52,6 +49,10 @@ typedef struct H5HG_heap_t H5HG_heap_t;
#define H5HG_FREE_SIZE(H) (H5HG_get_free_size(H))
#endif /* H5HG_MODULE */
+/* Size of encoded global heap ID */
+/* (size of file address + 32-bit integer) */
+#define H5HG_HEAP_ID_SIZE(F) ((size_t)H5F_SIZEOF_ADDR(F) + H5_SIZEOF_UINT32_T)
+
/* Main global heap routines */
H5_DLL herr_t H5HG_insert(H5F_t *f, size_t size, void *obj, H5HG_t *hobj/*out*/);
diff --git a/src/H5HL.c b/src/H5HL.c
index 735077c..f290294 100644
--- a/src/H5HL.c
+++ b/src/H5HL.c
@@ -725,7 +725,7 @@ H5HL_insert(H5F_t *f, H5HL_t *heap, size_t buf_size, const void *buf))
} /* end if */
/* Copy the data into the heap */
- HDmemcpy(heap->dblk_image + offset, buf, buf_size);
+ H5MM_memcpy(heap->dblk_image + offset, buf, buf_size);
/* Set return value */
ret_value = offset;
diff --git a/src/H5HLcache.c b/src/H5HLcache.c
index 69eada4..5018999 100644
--- a/src/H5HLcache.c
+++ b/src/H5HLcache.c
@@ -36,6 +36,7 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5HLpkg.h" /* Local Heaps */
#include "H5MFprivate.h" /* File memory management */
+#include "H5MMprivate.h" /* Memory management */
#include "H5WBprivate.h" /* Wrapped Buffers */
@@ -466,7 +467,7 @@ H5HL__cache_prefix_deserialize(const void *_image, size_t len, void *_udata,
image = ((const uint8_t *)_image) + heap->prfx_size;
/* Copy the heap data from the speculative read buffer */
- HDmemcpy(heap->dblk_image, image, heap->dblk_size);
+ H5MM_memcpy(heap->dblk_image, image, heap->dblk_size);
/* Build free list */
if(H5HL__fl_deserialize(heap) < 0)
@@ -589,7 +590,7 @@ H5HL__cache_prefix_serialize(const H5F_t *f, void *_image, size_t len,
heap->free_block = heap->freelist ? heap->freelist->offset : H5HL_FREE_NULL;
/* Serialize the heap prefix */
- HDmemcpy(image, H5HL_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ H5MM_memcpy(image, H5HL_MAGIC, (size_t)H5_SIZEOF_MAGIC);
image += H5_SIZEOF_MAGIC;
*image++ = H5HL_VERSION;
*image++ = 0; /*reserved*/
@@ -617,7 +618,7 @@ H5HL__cache_prefix_serialize(const H5F_t *f, void *_image, size_t len,
H5HL__fl_serialize(heap);
/* Copy the heap data block into the cache image */
- HDmemcpy(image, heap->dblk_image, heap->dblk_size);
+ H5MM_memcpy(image, heap->dblk_image, heap->dblk_size);
/* Sanity check */
HDassert((size_t)(image - (uint8_t *)_image) + heap->dblk_size == len);
@@ -758,7 +759,7 @@ H5HL__cache_datablock_deserialize(const void *image, size_t len, void *_udata,
HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "can't allocate data block image buffer");
/* copy the datablock from the read buffer */
- HDmemcpy(heap->dblk_image, image, len);
+ H5MM_memcpy(heap->dblk_image, image, len);
/* Build free list */
if(FAIL == H5HL__fl_deserialize(heap))
@@ -853,7 +854,7 @@ H5HL__cache_datablock_serialize(const H5F_t *f, void *image, size_t len,
H5HL__fl_serialize(heap);
/* Copy the heap's data block into the cache's image */
- HDmemcpy(image, heap->dblk_image, heap->dblk_size);
+ H5MM_memcpy(image, heap->dblk_image, heap->dblk_size);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5HL__cache_datablock_serialize() */
diff --git a/src/H5HLprivate.h b/src/H5HLprivate.h
index 4001ef1..7a53b25 100644
--- a/src/H5HLprivate.h
+++ b/src/H5HLprivate.h
@@ -24,9 +24,6 @@
#ifndef _H5HLprivate_H
#define _H5HLprivate_H
-/* Include package's public header */
-#include "H5HLpublic.h"
-
/* Private headers needed by this file. */
#include "H5private.h" /* Generic Functions */
#include "H5ACprivate.h" /* Metadata cache */
diff --git a/src/H5I.c b/src/H5I.c
index 293a0ea..76faab1 100644
--- a/src/H5I.c
+++ b/src/H5I.c
@@ -26,28 +26,24 @@
*/
#include "H5Imodule.h" /* This source code file is part of the H5I module */
+#define H5T_FRIEND /* Suppress error about including H5Tpkg */
#include "H5private.h" /* Generic Functions */
#include "H5ACprivate.h" /* Metadata cache */
#include "H5CXprivate.h" /* API Contexts */
-#include "H5Eprivate.h" /* Error handling */
-#include "H5FLprivate.h" /* Free Lists */
+#include "H5Dprivate.h" /* Datasets */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fprivate.h" /* File access */
+#include "H5FLprivate.h" /* Free Lists */
+#include "H5Gprivate.h" /* Groups */
#include "H5Ipkg.h" /* IDs */
#include "H5MMprivate.h" /* Memory management */
#include "H5Oprivate.h" /* Object headers */
#include "H5SLprivate.h" /* Skip Lists */
+#include "H5Tpkg.h" /* Datatypes */
+#include "H5VLprivate.h" /* Virtual Object Layer */
-/* Define this to compile in support for dumping ID information */
-/* #define H5I_DEBUG_OUTPUT */
-#ifndef H5I_DEBUG_OUTPUT
-#include "H5Gprivate.h" /* Groups */
-#else /* H5I_DEBUG_OUTPUT */
-#define H5G_FRIEND /* Suppress error about including H5Gpkg */
-#include "H5Gpkg.h" /* Groups */
-#include "H5Dprivate.h" /* Datasets */
-#include "H5Tprivate.h" /* Datatypes */
-#endif /* H5I_DEBUG_OUTPUT */
/* Local Macros */
@@ -80,11 +76,24 @@ typedef struct {
void *ret_obj; /* Object to return */
} H5I_search_ud_t;
+typedef struct {
+ H5I_iterate_func_t op; /* Application's callback routine */
+ void *op_data; /* Application's user data */
+} H5I_iterate_pub_ud_t;
+
+/* User data for iterator callback for retrieving an ID corresponding to an object pointer */
+typedef struct {
+ const void *object; /* object pointer to search for */
+ H5I_type_t obj_type; /* type of object we are searching for */
+ hid_t ret_id; /* ID returned */
+} H5I_get_id_ud_t;
+
/* User data for iterator callback for ID iteration */
typedef struct {
H5I_search_func_t user_func; /* 'User' function to invoke */
void *user_udata; /* User data to pass to 'user' function */
hbool_t app_ref; /* Whether this is an appl. ref. call */
+ H5I_type_t obj_type; /* Type of object we are iterating over */
} H5I_iterate_ud_t;
/* User data for H5I__clear_type_cb */
@@ -108,7 +117,7 @@ static H5I_id_type_t *H5I_id_type_list_g[H5I_MAX_NUM_TYPES];
/* Starts at 1 instead of 0 because it makes trace output look nicer. If more */
/* types (or IDs within a type) are needed, adjust TYPE_BITS in H5Ipkg.h */
/* and/or increase size of hid_t */
-static H5I_type_t H5I_next_type = (H5I_type_t) H5I_NTYPES;
+static int H5I_next_type = (int)H5I_NTYPES;
/* Declare a free list to manage the H5I_id_info_t struct */
H5FL_DEFINE_STATIC(H5I_id_info_t);
@@ -119,7 +128,10 @@ H5FL_DEFINE_STATIC(H5I_id_type_t);
/* Declare a free list to manage the H5I_class_t struct */
H5FL_DEFINE_STATIC(H5I_class_t);
+H5FL_EXTERN(H5VL_object_t);
+
/*--------------------- Local function prototypes ---------------------------*/
+static void *H5I__unwrap(void *obj_ptr, H5I_type_t type);
static htri_t H5I__clear_type_cb(void *_id, void *key, void *udata);
static int H5I__destroy_type(H5I_type_t type);
static void *H5I__remove_verify(hid_t id, H5I_type_t id_type);
@@ -128,11 +140,9 @@ static int H5I__inc_type_ref(H5I_type_t type);
static int H5I__get_type_ref(H5I_type_t type);
static int H5I__search_cb(void *obj, hid_t id, void *_udata);
static H5I_id_info_t *H5I__find_id(hid_t id);
-static hid_t H5I__get_file_id(hid_t obj_id, H5I_type_t id_type);
-#ifdef H5I_DEBUG_OUTPUT
-static int H5I__debug_cb(void *_item, void *_key, void *_udata);
-static herr_t H5I__debug(H5I_type_t type);
-#endif /* H5I_DEBUG_OUTPUT */
+static int H5I__iterate_pub_cb(void *obj, hid_t id, void *udata);
+static int H5I__find_id_cb(void *_item, void *_key, void *_udata);
+static int H5I__id_dump_cb(void *_item, void *_key, void *_udata);
/*-------------------------------------------------------------------------
@@ -158,16 +168,16 @@ H5I_term_package(void)
if(H5_PKG_INIT_VAR) {
H5I_id_type_t *type_ptr; /* Pointer to ID type */
- H5I_type_t type; /* Type of ID */
+ int type; /* Type of ID */
/* How many types are still being used? */
- for(type = (H5I_type_t)0; type < H5I_next_type; H5_INC_ENUM(H5I_type_t, type))
+ for(type = 0; type < H5I_next_type; type++)
if((type_ptr = H5I_id_type_list_g[type]) && type_ptr->ids)
n++;
/* If no types are used then clean up */
if(0 == n) {
- for(type = (H5I_type_t)0; type < H5I_next_type; H5_INC_ENUM(H5I_type_t,type)) {
+ for(type = 0; type < H5I_next_type; type++) {
type_ptr = H5I_id_type_list_g[type];
if(type_ptr) {
HDassert(NULL == type_ptr->ids);
@@ -216,10 +226,10 @@ H5Iregister_type(size_t hash_size, unsigned reserved, H5I_free_t free_func)
/* Generate a new H5I_type_t value */
- /* Increment the number of types*/
+ /* Increment the number of types */
if(H5I_next_type < H5I_MAX_NUM_TYPES) {
- new_type = H5I_next_type;
- H5_INC_ENUM(H5I_type_t, H5I_next_type);
+ new_type = (H5I_type_t)H5I_next_type;
+ H5I_next_type++;
} /* end if */
else {
hbool_t done; /* Indicate that search was successful */
@@ -237,7 +247,7 @@ H5Iregister_type(size_t hash_size, unsigned reserved, H5I_free_t free_func)
/* Verify that we found a type to give out */
if(done == FALSE)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5I_BADID, "Maximum number of ID types exceeded.")
+ HGOTO_ERROR(H5E_ATOM, H5E_NOSPACE, H5I_BADID, "Maximum number of ID types exceeded")
} /* end else */
/* Allocate new ID class */
@@ -288,7 +298,7 @@ H5I_register_type(const H5I_class_t *cls)
/* Sanity check */
HDassert(cls);
- HDassert(cls->type_id > 0 && cls->type_id < H5I_MAX_NUM_TYPES);
+ HDassert(cls->type_id > 0 && (int)cls->type_id < H5I_MAX_NUM_TYPES);
/* Initialize the type */
if(NULL == H5I_id_type_list_g[cls->type_id]) {
@@ -345,10 +355,13 @@ H5Itype_exists(H5I_type_t type)
FUNC_ENTER_API(FAIL)
H5TRACE1("t", "It", type);
- if (type <= H5I_BADID || type >= H5I_next_type)
+ /* Validate parameter */
+ if(H5I_IS_LIB_TYPE(type))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "cannot call public function on library type")
+ if(type <= H5I_BADID || (int)type >= H5I_next_type)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
- if (NULL == H5I_id_type_list_g[type])
+ if(NULL == H5I_id_type_list_g[type])
ret_value = FALSE;
done:
@@ -387,7 +400,7 @@ H5Inmembers(H5I_type_t type, hsize_t *num_members)
* the private interface handle it, because the public interface throws
* an error when the supplied type does not exist.
*/
- if(type <= H5I_BADID || type >= H5I_next_type)
+ if(type <= H5I_BADID || (int)type >= H5I_next_type)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
if(NULL == H5I_id_type_list_g[type])
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "supplied type does not exist")
@@ -429,7 +442,8 @@ H5I_nmembers(H5I_type_t type)
FUNC_ENTER_NOAPI(FAIL)
- if(type <= H5I_BADID || type >= H5I_next_type)
+ /* Validate parameter */
+ if(type <= H5I_BADID || (int)type >= H5I_next_type)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
if(NULL == (type_ptr = H5I_id_type_list_g[type]) || type_ptr->init_count <= 0)
HGOTO_DONE(0);
@@ -443,6 +457,50 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5I__unwrap
+ *
+ * Purpose: Unwraps the object pointer for the 'item' that corresponds
+ * to an ID.
+ *
+ * Return: Pointer to the unwrapped pointer (can't fail)
+ *
+ * Programmer: Quincey Koziol
+ * Friday, October 19, 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5I__unwrap(void *obj_ptr, H5I_type_t type)
+{
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Sanity checks */
+ HDassert(obj_ptr);
+
+ /* The stored object pointer might be an H5VL_object_t, in which
+ * case we'll need to get the wrapped object struct (H5F_t *, etc.).
+ */
+ if(H5I_FILE == type || H5I_GROUP == type || H5I_DATASET == type || H5I_ATTR == type) {
+ const H5VL_object_t *vol_obj;
+
+ vol_obj = (const H5VL_object_t *)obj_ptr;
+ ret_value = H5VL_object_data(vol_obj);
+ } /* end if */
+ else if(H5I_DATATYPE == type) {
+ H5T_t *dt = (H5T_t *)obj_ptr;
+
+ ret_value = (void *)H5T_get_actual_type(dt);
+ } /* end if */
+ else
+ ret_value = obj_ptr;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5I__unwrap() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5Iclear_type
*
* Purpose: Removes all objects from the type, calling the free
@@ -496,7 +554,8 @@ H5I_clear_type(H5I_type_t type, hbool_t force, hbool_t app_ref)
FUNC_ENTER_NOAPI(FAIL)
- if(type <= H5I_BADID || type >= H5I_next_type)
+ /* Validate parameters */
+ if(type <= H5I_BADID || (int)type >= H5I_next_type)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
udata.type_ptr = H5I_id_type_list_g[type];
@@ -538,6 +597,7 @@ H5I__clear_type_cb(void *_id, void H5_ATTR_UNUSED *key, void *_udata)
FUNC_ENTER_STATIC_NOERR
+ /* Sanity checks */
HDassert(id);
HDassert(udata);
HDassert(udata->type_ptr);
@@ -547,12 +607,11 @@ H5I__clear_type_cb(void *_id, void H5_ATTR_UNUSED *key, void *_udata)
*/
if(udata->force || (id->count - (!udata->app_ref * id->app_count)) <= 1) {
/* Check for a 'free' function and call it, if it exists */
- /* (Casting away const OK -QAK) */
- if(udata->type_ptr->cls->free_func && (udata->type_ptr->cls->free_func)((void *)id->obj_ptr) < 0) {
+ if(udata->type_ptr->cls->free_func && (udata->type_ptr->cls->free_func)((void *)id->obj_ptr) < 0) { /* (Casting away const OK -QAK) */
if(udata->force) {
#ifdef H5I_DEBUG
if(H5DEBUG(I)) {
- fprintf(H5DEBUG(I), "H5I: free type=%d obj=0x%08lx "
+ HDfprintf(H5DEBUG(I), "H5I: free type=%d obj=0x%08lx "
"failure ignored\n",
(int)udata->type_ptr->cls->type_id,
(unsigned long)(id->obj_ptr));
@@ -639,7 +698,8 @@ H5I__destroy_type(H5I_type_t type)
FUNC_ENTER_STATIC
- if(type <= H5I_BADID || type >= H5I_next_type)
+ /* Validate parameter */
+ if(type <= H5I_BADID || (int)type >= H5I_next_type)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
type_ptr = H5I_id_type_list_g[type];
@@ -722,7 +782,7 @@ H5I_register(H5I_type_t type, const void *object, hbool_t app_ref)
FUNC_ENTER_NOAPI(FAIL)
/* Check arguments */
- if (type <= H5I_BADID || type >= H5I_next_type)
+ if (type <= H5I_BADID || (int)type >= H5I_next_type)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, H5I_INVALID_HID, "invalid type number")
type_ptr = H5I_id_type_list_g[type];
if ((NULL == type_ptr) || (type_ptr->init_count <= 0))
@@ -755,7 +815,7 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5I_register_with_id
+ * Function: H5I_register_using_existing_id
*
* Purpose: Registers an OBJECT in a TYPE with the supplied ID for it.
* This routine will check to ensure the supplied ID is not already
@@ -764,12 +824,16 @@ done:
* registered (thus, it is possible to register one object under
* multiple IDs).
*
+ * NOTE: Intended for use in refresh calls, where we have to close
+ * and re-open the underlying data, then hook the object back
+ * up to the original ID.
+ *
* Return: SUCCEED/FAIL
*
*-------------------------------------------------------------------------
*/
herr_t
-H5I_register_with_id(H5I_type_t type, const void *object, hbool_t app_ref, hid_t id)
+H5I_register_using_existing_id(H5I_type_t type, void *object, hbool_t app_ref, hid_t existing_id)
{
H5I_id_type_t *type_ptr; /* ptr to the type */
H5I_id_info_t *id_ptr; /* ptr to the new ID information */
@@ -781,11 +845,11 @@ H5I_register_with_id(H5I_type_t type, const void *object, hbool_t app_ref, hid_t
HDassert(object);
/* Make sure ID is not already in use */
- if(NULL != (id_ptr = H5I__find_id(id)))
+ if(NULL != (id_ptr = H5I__find_id(existing_id)))
HGOTO_ERROR(H5E_ATOM, H5E_BADRANGE, FAIL, "ID already in use")
/* Make sure type number is valid */
- if(type <= H5I_BADID || type >= H5I_next_type)
+ if(type <= H5I_BADID || (int)type >= H5I_next_type)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
/* Get type pointer from list of types */
@@ -795,7 +859,7 @@ H5I_register_with_id(H5I_type_t type, const void *object, hbool_t app_ref, hid_t
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type")
/* Make sure requested ID belongs to object's type */
- if(H5I_TYPE(id) != type)
+ if(H5I_TYPE(existing_id) != type)
HGOTO_ERROR(H5E_ATOM, H5E_BADRANGE, FAIL, "invalid type for provided ID")
/* Allocate new structure to house this ID */
@@ -803,7 +867,7 @@ H5I_register_with_id(H5I_type_t type, const void *object, hbool_t app_ref, hid_t
HGOTO_ERROR(H5E_ATOM, H5E_NOSPACE, FAIL, "memory allocation failed")
/* Create the struct & insert requested ID */
- id_ptr->id = id;
+ id_ptr->id = existing_id;
id_ptr->count = 1; /* initial reference count*/
id_ptr->app_count = !!app_ref;
id_ptr->obj_ptr = object;
@@ -815,7 +879,7 @@ H5I_register_with_id(H5I_type_t type, const void *object, hbool_t app_ref, hid_t
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5I_register_with_id() */
+} /* end H5I_register_using_existing_id() */
/*-------------------------------------------------------------------------
@@ -845,8 +909,7 @@ H5I_subst(hid_t id, const void *new_object)
HGOTO_ERROR(H5E_ATOM, H5E_NOTFOUND, NULL, "can't get ID ref count")
/* Get the old object pointer to return */
- /* (Casting away const OK -QAK) */
- ret_value = (void *)id_ptr->obj_ptr;
+ ret_value = (void *)id_ptr->obj_ptr; /* (Casting away const OK -QAK) */
/* Set the new object pointer for the ID */
id_ptr->obj_ptr = new_object;
@@ -907,10 +970,10 @@ H5Iobject_verify(hid_t id, H5I_type_t id_type)
FUNC_ENTER_API(NULL)
H5TRACE2("*x", "iIt", id, id_type);
+ /* Validate parameters */
if(H5I_IS_LIB_TYPE(id_type))
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "cannot call public function on library type")
-
- if(id_type < 1 || id_type >= H5I_next_type)
+ if(id_type < 1 || (int)id_type >= H5I_next_type)
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "identifier has invalid type")
ret_value = H5I_object_verify(id, id_type);
@@ -943,7 +1006,7 @@ H5I_object_verify(hid_t id, H5I_type_t id_type)
FUNC_ENTER_NOAPI_NOERR
- HDassert(id_type >= 1 && id_type < H5I_next_type);
+ HDassert(id_type >= 1 && (int)id_type < H5I_next_type);
/* Verify that the type of the ID is correct & lookup the ID */
if(id_type == H5I_TYPE(id) && NULL != (id_ptr = H5I__find_id(id))) {
@@ -983,7 +1046,7 @@ H5I_get_type(hid_t id)
if(id > 0)
ret_value = H5I_TYPE(id);
- HDassert(ret_value >= H5I_BADID && ret_value < H5I_next_type);
+ HDassert(ret_value >= H5I_BADID && (int)ret_value < H5I_next_type);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I_get_type() */
@@ -1014,7 +1077,7 @@ H5Iget_type(hid_t id)
ret_value = H5I_get_type(id);
- if(ret_value <= H5I_BADID || ret_value >= H5I_next_type || NULL == H5I_object(id))
+ if(ret_value <= H5I_BADID || (int)ret_value >= H5I_next_type || NULL == H5I_object(id))
HGOTO_DONE(H5I_BADID);
done:
@@ -1023,6 +1086,57 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5I_is_file_object
+ *
+ * Purpose: Convenience function to determine if an ID represents
+ * a file object.
+ *
+ * In H5O calls, you can't use object_verify to ensure
+ * the ID was of the correct class since there's no
+ * H5I_OBJECT ID class.
+ *
+ * Return: Success: TRUE/FALSE
+ * Failure: FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5I_is_file_object(hid_t id)
+{
+ H5I_type_t id_type = H5I_get_type(id);
+ htri_t ret_value = FAIL;
+
+ FUNC_ENTER_NOAPI(FAIL);
+
+ /* Fail if the ID type is out of range */
+ if (id_type < 1 || id_type >= H5I_NTYPES)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID type out of range");
+
+ /* Return TRUE if the ID is a file object (dataset, group, map, or committed
+ * datatype), FALSE otherwise.
+ */
+ if (H5I_DATASET == id_type || H5I_GROUP == id_type || H5I_MAP == id_type) {
+ ret_value = TRUE;
+ }
+ else if (H5I_DATATYPE == id_type) {
+
+ H5T_t *dt = NULL;
+
+ if(NULL == (dt = (H5T_t *)H5I_object(id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "unable to get underlying datatype struct");
+
+ ret_value = H5T_is_named(dt);
+ }
+ else {
+ ret_value = FALSE;
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* H5I_is_file_object() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5Iremove_verify
*
* Purpose: Removes the specified ID from its type, first checking that the
@@ -1074,7 +1188,7 @@ done:
*
*-------------------------------------------------------------------------
*/
-void *
+static void *
H5I__remove_verify(hid_t id, H5I_type_t id_type)
{
void * ret_value = NULL; /*return value */
@@ -1158,7 +1272,7 @@ H5I_remove(hid_t id)
/* Check arguments */
type = H5I_TYPE(id);
- if(type <= H5I_BADID || type >= H5I_next_type)
+ if(type <= H5I_BADID || (int)type >= H5I_next_type)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, NULL, "invalid type number")
type_ptr = H5I_id_type_list_g[type];
if(type_ptr == NULL || type_ptr->init_count <= 0)
@@ -1521,14 +1635,13 @@ H5Iinc_type_ref(H5I_type_t type)
H5TRACE1("Is", "It", type);
/* Check arguments */
- if (type <= 0 || type >= H5I_next_type)
+ if(type <= 0 || (int)type >= H5I_next_type)
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, (-1), "invalid ID type")
-
- if (H5I_IS_LIB_TYPE(type))
+ if(H5I_IS_LIB_TYPE(type))
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, (-1), "cannot call public function on library type")
/* Do actual increment operation */
- if ((ret_value = H5I__inc_type_ref(type)) < 0)
+ if((ret_value = H5I__inc_type_ref(type)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTINC, (-1), "can't increment ID type ref count")
done:
@@ -1555,11 +1668,11 @@ H5I__inc_type_ref(H5I_type_t type)
FUNC_ENTER_STATIC
/* Sanity check */
- HDassert(type > 0 && type < H5I_next_type);
+ HDassert(type > 0 && (int)type < H5I_next_type);
/* Check arguments */
type_ptr = H5I_id_type_list_g[type];
- if (!type_ptr)
+ if(NULL == type_ptr)
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, (-1), "invalid type")
/* Set return value */
@@ -1639,11 +1752,11 @@ H5I_dec_type_ref(H5I_type_t type)
FUNC_ENTER_NOAPI((-1))
- if (type <= H5I_BADID || type >= H5I_next_type)
+ if(type <= H5I_BADID || (int)type >= H5I_next_type)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, (-1), "invalid type number")
type_ptr = H5I_id_type_list_g[type];
- if (type_ptr == NULL || type_ptr->init_count <= 0)
+ if(type_ptr == NULL || type_ptr->init_count <= 0)
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, (-1), "invalid type")
/* Decrement the number of users of the atomic type. If this is the
@@ -1651,14 +1764,14 @@ H5I_dec_type_ref(H5I_type_t type)
* free all memory it used. The free function is invoked for each atom
* being freed.
*/
- if (1 == type_ptr->init_count) {
+ if(1 == type_ptr->init_count) {
H5I__destroy_type(type);
ret_value = 0;
- }
+ } /* end if */
else {
--(type_ptr->init_count);
ret_value = (herr_t)type_ptr->init_count;
- }
+ } /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -1684,14 +1797,13 @@ H5Iget_type_ref(H5I_type_t type)
H5TRACE1("Is", "It", type);
/* Check arguments */
- if (type <= 0 || type >= H5I_next_type)
+ if(type <= 0 || (int)type >= H5I_next_type)
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, (-1), "invalid ID type")
-
- if (H5I_IS_LIB_TYPE(type))
+ if(H5I_IS_LIB_TYPE(type))
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, (-1), "cannot call public function on library type")
/* Do actual retrieve operation */
- if ((ret_value = H5I__get_type_ref(type)) < 0)
+ if((ret_value = H5I__get_type_ref(type)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, (-1), "can't get ID type ref count")
done:
@@ -1851,6 +1963,93 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5I__iterate_pub_cb
+ *
+ * Purpose: Callback routine for H5Iiterate, when it calls
+ * H5I_iterate. Calls "user" callback search function, and
+ * then sets return value, based on the result of that
+ * callback.
+ *
+ * Return: Success: H5_ITER_CONT (0) or H5_ITER_STOP (1)
+ * Failure: H5_ITER_ERROR (-1)
+ *
+ * Programmer: Neil Fortner
+ * Friday, October 11, 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+H5I__iterate_pub_cb(void H5_ATTR_UNUSED *obj, hid_t id, void *_udata)
+{
+ H5I_iterate_pub_ud_t *udata = (H5I_iterate_pub_ud_t *)_udata; /* User data for callback */
+ herr_t cb_ret_val; /* User callback return value */
+ int ret_value = H5_ITER_ERROR; /* Callback return value */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Invoke the callback */
+ cb_ret_val = (*udata->op)(id, udata->op_data);
+
+ /* Set the return value based on the callback's return value */
+ if(cb_ret_val > 0)
+ ret_value = H5_ITER_STOP; /* terminate iteration early */
+ else if(cb_ret_val < 0)
+ ret_value = H5_ITER_ERROR; /* indicate failure (which terminates iteration) */
+ else
+ ret_value = H5_ITER_CONT; /* continue iteration */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5I__iterate_pub_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Iiterate
+ *
+ * Purpose: Call the callback funciton op for each member of the id
+ * type type. op takes as parameters the id and a
+ * passthrough of op_data, and returns an herr_t. A positive
+ * return from op will cause the iteration to stop and
+ * H5Iiterate will return the value returned by op. A
+ * negative return from op will cause the iteration to stop
+ * and H5Iiterate will return failure. A zero return from op
+ * will allow iteration to continue, as long as there are
+ * other ids remaining in type.
+ *
+ * Limitation: Currently there is no way to start searching from where a
+ * previous search left off.
+ *
+ * Return: The last value returned by op
+ *
+ * Programmer: Neil Fortner
+ * Friday, October 11, 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Iiterate(H5I_type_t type, H5I_iterate_func_t op, void *op_data)
+{
+ H5I_iterate_pub_ud_t int_udata; /* Internal user data */
+ herr_t ret_value; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE3("e", "Itx*x", type, op, op_data);
+
+ /* Set up udata struct */
+ int_udata.op = op;
+ int_udata.op_data = op_data;
+
+ /* Note that H5I_iterate returns an error code. We ignore it
+ * here, as we can't do anything with it without revising the API.
+ */
+ if ((ret_value = H5I_iterate(type, H5I__iterate_pub_cb, &int_udata, TRUE)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADITER, FAIL, "can't iterate over ids")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Iiterate() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5I__iterate_cb
*
* Purpose: Callback routine for H5I_iterate, invokes "user" callback
@@ -1875,17 +2074,24 @@ H5I__iterate_cb(void *_item, void H5_ATTR_UNUSED *_key, void *_udata)
* its reference count is positive.
*/
if((!udata->app_ref) || (item->app_count > 0)) {
+ H5I_type_t type = udata->obj_type;
+ void *obj_ptr;
herr_t cb_ret_val;
+ /* The stored object pointer might be an H5VL_object_t, in which
+ * case we'll need to get the wrapped object struct (H5F_t *, etc.).
+ */
+ obj_ptr = H5I__unwrap((void *)item->obj_ptr, type);
+
/* Invoke callback function */
- cb_ret_val = (*udata->user_func)((void *)item->obj_ptr, item->id, udata->user_udata); /* (Casting away const OK) */
+ cb_ret_val = (*udata->user_func)((void *)obj_ptr, item->id, udata->user_udata); /* (Casting away const OK) */
/* Set the return value based on the callback's return value */
if(cb_ret_val > 0)
ret_value = H5_ITER_STOP; /* terminate iteration early */
else if(cb_ret_val < 0)
ret_value = H5_ITER_ERROR; /* indicate failure (which terminates iteration) */
- }
+ } /* end if */
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I__iterate_cb() */
@@ -1925,12 +2131,12 @@ H5I_iterate(H5I_type_t type, H5I_search_func_t func, void *udata, hbool_t app_re
FUNC_ENTER_NOAPI(FAIL)
/* Check arguments */
- if (type <= H5I_BADID || type >= H5I_next_type)
+ if(type <= H5I_BADID || (int)type >= H5I_next_type)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
type_ptr = H5I_id_type_list_g[type];
/* Only iterate through ID list if it is initialized and there are IDs in type */
- if (type_ptr && type_ptr->init_count > 0 && type_ptr->id_count > 0) {
+ if(type_ptr && type_ptr->init_count > 0 && type_ptr->id_count > 0) {
H5I_iterate_ud_t iter_udata; /* User data for iteration callback */
herr_t iter_status; /* Iteration status */
@@ -1938,11 +2144,12 @@ H5I_iterate(H5I_type_t type, H5I_search_func_t func, void *udata, hbool_t app_re
iter_udata.user_func = func;
iter_udata.user_udata = udata;
iter_udata.app_ref = app_ref;
+ iter_udata.obj_type = type;
/* Iterate over IDs */
- if ((iter_status = H5SL_iterate(type_ptr->ids, H5I__iterate_cb, &iter_udata)) < 0)
+ if((iter_status = H5SL_iterate(type_ptr->ids, H5I__iterate_cb, &iter_udata)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_BADITER, FAIL, "iteration failed")
- }
+ } /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -1972,11 +2179,10 @@ H5I__find_id(hid_t id)
/* Check arguments */
type = H5I_TYPE(id);
- if (type <= H5I_BADID || type >= H5I_next_type)
+ if(type <= H5I_BADID || (int)type >= H5I_next_type)
HGOTO_DONE(NULL)
-
type_ptr = H5I_id_type_list_g[type];
- if (!type_ptr || type_ptr->init_count <= 0)
+ if(!type_ptr || type_ptr->init_count <= 0)
HGOTO_DONE(NULL)
/* Locate the ID node for the ID */
@@ -1996,6 +2202,9 @@ done:
*
* Failure: -1
*
+ * NOTE: Not safe for arbitrary VOL connectors as it relies on
+ * private H5G calls.
+ *
* Comments: Public function
* If 'name' is non-NULL then write up to 'size' bytes into that
* buffer and always return the length of the entry name.
@@ -2011,18 +2220,23 @@ done:
ssize_t
H5Iget_name(hid_t id, char *name/*out*/, size_t size)
{
- H5G_loc_t loc; /* Object location */
+ H5VL_object_t *vol_obj; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
ssize_t ret_value; /* Return value */
FUNC_ENTER_API((-1))
H5TRACE3("Zs", "ixz", id, name, size);
- /* Get object location */
- if(H5G_loc(id, &loc) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, (-1), "can't retrieve object location")
+ /* Get the object pointer */
+ if(NULL == (vol_obj = H5VL_vol_object(id)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADTYPE, (-1), "invalid identifier")
+
+ /* Set location parameters */
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(id);
/* Retrieve object's name */
- if((ret_value = H5G_get_name(&loc, name, size, NULL)) < 0)
+ if(H5VL_object_get(vol_obj, &loc_params, H5VL_OBJECT_GET_NAME, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &ret_value, name, size) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, (-1), "can't retrieve object name")
done:
@@ -2056,9 +2270,9 @@ H5Iget_file_id(hid_t obj_id)
/* Call internal function */
if (H5I_FILE == type || H5I_DATATYPE == type || H5I_GROUP == type || H5I_DATASET == type || H5I_ATTR == type) {
- if ((ret_value = H5I__get_file_id(obj_id, type)) < 0)
+ if ((ret_value = H5F_get_file_id(obj_id, type, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, H5I_INVALID_HID, "can't retrieve file ID")
- }
+ } /* end if */
else
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, H5I_INVALID_HID, "not an ID of a file object")
@@ -2068,52 +2282,94 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5I__get_file_id
+ * Function: H5I__find_id_cb
*
- * Purpose: The private version of H5Iget_file_id(), obtains the file
- * ID given an object ID.
+ * Purpose: Callback for searching for an ID with a specific pointer
*
- * Return: Success: The file ID associated with the object
- * Failure: H5I_INVALID_HID
+ * Return: Success: H5_ITER_CONT (0) or H5_ITER_STOP (1)
+ * Failure: H5_ITER_ERROR (-1)
*
*-------------------------------------------------------------------------
*/
-static hid_t
-H5I__get_file_id(hid_t obj_id, H5I_type_t type)
+static int
+H5I__find_id_cb(void *_item, void H5_ATTR_UNUSED *_key, void *_udata)
{
- hid_t ret_value = H5I_INVALID_HID; /* Return value */
+ H5I_id_info_t *item = (H5I_id_info_t *)_item; /* Pointer to the ID node */
+ H5I_get_id_ud_t *udata = (H5I_get_id_ud_t *)_udata; /* Pointer to user data */
+ H5I_type_t type = udata->obj_type;
+ const void *obj_ptr = NULL;
+ int ret_value = H5_ITER_CONT; /* Return value */
- FUNC_ENTER_STATIC
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Sanity check */
+ HDassert(item);
+ HDassert(udata);
- /* Process based on object type */
- if (type == H5I_FILE) {
- /* Increment reference count on file ID */
- if(H5I_inc_ref(obj_id, TRUE) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTSET, H5I_INVALID_HID, "incrementing file ID failed")
+ /* Get a pointer to the VOL connector's data */
+ obj_ptr = H5I__unwrap(item->obj_ptr, type);
- /* Set return value */
- ret_value = obj_id;
- }
- else {
- H5G_loc_t loc; /* Location of object */
+ /* Check for a match */
+ if (obj_ptr == udata->object) {
+ udata->ret_id = item->id;
+ ret_value = H5_ITER_STOP;
+ } /* end if */
- /* Get the object location information */
- if(H5G_loc(obj_id, &loc) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, H5I_INVALID_HID, "can't get object location")
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5I__find_id_cb() */
- /* Get the file ID for the object */
- if((ret_value = H5F_get_id(loc.oloc->file, TRUE)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, H5I_INVALID_HID, "can't get file ID")
- }
+
+/*-------------------------------------------------------------------------
+ * Function: H5I_find_id
+ *
+ * Purpose: Return the ID of an object by searching through the ID list
+ * for the type.
+ *
+ * Return: SUCCEED/FAIL
+ * (id will be set to H5I_INVALID_HID on errors or not found)
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5I_find_id(const void *object, H5I_type_t type, hid_t *id)
+{
+ H5I_id_type_t *type_ptr; /* Pointer to the type */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ HDassert(id);
+
+ *id = H5I_INVALID_HID;
+
+ type_ptr = H5I_id_type_list_g[type];
+ if (!type_ptr || type_ptr->init_count <= 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type")
+
+ /* Only iterate through ID list if it is initialized and there are IDs in type */
+ if (type_ptr->init_count > 0 && type_ptr->id_count > 0) {
+ H5I_get_id_ud_t udata; /* User data */
+ herr_t iter_status; /* Iteration status */
+
+ /* Set up iterator user data */
+ udata.object = object;
+ udata.obj_type = type;
+ udata.ret_id = H5I_INVALID_HID;
+
+ /* Iterate over IDs for the ID type */
+ if ((iter_status = H5SL_iterate(type_ptr->ids, H5I__find_id_cb, &udata)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADITER, FAIL, "iteration failed")
+
+ *id = udata.ret_id;
+ } /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5I__get_file_id() */
+} /* end H5I_find_id() */
-#ifdef H5I_DEBUG_OUTPUT
/*-------------------------------------------------------------------------
- * Function: H5I__debug_cb
+ * Function: H5I__id_dump_cb
*
* Purpose: Dump the contents of an ID to stderr for debugging.
*
@@ -2122,11 +2378,12 @@ done:
*-------------------------------------------------------------------------
*/
static int
-H5I__debug_cb(void *_item, void H5_ATTR_UNUSED *_key, void *_udata)
+H5I__id_dump_cb(void *_item, void H5_ATTR_UNUSED *_key, void *_udata)
{
H5I_id_info_t *item = (H5I_id_info_t *)_item; /* Pointer to the ID node */
H5I_type_t type = *(H5I_type_t *)_udata; /* User data */
H5G_name_t *path = NULL; /* Path to file object */
+ const void *obj_ptr = NULL; /* Pointer to VOL connector object */
FUNC_ENTER_STATIC_NOERR
@@ -2138,31 +2395,51 @@ H5I__debug_cb(void *_item, void H5_ATTR_UNUSED *_key, void *_udata)
switch (type) {
case H5I_GROUP:
{
- path = H5G_nameof((H5G_t*)item->obj_ptr);
+ const H5VL_object_t *vol_obj = (const H5VL_object_t *)item->obj_ptr;
+
+ obj_ptr = H5VL_object_data(vol_obj);
+ if(H5_VOL_NATIVE == vol_obj->connector->cls->value)
+ path = H5G_nameof((const H5G_t *)obj_ptr);
break;
}
+
case H5I_DATASET:
{
- path = H5D_nameof((H5D_t*)item->obj_ptr);
+ const H5VL_object_t *vol_obj = (const H5VL_object_t *)item->obj_ptr;
+
+ obj_ptr = H5VL_object_data(vol_obj);
+ if(H5_VOL_NATIVE == vol_obj->connector->cls->value)
+ path = H5D_nameof((const H5D_t *)obj_ptr);
break;
}
+
case H5I_DATATYPE:
{
- path = H5T_nameof((H5T_t*)item->obj_ptr);
+ const H5T_t *dt = (const H5T_t *)item->obj_ptr;
+
+ obj_ptr = (void *)H5T_get_actual_type((H5T_t *)dt); /* Casting away const OK - QAK */
+ path = H5T_nameof((const H5T_t *)obj_ptr);
break;
}
+
+ /* TODO: Maps will have to be added when they are supported in the
+ * native VOL connector.
+ */
+ case H5I_MAP:
+
case H5I_UNINIT:
case H5I_BADID:
case H5I_FILE:
case H5I_DATASPACE:
case H5I_ATTR:
- case H5I_REFERENCE:
case H5I_VFL:
+ case H5I_VOL:
case H5I_GENPROP_CLS:
case H5I_GENPROP_LST:
case H5I_ERROR_CLASS:
case H5I_ERROR_MSG:
case H5I_ERROR_STACK:
+ case H5I_SPACE_SEL_ITER:
case H5I_NTYPES:
default:
break; /* Other types of IDs are not stored in files */
@@ -2176,11 +2453,11 @@ H5I__debug_cb(void *_item, void H5_ATTR_UNUSED *_key, void *_udata)
}
FUNC_LEAVE_NOAPI(H5_ITER_CONT)
-} /* end H5I__debug_cb() */
+} /* end H5I__id_dump_cb() */
/*-------------------------------------------------------------------------
- * Function: H5I__debug
+ * Function: H5I_dump_ids_for_type
*
* Purpose: Dump the contents of a type to stderr for debugging.
*
@@ -2188,27 +2465,33 @@ H5I__debug_cb(void *_item, void H5_ATTR_UNUSED *_key, void *_udata)
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5I__debug(H5I_type_t type)
+herr_t
+H5I_dump_ids_for_type(H5I_type_t type)
{
- H5I_id_type_t *type_ptr;
+ H5I_id_type_t *type_ptr = NULL;
- FUNC_ENTER_STATIC_NOERR
+ FUNC_ENTER_NOAPI_NOERR
HDfprintf(stderr, "Dumping ID type %d\n", (int)type);
type_ptr = H5I_id_type_list_g[type];
- /* Header */
- HDfprintf(stderr, " init_count = %u\n", type_ptr->init_count);
- HDfprintf(stderr, " reserved = %u\n", type_ptr->cls->reserved);
- HDfprintf(stderr, " id_count = %llu\n", (unsigned long long)type_ptr->id_count);
- HDfprintf(stderr, " nextid = %llu\n", (unsigned long long)type_ptr->nextid);
+ if(type_ptr) {
+
+ /* Header */
+ HDfprintf(stderr, " init_count = %u\n", type_ptr->init_count);
+ HDfprintf(stderr, " reserved = %u\n", type_ptr->cls->reserved);
+ HDfprintf(stderr, " id_count = %llu\n", (unsigned long long)type_ptr->id_count);
+ HDfprintf(stderr, " nextid = %llu\n", (unsigned long long)type_ptr->nextid);
- /* List */
- HDfprintf(stderr, " List:\n");
- H5SL_iterate(type_ptr->ids, H5I__debug_cb, &type);
+ /* List */
+ if(type_ptr->id_count > 0) {
+ HDfprintf(stderr, " List:\n");
+ H5SL_iterate(type_ptr->ids, H5I__id_dump_cb, &type);
+ }
+ }
+ else
+ HDfprintf(stderr, "Global type info/tracking pointer for that type is NULL\n");
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5I__debug() */
-#endif /* H5I_DEBUG_OUTPUT */
+} /* end H5I_dump_ids_for_type() */
diff --git a/src/H5Iprivate.h b/src/H5Iprivate.h
index a10147d..cc1ce1f 100644
--- a/src/H5Iprivate.h
+++ b/src/H5Iprivate.h
@@ -25,6 +25,7 @@
/* Private headers needed by this file */
#include "H5private.h"
+#include "H5VLprivate.h"
/**************************/
/* Library Private Macros */
@@ -66,13 +67,7 @@ typedef struct H5I_class_t {
H5_DLL herr_t H5I_register_type(const H5I_class_t *cls);
H5_DLL int64_t H5I_nmembers(H5I_type_t type);
H5_DLL herr_t H5I_clear_type(H5I_type_t type, hbool_t force, hbool_t app_ref);
-H5_DLL hid_t H5I_register(H5I_type_t type, const void *object, hbool_t app_ref);
-H5_DLL herr_t H5I_register_with_id(H5I_type_t type, const void *object, hbool_t app_ref, hid_t id);
-H5_DLL void *H5I_subst(hid_t id, const void *new_object);
-H5_DLL void *H5I_object(hid_t id);
-H5_DLL void *H5I_object_verify(hid_t id, H5I_type_t id_type);
H5_DLL H5I_type_t H5I_get_type(hid_t id);
-H5_DLL void *H5I_remove(hid_t id);
H5_DLL herr_t H5I_iterate(H5I_type_t type, H5I_search_func_t func, void *udata, hbool_t app_ref);
H5_DLL int H5I_get_ref(hid_t id, hbool_t app_ref);
H5_DLL int H5I_inc_ref(hid_t id, hbool_t app_ref);
@@ -80,6 +75,31 @@ H5_DLL int H5I_dec_ref(hid_t id);
H5_DLL int H5I_dec_app_ref(hid_t id);
H5_DLL int H5I_dec_app_ref_always_close(hid_t id);
H5_DLL int H5I_dec_type_ref(H5I_type_t type);
+H5_DLL herr_t H5I_find_id(const void *object, H5I_type_t type, hid_t *id /*out*/);
+
+/* NOTE: The object and ID functions below deal in non-VOL objects (i.e.;
+ * H5S_t, etc.). Similar VOL calls exist in H5VLprivate.h. Use
+ * the H5VL calls with objects that go through the VOL, such as
+ * datasets and groups, and the H5I calls with objects
+ * that do not, such as property lists and dataspaces. Datatypes
+ * are can be either named, where they will use the VOL, or not,
+ * and thus require special treatment. See the datatype docs for
+ * how to handle this.
+ */
+
+/* Functions that manipulate objects */
+H5_DLL void *H5I_object(hid_t id);
+H5_DLL void *H5I_object_verify(hid_t id, H5I_type_t id_type);
+H5_DLL void *H5I_remove(hid_t id);
+H5_DLL void *H5I_subst(hid_t id, const void *new_object);
+H5_DLL htri_t H5I_is_file_object(hid_t id);
+
+/* ID registration functions */
+H5_DLL hid_t H5I_register(H5I_type_t type, const void *object, hbool_t app_ref);
+H5_DLL herr_t H5I_register_using_existing_id(H5I_type_t type, void *object, hbool_t app_ref, hid_t existing_id);
+
+/* Debugging functions */
+H5_DLL herr_t H5I_dump_ids_for_type(H5I_type_t type);
#endif /* _H5Iprivate_H */
diff --git a/src/H5Ipublic.h b/src/H5Ipublic.h
index c471e5a..34a408f 100644
--- a/src/H5Ipublic.h
+++ b/src/H5Ipublic.h
@@ -29,9 +29,6 @@
*
* When adding types here, add a section to the 'misc19' test in test/tmisc.c
* to verify that the H5I{inc|dec|get}_ref() routines work correctly with it.
- *
- * NOTE: H5I_REFERENCE is not used by the library and has been deprecated
- * with a tentative removal version of 1.12.0. (DER, July 2017)
*/
typedef enum H5I_type_t {
H5I_UNINIT = (-2), /* uninitialized type */
@@ -41,14 +38,16 @@ typedef enum H5I_type_t {
H5I_DATATYPE, /* type ID for Datatype objects */
H5I_DATASPACE, /* type ID for Dataspace objects */
H5I_DATASET, /* type ID for Dataset objects */
+ H5I_MAP, /* type ID for Map objects */
H5I_ATTR, /* type ID for Attribute objects */
- H5I_REFERENCE, /* *DEPRECATED* type ID for Reference objects */
H5I_VFL, /* type ID for virtual file layer */
+ H5I_VOL, /* type ID for virtual object layer */
H5I_GENPROP_CLS, /* type ID for generic property list classes */
H5I_GENPROP_LST, /* type ID for generic property lists */
H5I_ERROR_CLASS, /* type ID for error classes */
H5I_ERROR_MSG, /* type ID for error messages */
H5I_ERROR_STACK, /* type ID for error stacks */
+ H5I_SPACE_SEL_ITER, /* type ID for dataspace selection iterator */
H5I_NTYPES /* number of library types, MUST BE LAST! */
} H5I_type_t;
@@ -71,6 +70,9 @@ typedef herr_t (*H5I_free_t)(void *);
/* Type of the function to compare objects & keys */
typedef int (*H5I_search_func_t)(void *obj, hid_t id, void *key);
+/* Type of the H5Iiterate callback function */
+typedef herr_t (*H5I_iterate_func_t)(hid_t id, void *udata);
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -93,6 +95,7 @@ H5_DLL int H5Iinc_type_ref(H5I_type_t type);
H5_DLL int H5Idec_type_ref(H5I_type_t type);
H5_DLL int H5Iget_type_ref(H5I_type_t type);
H5_DLL void *H5Isearch(H5I_type_t type, H5I_search_func_t func, void *key);
+H5_DLL herr_t H5Iiterate(H5I_type_t type, H5I_iterate_func_t op, void *op_data);
H5_DLL herr_t H5Inmembers(H5I_type_t type, hsize_t *num_members);
H5_DLL htri_t H5Itype_exists(H5I_type_t type);
H5_DLL htri_t H5Iis_valid(hid_t id);
diff --git a/src/H5Itest.c b/src/H5Itest.c
index 4b54835..79bc482 100644
--- a/src/H5Itest.c
+++ b/src/H5Itest.c
@@ -78,26 +78,41 @@
ssize_t
H5I__get_name_test(hid_t id, char *name/*out*/, size_t size, hbool_t *cached)
{
+ H5VL_object_t *vol_obj; /* Object token of id */
H5G_loc_t loc; /* Object location */
hbool_t api_ctx_pushed = FALSE; /* Whether API context pushed */
+ hbool_t vol_wrapper_set = FALSE;/* Whether the VOL object wrapping context was set up */
ssize_t ret_value = -1; /* Return value */
FUNC_ENTER_PACKAGE
- /* Get object location */
- if(H5G_loc(id, &loc) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, (-1), "can't retrieve object location")
-
/* Set API context */
if(H5CX_push() < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTSET, (-1), "can't set API context")
api_ctx_pushed = TRUE;
+ /* Get the object pointer */
+ if(NULL == (vol_obj = H5VL_vol_object(id)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADTYPE, (-1), "invalid identifier")
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTSET, FAIL, "can't set VOL wrapper info")
+ vol_wrapper_set = TRUE;
+
+ /* Get object location */
+ if(H5G_loc(id, &loc) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, (-1), "can't retrieve object location")
+
/* Call internal group routine to retrieve object's name */
if((ret_value = H5G_get_name(&loc, name, size, cached)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, (-1), "can't retrieve object name")
done:
+ /* Reset object wrapping info in API context */
+ if(vol_wrapper_set && H5VL_reset_vol_wrapper() < 0)
+ HDONE_ERROR(H5E_ATOM, H5E_CANTRESET, FAIL, "can't reset VOL wrapper info")
+
if(api_ctx_pushed && H5CX_pop() < 0)
HDONE_ERROR(H5E_SYM, H5E_CANTRESET, (-1), "can't reset API context")
diff --git a/src/H5L.c b/src/H5L.c
index b659d42..1e554a9 100644
--- a/src/H5L.c
+++ b/src/H5L.c
@@ -33,6 +33,8 @@
#include "H5MMprivate.h" /* Memory management */
#include "H5Oprivate.h" /* File objects */
#include "H5Pprivate.h" /* Property lists */
+#include "H5VLprivate.h" /* Virtual Object Layer */
+
/****************/
/* Local Macros */
@@ -272,8 +274,11 @@ herr_t
H5Lmove(hid_t src_loc_id, const char *src_name, hid_t dst_loc_id,
const char *dst_name, hid_t lcpl_id, hid_t lapl_id)
{
- H5G_loc_t src_loc, *src_loc_p;
- H5G_loc_t dst_loc, *dst_loc_p;
+ H5VL_object_t *vol_obj1 = NULL; /* Object token of src_id */
+ H5VL_loc_params_t loc_params1;
+ H5VL_object_t *vol_obj2 = NULL; /* Object token of dst_id */
+ H5VL_loc_params_t loc_params2;
+ H5VL_object_t tmp_vol_obj; /* Temporary object token */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -283,10 +288,6 @@ H5Lmove(hid_t src_loc_id, const char *src_name, hid_t dst_loc_id,
/* Check arguments */
if(src_loc_id == H5L_SAME_LOC && dst_loc_id == H5L_SAME_LOC)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "source and destination should not both be H5L_SAME_LOC")
- if(src_loc_id != H5L_SAME_LOC && H5G_loc(src_loc_id, &src_loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
- if(dst_loc_id != H5L_SAME_LOC && H5G_loc(dst_loc_id, &dst_loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!src_name || !*src_name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no current name specified")
if(!dst_name || !*dst_name)
@@ -294,21 +295,47 @@ H5Lmove(hid_t src_loc_id, const char *src_name, hid_t dst_loc_id,
if(lcpl_id != H5P_DEFAULT && (TRUE != H5P_isa_class(lcpl_id, H5P_LINK_CREATE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a link creation property list")
+ /* Check the link create property list */
+ if(H5P_DEFAULT == lcpl_id)
+ lcpl_id = H5P_LINK_CREATE_DEFAULT;
+
/* Verify access property list and set up collective metadata if appropriate */
if(H5CX_set_apl(&lapl_id, H5P_CLS_LACC,
((src_loc_id != H5L_SAME_LOC) ? src_loc_id : dst_loc_id), TRUE) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access property list info")
- /* Set up src & dst location pointers */
- src_loc_p = &src_loc;
- dst_loc_p = &dst_loc;
- if(src_loc_id == H5L_SAME_LOC)
- src_loc_p = dst_loc_p;
- else if(dst_loc_id == H5L_SAME_LOC)
- dst_loc_p = src_loc_p;
+ /* Set location paramter for source object */
+ loc_params1.type = H5VL_OBJECT_BY_NAME;
+ loc_params1.loc_data.loc_by_name.name = src_name;
+ loc_params1.loc_data.loc_by_name.lapl_id = lapl_id;
+ loc_params1.obj_type = H5I_get_type(src_loc_id);
+
+ /* Set location paramter for destination object */
+ loc_params2.type = H5VL_OBJECT_BY_NAME;
+ loc_params2.loc_data.loc_by_name.name = dst_name;
+ loc_params2.loc_data.loc_by_name.lapl_id = lapl_id;
+ loc_params2.obj_type = H5I_get_type(dst_loc_id);
+
+ if (H5L_SAME_LOC != src_loc_id)
+ /* Get the location object */
+ if (NULL == (vol_obj1 = (H5VL_object_t *)H5I_object(src_loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+ if (H5L_SAME_LOC != dst_loc_id)
+ /* Get the location object */
+ if (NULL == (vol_obj2 = (H5VL_object_t *)H5I_object(dst_loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Make sure that the VOL connectors are the same */
+ if (vol_obj1 && vol_obj2)
+ if (vol_obj1->connector->cls->value != vol_obj2->connector->cls->value)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "Objects are accessed through different VOL connectors and can't be linked")
+
+ /* Construct a temporary source VOL object */
+ tmp_vol_obj.data = (vol_obj1 ? vol_obj1->data : NULL);
+ tmp_vol_obj.connector = (vol_obj1 ? vol_obj1->connector : vol_obj2->connector);
/* Move the link */
- if(H5L_move(src_loc_p, src_name, dst_loc_p, dst_name, FALSE, lcpl_id) < 0)
+ if(H5VL_link_move(&tmp_vol_obj, &loc_params1, vol_obj2, &loc_params2, lcpl_id, lapl_id, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTMOVE, FAIL, "unable to move link")
done:
@@ -334,8 +361,11 @@ herr_t
H5Lcopy(hid_t src_loc_id, const char *src_name, hid_t dst_loc_id,
const char *dst_name, hid_t lcpl_id, hid_t lapl_id)
{
- H5G_loc_t src_loc, *src_loc_p;
- H5G_loc_t dst_loc, *dst_loc_p;
+ H5VL_object_t *vol_obj1 = NULL; /* Object token of src_id */
+ H5VL_loc_params_t loc_params1;
+ H5VL_object_t *vol_obj2 = NULL; /* Object token of dst_id */
+ H5VL_loc_params_t loc_params2;
+ H5VL_object_t tmp_vol_obj; /* Temporary object token */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -345,10 +375,6 @@ H5Lcopy(hid_t src_loc_id, const char *src_name, hid_t dst_loc_id,
/* Check arguments */
if(src_loc_id == H5L_SAME_LOC && dst_loc_id == H5L_SAME_LOC)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "source and destination should not both be H5L_SAME_LOC")
- if(src_loc_id != H5L_SAME_LOC && H5G_loc(src_loc_id, &src_loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
- if(dst_loc_id != H5L_SAME_LOC && H5G_loc(dst_loc_id, &dst_loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!src_name || !*src_name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no current name specified")
if(!dst_name || !*dst_name)
@@ -356,21 +382,47 @@ H5Lcopy(hid_t src_loc_id, const char *src_name, hid_t dst_loc_id,
if(lcpl_id != H5P_DEFAULT && (TRUE != H5P_isa_class(lcpl_id, H5P_LINK_CREATE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a link creation property list")
+ /* Check the link create property list */
+ if(H5P_DEFAULT == lcpl_id)
+ lcpl_id = H5P_LINK_CREATE_DEFAULT;
+
/* Verify access property list and set up collective metadata if appropriate */
if(H5CX_set_apl(&lapl_id, H5P_CLS_LACC,
((src_loc_id != H5L_SAME_LOC) ? src_loc_id : dst_loc_id), TRUE) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access property list info")
- /* Set up src & dst location pointers */
- src_loc_p = &src_loc;
- dst_loc_p = &dst_loc;
- if(src_loc_id == H5L_SAME_LOC)
- src_loc_p = dst_loc_p;
- else if(dst_loc_id == H5L_SAME_LOC)
- dst_loc_p = src_loc_p;
+ /* Set location paramter for source object */
+ loc_params1.type = H5VL_OBJECT_BY_NAME;
+ loc_params1.loc_data.loc_by_name.name = src_name;
+ loc_params1.loc_data.loc_by_name.lapl_id = lapl_id;
+ loc_params1.obj_type = H5I_get_type(src_loc_id);
+
+ /* Set location paramter for destination object */
+ loc_params2.type = H5VL_OBJECT_BY_NAME;
+ loc_params2.loc_data.loc_by_name.name = dst_name;
+ loc_params2.loc_data.loc_by_name.lapl_id = lapl_id;
+ loc_params2.obj_type = H5I_get_type(dst_loc_id);
+
+ if(H5L_SAME_LOC != src_loc_id)
+ /* Get the location object */
+ if(NULL == (vol_obj1 = (H5VL_object_t *)H5I_object(src_loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+ if(H5L_SAME_LOC != dst_loc_id)
+ /* Get the location object */
+ if(NULL == (vol_obj2 = (H5VL_object_t *)H5I_object(dst_loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Make sure that the VOL connectors are the same */
+ if(vol_obj1 && vol_obj2)
+ if(vol_obj1->connector->cls->value != vol_obj2->connector->cls->value)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "Objects are accessed through different VOL connectors and can't be linked")
+
+ /* Construct a temporary source VOL object */
+ tmp_vol_obj.data = (vol_obj1 ? vol_obj1->data : NULL);
+ tmp_vol_obj.connector = (vol_obj1 ? vol_obj1->connector : vol_obj2->connector);
/* Copy the link */
- if(H5L_move(src_loc_p, src_name, dst_loc_p, dst_name, TRUE, lcpl_id) < 0)
+ if(H5VL_link_copy(&tmp_vol_obj, &loc_params1, vol_obj2, &loc_params2, lcpl_id, lapl_id, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTMOVE, FAIL, "unable to copy link")
done:
@@ -397,18 +449,19 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5Lcreate_soft(const char *link_target, hid_t link_loc_id,
- const char *link_name, hid_t lcpl_id, hid_t lapl_id)
+H5Lcreate_soft(const char *link_target, hid_t link_loc_id, const char *link_name,
+ hid_t lcpl_id, hid_t lapl_id)
{
- H5G_loc_t link_loc; /* Group location for new link */
+ H5VL_object_t *vol_obj = NULL; /* object token of loc_id */
+ H5VL_loc_params_t loc_params;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE5("e", "*si*sii", link_target, link_loc_id, link_name, lcpl_id, lapl_id);
/* Check arguments */
- if(H5G_loc(link_loc_id, &link_loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
+ if(link_loc_id == H5L_SAME_LOC)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "link location id should not be H5L_SAME_LOC")
if(!link_target)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "link_target parameter cannot be NULL")
if(!*link_target)
@@ -420,12 +473,26 @@ H5Lcreate_soft(const char *link_target, hid_t link_loc_id,
if(lcpl_id != H5P_DEFAULT && (TRUE != H5P_isa_class(lcpl_id, H5P_LINK_CREATE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a link creation property list")
+ /* Check the group access property list */
+ if(H5P_DEFAULT == lcpl_id)
+ lcpl_id = H5P_LINK_CREATE_DEFAULT;
+
+ /* Set location fields */
+ loc_params.type = H5VL_OBJECT_BY_NAME;
+ loc_params.loc_data.loc_by_name.name = link_name;
+ loc_params.loc_data.loc_by_name.lapl_id = lapl_id;
+ loc_params.obj_type = H5I_get_type(link_loc_id);
+
+ /* get the location object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5VL_vol_object(link_loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
/* Verify access property list and set up collective metadata if appropriate */
if(H5CX_set_apl(&lapl_id, H5P_CLS_LACC, link_loc_id, TRUE) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access property list info")
/* Create the link */
- if(H5L_create_soft(link_target, &link_loc, link_name, lcpl_id) < 0)
+ if(H5VL_link_create(H5VL_LINK_CREATE_SOFT, vol_obj, &loc_params, lcpl_id, lapl_id, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, link_target) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTCREATE, FAIL, "unable to create soft link")
done:
@@ -453,8 +520,11 @@ herr_t
H5Lcreate_hard(hid_t cur_loc_id, const char *cur_name,
hid_t new_loc_id, const char *new_name, hid_t lcpl_id, hid_t lapl_id)
{
- H5G_loc_t cur_loc, *cur_loc_p;
- H5G_loc_t new_loc, *new_loc_p;
+ H5VL_object_t *vol_obj1 = NULL; /* Object token of cur_loc_id */
+ H5VL_object_t *vol_obj2 = NULL; /* Object token of new_loc_id */
+ H5VL_object_t tmp_vol_obj; /* Temporary object token of */
+ H5VL_loc_params_t loc_params1;
+ H5VL_loc_params_t loc_params2;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -464,10 +534,6 @@ H5Lcreate_hard(hid_t cur_loc_id, const char *cur_name,
/* Check arguments */
if(cur_loc_id == H5L_SAME_LOC && new_loc_id == H5L_SAME_LOC)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "source and destination should not be both H5L_SAME_LOC")
- if(cur_loc_id != H5L_SAME_LOC && H5G_loc(cur_loc_id, &cur_loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
- if(new_loc_id != H5L_SAME_LOC && H5G_loc(new_loc_id, &new_loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!cur_name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "cur_name parameter cannot be NULL")
if(!*cur_name)
@@ -479,22 +545,45 @@ H5Lcreate_hard(hid_t cur_loc_id, const char *cur_name,
if(lcpl_id != H5P_DEFAULT && (TRUE != H5P_isa_class(lcpl_id, H5P_LINK_CREATE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a link creation property list")
+ /* Check the link create property list */
+ if(H5P_DEFAULT == lcpl_id)
+ lcpl_id = H5P_LINK_CREATE_DEFAULT;
+
/* Verify access property list and set up collective metadata if appropriate */
if(H5CX_set_apl(&lapl_id, H5P_CLS_LACC, cur_loc_id, TRUE) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access property list info")
- /* Set up current & new location pointers */
- cur_loc_p = &cur_loc;
- new_loc_p = &new_loc;
- if(cur_loc_id == H5L_SAME_LOC)
- cur_loc_p = new_loc_p;
- else if(new_loc_id == H5L_SAME_LOC)
- new_loc_p = cur_loc_p;
- else if(cur_loc_p->oloc->file != new_loc_p->oloc->file)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "source and destination should be in the same file.")
+ /* Set up current & new location structs */
+ loc_params1.type = H5VL_OBJECT_BY_NAME;
+ loc_params1.obj_type = H5I_get_type(cur_loc_id);
+ loc_params1.loc_data.loc_by_name.name = cur_name;
+ loc_params1.loc_data.loc_by_name.lapl_id = lapl_id;
+
+ loc_params2.type = H5VL_OBJECT_BY_NAME;
+ loc_params2.obj_type = H5I_get_type(new_loc_id);
+ loc_params2.loc_data.loc_by_name.name = new_name;
+ loc_params2.loc_data.loc_by_name.lapl_id = lapl_id;
+
+ if(H5L_SAME_LOC != cur_loc_id)
+ /* Get the current location object */
+ if (NULL == (vol_obj1 = (H5VL_object_t *)H5VL_vol_object(cur_loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+ if(H5L_SAME_LOC != new_loc_id)
+ /* Get the new location object */
+ if(NULL == (vol_obj2 = (H5VL_object_t *)H5VL_vol_object(new_loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Make sure that the VOL connectors are the same */
+ if(vol_obj1 && vol_obj2)
+ if(vol_obj1->connector->cls->value != vol_obj2->connector->cls->value)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "Objects are accessed through different VOL connectors and can't be linked")
+
+ /* Construct a temporary VOL object */
+ tmp_vol_obj.data = (vol_obj2 ? (vol_obj2->data) : NULL);
+ tmp_vol_obj.connector = (vol_obj1 != NULL ? vol_obj1->connector : vol_obj2->connector);
/* Create the link */
- if(H5L_create_hard(cur_loc_p, cur_name, new_loc_p, new_name, lcpl_id) < 0)
+ if(H5VL_link_create(H5VL_LINK_CREATE_HARD, &tmp_vol_obj, &loc_params2, lcpl_id, lapl_id, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, (vol_obj1 ? vol_obj1->data : NULL), &loc_params1) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTCREATE, FAIL, "unable to create hard link")
done:
@@ -530,27 +619,41 @@ herr_t
H5Lcreate_ud(hid_t link_loc_id, const char *link_name, H5L_type_t link_type,
const void *udata, size_t udata_size, hid_t lcpl_id, hid_t lapl_id)
{
- H5G_loc_t link_loc;
- herr_t ret_value = SUCCEED; /* Return value */
+ H5VL_object_t *vol_obj = NULL; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE7("e", "i*sLl*xzii", link_loc_id, link_name, link_type, udata,
udata_size, lcpl_id, lapl_id);
/* Check arguments */
- if(H5G_loc(link_loc_id, &link_loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!link_name || !*link_name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no link name specified")
if(link_type < H5L_TYPE_UD_MIN || link_type > H5L_TYPE_MAX)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid link class")
+ if(!udata && udata_size)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "udata cannot be NULL if udata_size is non-zero")
+
+ /* Check the group access property list */
+ if(H5P_DEFAULT == lcpl_id)
+ lcpl_id = H5P_LINK_CREATE_DEFAULT;
/* Verify access property list and set up collective metadata if appropriate */
if(H5CX_set_apl(&lapl_id, H5P_CLS_LACC, link_loc_id, TRUE) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access property list info")
+ loc_params.type = H5VL_OBJECT_BY_NAME;
+ loc_params.loc_data.loc_by_name.name = link_name;
+ loc_params.loc_data.loc_by_name.lapl_id = lapl_id;
+ loc_params.obj_type = H5I_get_type(link_loc_id);
+
+ /* get the location object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(link_loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
/* Create external link */
- if(H5L__create_ud(&link_loc, link_name, udata, udata_size, link_type, lcpl_id) < 0)
+ if(H5VL_link_create(H5VL_LINK_CREATE_UD, vol_obj, &loc_params, lcpl_id, lapl_id, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, (int)link_type, udata, udata_size) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "unable to create link")
done:
@@ -578,15 +681,14 @@ done:
herr_t
H5Ldelete(hid_t loc_id, const char *name, hid_t lapl_id)
{
- H5G_loc_t loc; /* Group's location */
+ H5VL_object_t *vol_obj = NULL; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE3("e", "i*si", loc_id, name, lapl_id);
/* Check arguments */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!name || !*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name")
@@ -594,8 +696,18 @@ H5Ldelete(hid_t loc_id, const char *name, hid_t lapl_id)
if(H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, TRUE) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access property list info")
+ /* Fill in the location struct fields */
+ loc_params.type = H5VL_OBJECT_BY_NAME;
+ loc_params.obj_type = H5I_get_type(loc_id);
+ loc_params.loc_data.loc_by_name.name = name;
+ loc_params.loc_data.loc_by_name.lapl_id = lapl_id;
+
+ /* get the location object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
/* Unlink */
- if(H5L_delete(&loc, name) < 0)
+ if(H5VL_link_specific(vol_obj, &loc_params, H5VL_LINK_DELETE, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTDELETE, FAIL, "unable to delete link")
done:
@@ -626,15 +738,14 @@ herr_t
H5Ldelete_by_idx(hid_t loc_id, const char *group_name, H5_index_t idx_type,
H5_iter_order_t order, hsize_t n, hid_t lapl_id)
{
- H5G_loc_t loc; /* Group's location */
+ H5VL_object_t *vol_obj = NULL; /* object token of loc_id */
+ H5VL_loc_params_t loc_params;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE6("e", "i*sIiIohi", loc_id, group_name, idx_type, order, n, lapl_id);
/* Check arguments */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!group_name || !*group_name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified")
if(idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N)
@@ -646,8 +757,20 @@ H5Ldelete_by_idx(hid_t loc_id, const char *group_name, H5_index_t idx_type,
if(H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, TRUE) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access property list info")
+ loc_params.type = H5VL_OBJECT_BY_IDX;
+ loc_params.loc_data.loc_by_idx.name = group_name;
+ loc_params.loc_data.loc_by_idx.idx_type = idx_type;
+ loc_params.loc_data.loc_by_idx.order = order;
+ loc_params.loc_data.loc_by_idx.n = n;
+ loc_params.loc_data.loc_by_idx.lapl_id = lapl_id;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* Get the location object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
/* Delete the link */
- if(H5L_delete_by_idx(&loc, group_name, idx_type, order, n) < 0)
+ if(H5VL_link_specific(vol_obj, &loc_params, H5VL_LINK_DELETE, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTDELETE, FAIL, "unable to delete link")
done:
@@ -678,15 +801,14 @@ herr_t
H5Lget_val(hid_t loc_id, const char *name, void *buf/*out*/, size_t size,
hid_t lapl_id)
{
- H5G_loc_t loc; /* Group location for location to query */
+ H5VL_object_t *vol_obj = NULL; /* object token of loc_id */
+ H5VL_loc_params_t loc_params;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE5("e", "i*sxzi", loc_id, name, buf, size, lapl_id);
/* Check arguments */
- if(H5G_loc(loc_id, &loc))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!name || !*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified")
@@ -694,8 +816,17 @@ H5Lget_val(hid_t loc_id, const char *name, void *buf/*out*/, size_t size,
if(H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, FALSE) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access property list info")
+ loc_params.type = H5VL_OBJECT_BY_NAME;
+ loc_params.obj_type = H5I_get_type(loc_id);
+ loc_params.loc_data.loc_by_name.name = name;
+ loc_params.loc_data.loc_by_name.lapl_id = lapl_id;
+
+ /* Get the location object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
/* Get the link value */
- if(H5L_get_val(&loc, name, buf, size) < 0)
+ if(H5VL_link_get(vol_obj, &loc_params, H5VL_LINK_GET_VAL, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, buf, size) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "unable to get link value for '%s'", name)
done:
@@ -726,7 +857,8 @@ H5Lget_val_by_idx(hid_t loc_id, const char *group_name, H5_index_t idx_type,
H5_iter_order_t order, hsize_t n, void *buf/*out*/, size_t size,
hid_t lapl_id)
{
- H5G_loc_t loc; /* Group location for location to query */
+ H5VL_object_t *vol_obj = NULL; /* object token of loc_id */
+ H5VL_loc_params_t loc_params;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -734,8 +866,6 @@ H5Lget_val_by_idx(hid_t loc_id, const char *group_name, H5_index_t idx_type,
lapl_id);
/* Check arguments */
- if(H5G_loc(loc_id, &loc))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!group_name || !*group_name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified")
if(idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N)
@@ -747,8 +877,20 @@ H5Lget_val_by_idx(hid_t loc_id, const char *group_name, H5_index_t idx_type,
if(H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, FALSE) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access property list info")
+ loc_params.type = H5VL_OBJECT_BY_IDX;
+ loc_params.loc_data.loc_by_idx.name = group_name;
+ loc_params.loc_data.loc_by_idx.idx_type = idx_type;
+ loc_params.loc_data.loc_by_idx.order = order;
+ loc_params.loc_data.loc_by_idx.n = n;
+ loc_params.loc_data.loc_by_idx.lapl_id = lapl_id;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* get the location object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
/* Get the link value */
- if(H5L_get_val_by_idx(&loc, group_name, idx_type, order, n, buf, size) < 0)
+ if(H5VL_link_get(vol_obj, &loc_params, H5VL_LINK_GET_VAL, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, buf, size) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "unable to get link value")
done:
@@ -771,15 +913,14 @@ done:
htri_t
H5Lexists(hid_t loc_id, const char *name, hid_t lapl_id)
{
- H5G_loc_t loc;
+ H5VL_object_t *vol_obj = NULL; /* object token of loc_id */
+ H5VL_loc_params_t loc_params;
htri_t ret_value = FAIL; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE3("t", "i*si", loc_id, name, lapl_id);
/* Check arguments */
- if(H5G_loc(loc_id, &loc))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "name parameter cannot be NULL")
if(!*name)
@@ -789,8 +930,18 @@ H5Lexists(hid_t loc_id, const char *name, hid_t lapl_id)
if(H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, FALSE) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access property list info")
+ /* Set location struct fields */
+ loc_params.type = H5VL_OBJECT_BY_NAME;
+ loc_params.obj_type = H5I_get_type(loc_id);
+ loc_params.loc_data.loc_by_name.name = name;
+ loc_params.loc_data.loc_by_name.lapl_id = lapl_id;
+
+ /* Get the location object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
/* Check for the existence of the link */
- if((ret_value = H5L_exists(&loc, name)) < 0)
+ if(H5VL_link_specific(vol_obj, &loc_params, H5VL_LINK_EXISTS, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &ret_value) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "unable to get link info")
done:
@@ -816,15 +967,14 @@ herr_t
H5Lget_info(hid_t loc_id, const char *name, H5L_info_t *linfo /*out*/,
hid_t lapl_id)
{
- H5G_loc_t loc;
+ H5VL_object_t *vol_obj = NULL; /* object token of loc_id */
+ H5VL_loc_params_t loc_params;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE4("e", "i*sxi", loc_id, name, linfo, lapl_id);
/* Check arguments */
- if(H5G_loc(loc_id, &loc))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!name || !*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified")
@@ -832,8 +982,17 @@ H5Lget_info(hid_t loc_id, const char *name, H5L_info_t *linfo /*out*/,
if(H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, TRUE) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access property list info")
+ loc_params.type = H5VL_OBJECT_BY_NAME;
+ loc_params.obj_type = H5I_get_type(loc_id);
+ loc_params.loc_data.loc_by_name.name = name;
+ loc_params.loc_data.loc_by_name.lapl_id = lapl_id;
+
+ /* get the location object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
/* Get the link information */
- if(H5L_get_info(&loc, name, linfo) < 0)
+ if(H5VL_link_get(vol_obj, &loc_params, H5VL_LINK_GET_INFO, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, linfo) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "unable to get link info")
done:
@@ -860,7 +1019,8 @@ H5Lget_info_by_idx(hid_t loc_id, const char *group_name,
H5_index_t idx_type, H5_iter_order_t order, hsize_t n,
H5L_info_t *linfo /*out*/, hid_t lapl_id)
{
- H5G_loc_t loc; /* Group location for group to query */
+ H5VL_object_t *vol_obj = NULL; /* object token of loc_id */
+ H5VL_loc_params_t loc_params;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -868,8 +1028,6 @@ H5Lget_info_by_idx(hid_t loc_id, const char *group_name,
lapl_id);
/* Check arguments */
- if(H5G_loc(loc_id, &loc))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!group_name || !*group_name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified")
if(idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N)
@@ -881,8 +1039,20 @@ H5Lget_info_by_idx(hid_t loc_id, const char *group_name,
if(H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, FALSE) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access property list info")
+ loc_params.type = H5VL_OBJECT_BY_IDX;
+ loc_params.loc_data.loc_by_idx.name = group_name;
+ loc_params.loc_data.loc_by_idx.idx_type = idx_type;
+ loc_params.loc_data.loc_by_idx.order = order;
+ loc_params.loc_data.loc_by_idx.n = n;
+ loc_params.loc_data.loc_by_idx.lapl_id = lapl_id;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* get the location object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
/* Get the link information */
- if(H5L_get_info_by_idx(&loc, group_name, idx_type, order, n, linfo) < 0)
+ if(H5VL_link_get(vol_obj, &loc_params, H5VL_LINK_GET_INFO, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, linfo) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "unable to get link info")
done:
@@ -1044,7 +1214,8 @@ H5Lget_name_by_idx(hid_t loc_id, const char *group_name,
H5_index_t idx_type, H5_iter_order_t order, hsize_t n,
char *name /*out*/, size_t size, hid_t lapl_id)
{
- H5G_loc_t loc; /* Location of group */
+ H5VL_object_t *vol_obj = NULL; /* object token of loc_id */
+ H5VL_loc_params_t loc_params;
ssize_t ret_value = -1; /* Return value */
FUNC_ENTER_API((-1))
@@ -1052,8 +1223,6 @@ H5Lget_name_by_idx(hid_t loc_id, const char *group_name,
lapl_id);
/* Check arguments */
- if(H5G_loc(loc_id, &loc))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "not a location")
if(!group_name || !*group_name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, (-1), "no name specified")
if(idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N)
@@ -1065,8 +1234,21 @@ H5Lget_name_by_idx(hid_t loc_id, const char *group_name,
if(H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, TRUE) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTSET, (-1), "can't set access property list info")
+ /* Fill in location struct fields */
+ loc_params.type = H5VL_OBJECT_BY_IDX;
+ loc_params.loc_data.loc_by_idx.name = group_name;
+ loc_params.loc_data.loc_by_idx.idx_type = idx_type;
+ loc_params.loc_data.loc_by_idx.order = order;
+ loc_params.loc_data.loc_by_idx.n = n;
+ loc_params.loc_data.loc_by_idx.lapl_id = lapl_id;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* Get the location object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "invalid location identifier")
+
/* Get the link information */
- if((ret_value = H5L_get_name_by_idx(&loc, group_name, idx_type, order, n, name, size)) < 0)
+ if(H5VL_link_get(vol_obj, &loc_params, H5VL_LINK_GET_NAME, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, name, size, &ret_value) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTGET, (-1), "unable to get link name")
done:
@@ -1096,7 +1278,8 @@ herr_t
H5Literate(hid_t group_id, H5_index_t idx_type, H5_iter_order_t order,
hsize_t *idx_p, H5L_iterate_t op, void *op_data)
{
- H5G_loc_t loc;
+ H5VL_object_t *vol_obj = NULL; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
H5I_type_t id_type; /* Type of ID */
herr_t ret_value; /* Return value */
@@ -1104,8 +1287,6 @@ H5Literate(hid_t group_id, H5_index_t idx_type, H5_iter_order_t order,
H5TRACE6("e", "iIiIo*hx*x", group_id, idx_type, order, idx_p, op, op_data);
/* Check arguments */
- if(H5G_loc(group_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
id_type = H5I_get_type(group_id);
if (!(H5I_GROUP == id_type || H5I_FILE == id_type))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid argument")
@@ -1116,8 +1297,16 @@ H5Literate(hid_t group_id, H5_index_t idx_type, H5_iter_order_t order,
if (!op)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no operator specified")
+ /* Get the location object */
+ if (NULL == (vol_obj = (H5VL_object_t *)H5I_object(group_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Set location struct fields */
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(group_id);
+
/* Iterate over the links */
- if((ret_value = H5L_iterate(&loc, ".", idx_type, order, idx_p, op, op_data)) < 0)
+ if((ret_value = H5VL_link_specific(vol_obj, &loc_params, H5VL_LINK_ITER, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, (unsigned)FALSE, (int)idx_type, (int)order, idx_p, op, op_data)) < 0)
HGOTO_ERROR(H5E_LINK, H5E_BADITER, FAIL, "link iteration failed")
done:
@@ -1152,7 +1341,8 @@ H5Literate_by_name(hid_t loc_id, const char *group_name,
H5_index_t idx_type, H5_iter_order_t order, hsize_t *idx_p,
H5L_iterate_t op, void *op_data, hid_t lapl_id)
{
- H5G_loc_t loc;
+ H5VL_object_t *vol_obj = NULL; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
herr_t ret_value; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -1160,8 +1350,6 @@ H5Literate_by_name(hid_t loc_id, const char *group_name,
op_data, lapl_id);
/* Check arguments */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!group_name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "group_name parameter cannot be NULL")
if(!*group_name)
@@ -1177,8 +1365,18 @@ H5Literate_by_name(hid_t loc_id, const char *group_name,
if(H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, FALSE) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access property list info")
+ /* Get the location object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Set location struct fields */
+ loc_params.type = H5VL_OBJECT_BY_NAME;
+ loc_params.obj_type = H5I_get_type(loc_id);
+ loc_params.loc_data.loc_by_name.name = group_name;
+ loc_params.loc_data.loc_by_name.lapl_id = lapl_id;
+
/* Iterate over the links */
- if((ret_value = H5L_iterate(&loc, group_name, idx_type, order, idx_p, op, op_data)) < 0)
+ if((ret_value = H5VL_link_specific(vol_obj, &loc_params, H5VL_LINK_ITER, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, FALSE, idx_type, order, idx_p, op, op_data)) < 0)
HGOTO_ERROR(H5E_LINK, H5E_BADITER, FAIL, "link iteration failed")
done:
@@ -1218,7 +1416,8 @@ herr_t
H5Lvisit(hid_t group_id, H5_index_t idx_type, H5_iter_order_t order,
H5L_iterate_t op, void *op_data)
{
- H5G_loc_t loc;
+ H5VL_object_t *vol_obj = NULL; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
H5I_type_t id_type; /* Type of ID */
herr_t ret_value; /* Return value */
@@ -1226,8 +1425,6 @@ H5Lvisit(hid_t group_id, H5_index_t idx_type, H5_iter_order_t order,
H5TRACE5("e", "iIiIox*x", group_id, idx_type, order, op, op_data);
/* Check args */
- if(H5G_loc(group_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
id_type = H5I_get_type(group_id);
if(!(H5I_GROUP == id_type || H5I_FILE == id_type))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid argument")
@@ -1238,8 +1435,16 @@ H5Lvisit(hid_t group_id, H5_index_t idx_type, H5_iter_order_t order,
if(!op)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no callback operator specified")
+ /* Set location struct fields */
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(group_id);
+
+ /* Get the location object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(group_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
/* Iterate over the links */
- if((ret_value = H5G_visit(&loc, ".", idx_type, order, op, op_data)) < 0)
+ if((ret_value = H5VL_link_specific(vol_obj, &loc_params, H5VL_LINK_ITER, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, TRUE, idx_type, order, NULL, op, op_data)) < 0)
HGOTO_ERROR(H5E_LINK, H5E_BADITER, FAIL, "link visitation failed")
done:
@@ -1279,7 +1484,8 @@ herr_t
H5Lvisit_by_name(hid_t loc_id, const char *group_name, H5_index_t idx_type,
H5_iter_order_t order, H5L_iterate_t op, void *op_data, hid_t lapl_id)
{
- H5G_loc_t loc;
+ H5VL_object_t *vol_obj = NULL; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
herr_t ret_value; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -1287,8 +1493,6 @@ H5Lvisit_by_name(hid_t loc_id, const char *group_name, H5_index_t idx_type,
lapl_id);
/* Check args */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!group_name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "group_name parameter cannot be NULL")
if(!*group_name)
@@ -1304,8 +1508,18 @@ H5Lvisit_by_name(hid_t loc_id, const char *group_name, H5_index_t idx_type,
if(H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, FALSE) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access property list info")
+ /* get the location object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Set location struct fields */
+ loc_params.type = H5VL_OBJECT_BY_NAME;
+ loc_params.obj_type = H5I_get_type(loc_id);
+ loc_params.loc_data.loc_by_name.name = group_name;
+ loc_params.loc_data.loc_by_name.lapl_id = lapl_id;
+
/* Visit the links */
- if((ret_value = H5G_visit(&loc, group_name, idx_type, order, op, op_data)) < 0)
+ if((ret_value = H5VL_link_specific(vol_obj, &loc_params, H5VL_LINK_ITER, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, TRUE, idx_type, order, NULL, op, op_data)) < 0)
HGOTO_ERROR(H5E_LINK, H5E_BADITER, FAIL, "link visitation failed")
done:
@@ -1434,7 +1648,7 @@ H5L_register(const H5L_class_t *cls)
} /* end if */
/* Copy link class info into table */
- HDmemcpy(H5L_table_g + i, cls, sizeof(H5L_class_t));
+ H5MM_memcpy(H5L_table_g + i, cls, sizeof(H5L_class_t));
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -1683,7 +1897,7 @@ H5L__link_cb(H5G_loc_t *grp_loc/*in*/, const char *name, const H5O_link_t H5_ATT
/* Set up location for user-defined callback */
if(NULL == (grp = H5G_open(&temp_loc)))
HGOTO_ERROR(H5E_LINK, H5E_CANTOPENOBJ, FAIL, "unable to open group")
- if((grp_id = H5I_register(H5I_GROUP, grp, TRUE)) < 0)
+ if((grp_id = H5VL_wrap_register(H5I_GROUP, grp, TRUE)) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTREGISTER, FAIL, "unable to register ID for group")
/* Make callback */
@@ -1975,7 +2189,7 @@ H5L__create_ud(const H5G_loc_t *link_loc, const char *link_name,
/* Fill in UD link-specific information in the link struct*/
if(ud_data_size > 0) {
lnk.u.ud.udata = H5MM_malloc((size_t)ud_data_size);
- HDmemcpy(lnk.u.ud.udata, ud_data, (size_t) ud_data_size);
+ H5MM_memcpy(lnk.u.ud.udata, ud_data, (size_t) ud_data_size);
} /* end if */
else
lnk.u.ud.udata = NULL;
@@ -2468,7 +2682,7 @@ H5L__move_dest_cb(H5G_loc_t *grp_loc/*in*/, const char *name,
/* Set up location for user-defined callback */
if(NULL == (grp = H5G_open(&temp_loc)))
HGOTO_ERROR(H5E_LINK, H5E_CANTOPENOBJ, FAIL, "unable to open group")
- if((grp_id = H5I_register(H5I_GROUP, grp, TRUE)) < 0)
+ if((grp_id = H5VL_wrap_register(H5I_GROUP, grp, TRUE)) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTREGISTER, FAIL, "unable to register group ID")
if(udata->copy) {
diff --git a/src/H5Lexternal.c b/src/H5Lexternal.c
index 1cab17d..3c4ffcc 100644
--- a/src/H5Lexternal.c
+++ b/src/H5Lexternal.c
@@ -33,6 +33,7 @@
#include "H5MMprivate.h" /* Memory management */
#include "H5Opublic.h" /* File objects */
#include "H5Pprivate.h" /* Property lists */
+#include "H5VLprivate.h" /* Virtual Object Layer */
/****************/
@@ -125,7 +126,9 @@ H5L__extern_traverse(const char H5_ATTR_UNUSED *link_name, hid_t cur_group,
unsigned intent; /* File access permissions */
H5L_elink_cb_t cb_info; /* Callback info struct */
hid_t fapl_id = -1; /* File access property list for external link's file */
- hid_t ext_obj = -1; /* ID for external link's object */
+ void *ext_obj = NULL; /* External link's object */
+ hid_t ext_obj_id = H5I_INVALID_HID; /* ID for external link's object */
+ H5I_type_t opened_type; /* ID type of external link's object */
char *parent_group_name = NULL;/* Temporary pointer to group name */
char local_group_name[H5L_EXT_TRAVERSE_BUF_SIZE]; /* Local buffer to hold group name */
H5P_genplist_t *fa_plist; /* File access property list pointer */
@@ -235,13 +238,18 @@ H5L__extern_traverse(const char H5_ATTR_UNUSED *link_name, hid_t cur_group,
HGOTO_ERROR(H5E_LINK, H5E_BADVALUE, H5I_INVALID_HID, "unable to create location for file")
/* Open the object referenced in the external file */
- if((ext_obj = H5O_open_name(&root_loc, obj_name, FALSE)) < 0)
+ if(NULL == (ext_obj = H5O_open_name(&root_loc, obj_name, &opened_type)))
HGOTO_ERROR(H5E_LINK, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open object")
+ /* Get an ID for the external link's object */
+ if((ext_obj_id = H5VL_wrap_register(opened_type, ext_obj, TRUE)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register external link object")
+
/* Set return value */
- ret_value = ext_obj;
+ ret_value = ext_obj_id;
done:
+/* XXX (VOL MERGE): Probably also want to consider closing ext_obj here on failures */
/* Release resources */
if(fapl_id > 0 && H5I_dec_ref(fapl_id) < 0)
HDONE_ERROR(H5E_ATOM, H5E_CANTRELEASE, H5I_INVALID_HID, "unable to close atom for file access property list")
@@ -251,7 +259,7 @@ done:
parent_group_name = (char *)H5MM_xfree(parent_group_name);
if(ret_value < 0) {
/* Close object if it's open and something failed */
- if(ext_obj >= 0 && H5I_dec_ref(ext_obj) < 0)
+ if(ext_obj_id >= 0 && H5I_dec_ref(ext_obj_id) < 0)
HDONE_ERROR(H5E_ATOM, H5E_CANTRELEASE, H5I_INVALID_HID, "unable to close atom for external object")
} /* end if */
@@ -298,7 +306,7 @@ H5L__extern_query(const char H5_ATTR_UNUSED * link_name, const void *_udata, siz
buf_size = udata_size;
/* Copy the udata verbatim up to buf_size */
- HDmemcpy(buf, udata, buf_size);
+ H5MM_memcpy(buf, udata, buf_size);
} /* end if */
/* Set return value */
@@ -333,13 +341,15 @@ herr_t
H5Lcreate_external(const char *file_name, const char *obj_name,
hid_t link_loc_id, const char *link_name, hid_t lcpl_id, hid_t lapl_id)
{
- H5G_loc_t link_loc; /* Group location to create link */
- char *norm_obj_name = NULL; /* Pointer to normalized current name */
+ H5VL_object_t *vol_obj = NULL; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
+ char *norm_obj_name = NULL; /* Pointer to normalized current name */
void *ext_link_buf = NULL; /* Buffer to contain external link */
size_t buf_size; /* Size of buffer to hold external link */
size_t file_name_len; /* Length of file name string */
size_t norm_obj_name_len; /* Length of normalized object name string */
uint8_t *p; /* Pointer into external link buffer */
+ H5L_type_t link_type = H5L_TYPE_EXTERNAL;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -351,11 +361,13 @@ H5Lcreate_external(const char *file_name, const char *obj_name,
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no file name specified")
if(!obj_name || !*obj_name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no object name specified")
- if(H5G_loc(link_loc_id, &link_loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!link_name || !*link_name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no link name specified")
+ /* Check the group access property list */
+ if(H5P_DEFAULT == lcpl_id)
+ lcpl_id = H5P_LINK_CREATE_DEFAULT;
+
/* Get normalized copy of the link target */
if(NULL == (norm_obj_name = H5G_normalize(obj_name)))
HGOTO_ERROR(H5E_LINK, H5E_BADVALUE, FAIL, "can't normalize object name")
@@ -378,8 +390,17 @@ H5Lcreate_external(const char *file_name, const char *obj_name,
if(H5CX_set_apl(&lapl_id, H5P_CLS_LACC, link_loc_id, TRUE) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access property list info")
+ loc_params.type = H5VL_OBJECT_BY_NAME;
+ loc_params.loc_data.loc_by_name.name = link_name;
+ loc_params.loc_data.loc_by_name.lapl_id = lapl_id;
+ loc_params.obj_type = H5I_get_type(link_loc_id);
+
+ /* get the location object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(link_loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier")
+
/* Create an external link */
- if(H5L__create_ud(&link_loc, link_name, ext_link_buf, buf_size, H5L_TYPE_EXTERNAL, lcpl_id) < 0)
+ if(H5VL_link_create(H5VL_LINK_CREATE_UD, vol_obj, &loc_params, lcpl_id, lapl_id, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, (int)link_type, ext_link_buf, buf_size) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "unable to create external link")
done:
diff --git a/src/H5M.c b/src/H5M.c
new file mode 100644
index 0000000..adb4df0
--- /dev/null
+++ b/src/H5M.c
@@ -0,0 +1,1032 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#include "H5Mmodule.h" /* This source code file is part of the H5M module */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5CXprivate.h" /* API Contexts */
+#include "H5Mpkg.h" /* Maps */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Iprivate.h" /* IDs */
+#include "H5VLprivate.h" /* Virtual Object Layer */
+
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+static herr_t H5M__close_cb(H5VL_object_t *map_vol_obj);
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+/* Package initialization variable */
+hbool_t H5_PKG_INIT_VAR = FALSE;
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* Map ID class */
+static const H5I_class_t H5I_MAP_CLS[1] = {{
+ H5I_MAP, /* ID class value */
+ 0, /* Class flags */
+ 0, /* # of reserved IDs for class */
+ (H5I_free_t)H5M__close_cb /* Callback routine for closing objects of this class */
+}};
+
+/* Flag indicating "top" of interface has been initialized */
+static hbool_t H5M_top_package_initialize_s = FALSE;
+
+
+
+/*-------------------------------------------------------------------------
+NAME
+ H5M__init_package -- Initialize interface-specific information
+USAGE
+ herr_t H5M__init_package()
+
+RETURNS
+ Non-negative on success/Negative on failure
+DESCRIPTION
+ Initializes any interface-specific data or routines.
+---------------------------------------------------------------------------
+*/
+herr_t
+H5M__init_package(void)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Initialize the atom group for the map IDs */
+ if(H5I_register_type(H5I_MAP_CLS) < 0)
+ HGOTO_ERROR(H5E_MAP, H5E_CANTINIT, FAIL, "unable to initialize interface")
+
+ /* Mark "top" of interface as initialized, too */
+ H5M_top_package_initialize_s = TRUE;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5M__init_package() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5M_top_term_package
+ *
+ * Purpose: Close the "top" of the interface, releasing IDs, etc.
+ *
+ * Return: Success: Positive if anything was done that might
+ * affect other interfaces; zero otherwise.
+ * Failure: Negative.
+ *-------------------------------------------------------------------------
+ */
+int
+H5M_top_term_package(void)
+{
+ int n = 0;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ if(H5M_top_package_initialize_s) {
+ if(H5I_nmembers(H5I_MAP) > 0) {
+ (void)H5I_clear_type(H5I_MAP, FALSE, FALSE);
+ n++; /*H5I*/
+ } /* end if */
+
+ /* Mark closed */
+ if(0 == n)
+ H5M_top_package_initialize_s = FALSE;
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(n)
+} /* end H5M_top_term_package() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5M_term_package
+ *
+ * Purpose: Terminate this interface.
+ *
+ * Note: Finishes shutting down the interface, after
+ * H5M_top_term_package() is called
+ *
+ * Return: Success: Positive if anything was done that might
+ * affect other interfaces; zero otherwise.
+ * Failure: Negative.
+ *-------------------------------------------------------------------------
+ */
+int
+H5M_term_package(void)
+{
+ int n = 0;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ if(H5_PKG_INIT_VAR) {
+ /* Sanity checks */
+ HDassert(0 == H5I_nmembers(H5I_MAP));
+ HDassert(FALSE == H5M_top_package_initialize_s);
+
+ /* Destroy the dataset object id group */
+ n += (H5I_dec_type_ref(H5I_MAP) > 0);
+
+ /* Mark closed */
+ if(0 == n)
+ H5_PKG_INIT_VAR = FALSE;
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(n)
+} /* end H5M_term_package() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5M__close_cb
+ *
+ * Purpose: Called when the ref count reaches zero on the map's ID
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5M__close_cb(H5VL_object_t *map_vol_obj)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity check */
+ HDassert(map_vol_obj);
+
+ /* Close the map */
+ if(H5VL_optional(map_vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_MAP_CLOSE) < 0)
+ HGOTO_ERROR(H5E_MAP, H5E_CLOSEERROR, FAIL, "unable to close map");
+
+ /* Free the VOL object */
+ if(H5VL_free_object(map_vol_obj) < 0)
+ HGOTO_ERROR(H5E_MAP, H5E_CANTDEC, FAIL, "unable to free VOL object");
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5M__close_cb() */
+
+#ifdef H5_HAVE_MAP_API
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Mcreate
+ *
+ * Purpose: Creates a new map object for storing key-value pairs. The
+ * in-file datatype for keys is defined by KEY_TYPE_ID and
+ * the in-file datatype for values is defined by VAL_TYPE_ID.
+ * LOC_ID specifies the location to create the map object and
+ * NAME specifies the name of the link to the object
+ * (relative to LOC_ID). Other options can be specified
+ * through the property lists LCPL_ID, MCPL_ID, and MAPL_ID.
+ *
+ * Return: Success: The object ID of the new map.
+ *
+ * Failure: H5I_INVALID_HID
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5Mcreate(hid_t loc_id, const char *name, hid_t key_type_id, hid_t val_type_id,
+ hid_t lcpl_id, hid_t mcpl_id, hid_t mapl_id)
+{
+ void *map = NULL; /* New map's info */
+ H5VL_object_t *vol_obj = NULL; /* object token of loc_id */
+ H5VL_loc_params_t loc_params;
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
+
+ FUNC_ENTER_API(H5I_INVALID_HID)
+ H5TRACE7("i", "i*siiiii", loc_id, name, key_type_id, val_type_id, lcpl_id,
+ mcpl_id, mapl_id);
+
+ /* Check arguments */
+ if(!name)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "name parameter cannot be NULL")
+ if(!*name)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "name parameter cannot be an empty string")
+
+ /* Get link creation property list */
+ if(H5P_DEFAULT == lcpl_id)
+ lcpl_id = H5P_LINK_CREATE_DEFAULT;
+ else
+ if(TRUE != H5P_isa_class(lcpl_id, H5P_LINK_CREATE))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "lcpl_id is not a link creation property list")
+
+ /* Get map creation property list */
+ if(H5P_DEFAULT == mcpl_id)
+ mcpl_id = H5P_MAP_CREATE_DEFAULT;
+ else
+ if(TRUE != H5P_isa_class(mcpl_id, H5P_MAP_CREATE))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "mcpl_id is not a map create property list ID")
+
+ /* Verify access property list and set up collective metadata if appropriate */
+ if(H5CX_set_apl(&mapl_id, H5P_CLS_MACC, loc_id, TRUE) < 0)
+ HGOTO_ERROR(H5E_MAP, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info")
+
+ /* Get the location object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier")
+
+ /* Set location parameters */
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* Create the map */
+ if(H5VL_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_MAP_CREATE, &loc_params, name, lcpl_id,
+ key_type_id, val_type_id, mcpl_id, mapl_id, &map) < 0)
+ HGOTO_ERROR(H5E_MAP, H5E_CANTINIT, H5I_INVALID_HID, "unable to create map")
+
+ /* Get an atom for the map */
+ if((ret_value = H5VL_register(H5I_MAP, map, vol_obj->connector, TRUE)) < 0)
+ HGOTO_ERROR(H5E_MAP, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to atomize map handle")
+
+done:
+ /* Cleanup on failure */
+ if(H5I_INVALID_HID == ret_value)
+ if(map && H5VL_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_MAP_CLOSE) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, H5I_INVALID_HID, "unable to release map")
+
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Mcreate() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Mcreate_anon
+ *
+ * Purpose: Creates a new map object for storing key-value pairs. The
+ * in-file datatype for keys is defined by KEY_TYPE_ID and
+ * the in-file datatype for values is defined by VAL_TYPE_ID.
+ * LOC_ID specifies the file to create the map object, but no
+ * link to the object is created. Other options can be
+ * specified through the property lists LCPL_ID, MCPL_ID, and
+ * MAPL_ID.
+ *
+ * The resulting ID should be linked into the file with
+ * H5Olink or it will be deleted when closed.
+ *
+ * Return: Success: The object ID of the new map. The map should
+ * be linked into the group hierarchy before being closed or
+ * it will be deleted. The dataset should be
+ * closed when the caller is no longer interested
+ * in it.
+ *
+ * Failure: H5I_INVALID_HID
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5Mcreate_anon(hid_t loc_id, hid_t key_type_id, hid_t val_type_id,
+ hid_t mcpl_id, hid_t mapl_id)
+{
+ void *map = NULL; /* map token from VOL connector */
+ H5VL_object_t *vol_obj = NULL; /* object token of loc_id */
+ H5VL_loc_params_t loc_params;
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
+
+ FUNC_ENTER_API(H5I_INVALID_HID)
+ H5TRACE5("i", "iiiii", loc_id, key_type_id, val_type_id, mcpl_id, mapl_id);
+
+ /* Check arguments */
+ if(H5P_DEFAULT == mcpl_id)
+ mcpl_id = H5P_MAP_CREATE_DEFAULT;
+ else
+ if(TRUE != H5P_isa_class(mcpl_id, H5P_MAP_CREATE))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not map create property list ID")
+
+ /* Verify access property list and set up collective metadata if appropriate */
+ if(H5CX_set_apl(&mapl_id, H5P_CLS_MACC, loc_id, TRUE) < 0)
+ HGOTO_ERROR(H5E_MAP, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info")
+
+ /* get the location object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier")
+
+ /* Set location parameters */
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* Create the map */
+ if(H5VL_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_MAP_CREATE, &loc_params, NULL, H5P_LINK_CREATE_DEFAULT,
+ key_type_id, val_type_id, mcpl_id, mapl_id, &map) < 0)
+ HGOTO_ERROR(H5E_MAP, H5E_CANTINIT, H5I_INVALID_HID, "unable to create map")
+
+ /* Get an atom for the map */
+ if((ret_value = H5VL_register(H5I_MAP, map, vol_obj->connector, TRUE)) < 0)
+ HGOTO_ERROR(H5E_MAP, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register map")
+
+done:
+ /* Cleanup on failure */
+ if(H5I_INVALID_HID == ret_value)
+ if(map && H5VL_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_MAP_CLOSE) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, H5I_INVALID_HID, "unable to release map")
+
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Mcreate_anon() */
+
+
+/*------------------------------------------------------------------------
+ * Function: H5Mopen
+ *
+ * Purpose: Finds a map named NAME at LOC_ID, opens it, and returns
+ * its ID. The map should be close when the caller is no
+ * longer interested in it.
+ *
+ * Takes a map access property list
+ *
+ * Return: Success: Object ID of the map
+ *
+ * Failure: H5I_INVALID_HID
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5Mopen(hid_t loc_id, const char *name, hid_t mapl_id)
+{
+ void *map = NULL; /* map token from VOL connector */
+ H5VL_object_t *vol_obj = NULL; /* object token of loc_id */
+ H5VL_loc_params_t loc_params;
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
+
+ FUNC_ENTER_API(H5I_INVALID_HID)
+ H5TRACE3("i", "i*si", loc_id, name, mapl_id);
+
+ /* Check args */
+ if(!name)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "name parameter cannot be NULL")
+ if(!*name)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "name parameter cannot be an empty string")
+
+ /* Verify access property list and set up collective metadata if appropriate */
+ if(H5CX_set_apl(&mapl_id, H5P_CLS_MACC, loc_id, FALSE) < 0)
+ HGOTO_ERROR(H5E_MAP, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info")
+
+ /* get the location object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier")
+
+ /* Set the location parameters */
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* Open the map */
+ if(H5VL_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_MAP_OPEN, &loc_params, name, mapl_id, &map) < 0)
+ HGOTO_ERROR(H5E_MAP, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open map")
+
+ /* Register an atom for the map */
+ if((ret_value = H5VL_register(H5I_MAP, map, vol_obj->connector, TRUE)) < 0)
+ HGOTO_ERROR(H5E_MAP, H5E_CANTREGISTER, H5I_INVALID_HID, "can't register map atom")
+
+done:
+ /* Cleanup on failure */
+ if(H5I_INVALID_HID == ret_value)
+ if(map && H5VL_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_MAP_CLOSE) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, H5I_INVALID_HID, "unable to release map")
+
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Mopen() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Mclose
+ *
+ * Purpose: Closes access to a map and releases resources used by it.
+ * It is illegal to subsequently use that same map ID in
+ * calls to other map functions.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Mclose(hid_t map_id)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE1("e", "i", map_id);
+
+ /* Check args */
+ if(H5I_MAP != H5I_get_type(map_id))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a map ID")
+
+ /* Decrement the counter on the map. It will be freed if the count
+ * reaches zero.
+ */
+ if(H5I_dec_app_ref_always_close(map_id) < 0)
+ HGOTO_ERROR(H5E_MAP, H5E_CANTDEC, FAIL, "can't decrement count on map ID")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Mclose() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Mget_key_type
+ *
+ * Purpose: Returns a copy of the key datatype for a map.
+ *
+ * Return: Success: ID for a copy of the datatype. The data
+ * type should be released by calling
+ * H5Tclose().
+ *
+ * Failure: H5I_INVALID_HID
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5Mget_key_type(hid_t map_id)
+{
+ H5VL_object_t *vol_obj; /* Map structure */
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
+
+ FUNC_ENTER_API(H5I_INVALID_HID)
+ H5TRACE1("i", "i", map_id);
+
+ /* Check args */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(map_id, H5I_MAP)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid map identifier")
+
+ /* get the datatype */
+ if(H5VL_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_MAP_GET, H5VL_MAP_GET_KEY_TYPE, &ret_value) < 0)
+ HGOTO_ERROR(H5E_MAP, H5E_CANTGET, H5I_INVALID_HID, "unable to get datatype")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Mget_key_type() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Mget_val_type
+ *
+ * Purpose: Returns a copy of the value datatype for a map.
+ *
+ * Return: Success: ID for a copy of the datatype. The data
+ * type should be released by calling
+ * H5Tclose().
+ *
+ * Failure: H5I_INVALID_HID
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5Mget_val_type(hid_t map_id)
+{
+ H5VL_object_t *vol_obj; /* Map structure */
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
+
+ FUNC_ENTER_API(H5I_INVALID_HID)
+ H5TRACE1("i", "i", map_id);
+
+ /* Check args */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(map_id, H5I_MAP)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid map identifier")
+
+ /* get the datatype */
+ if(H5VL_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_MAP_GET, H5VL_MAP_GET_VAL_TYPE, &ret_value) < 0)
+ HGOTO_ERROR(H5E_MAP, H5E_CANTGET, H5I_INVALID_HID, "unable to get datatype")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Mget_val_type() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Mget_create_plist
+ *
+ * Purpose: Returns a copy of the map creation property list.
+ *
+ * Return: Success: ID for a copy of the map creation
+ * property list. The template should be
+ * released by calling H5P_close().
+ *
+ * Failure: H5I_INVALID_HID
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5Mget_create_plist(hid_t map_id)
+{
+ H5VL_object_t *vol_obj; /* Map structure */
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
+
+ FUNC_ENTER_API(H5I_INVALID_HID)
+ H5TRACE1("i", "i", map_id);
+
+ /* Check args */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(map_id, H5I_MAP)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid map identifier")
+
+ /* Get the map creation property list */
+ if(H5VL_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_MAP_GET, H5VL_MAP_GET_MCPL, &ret_value) < 0)
+ HGOTO_ERROR(H5E_MAP, H5E_CANTGET, H5I_INVALID_HID, "unable to get map creation properties")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Mget_create_plist() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Mget_access_plist
+ *
+ * Purpose: Returns a copy of the map access property list.
+ *
+ * Description: H5Mget_access_plist returns the map access property
+ * list identifier of the specified map.
+ *
+ * Return: Success: ID for a copy of the map access
+ * property list. The template should be
+ * released by calling H5Pclose().
+ *
+ * Failure: H5I_INVALID_HID
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5Mget_access_plist(hid_t map_id)
+{
+ H5VL_object_t *vol_obj; /* Map structure */
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
+
+ FUNC_ENTER_API(H5I_INVALID_HID)
+ H5TRACE1("i", "i", map_id);
+
+ /* Check args */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(map_id, H5I_MAP)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid map identifier")
+
+ /* Get the map access property list */
+ if(H5VL_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_MAP_GET, H5VL_MAP_GET_MAPL, &ret_value) < 0)
+ HGOTO_ERROR(H5E_MAP, H5E_CANTGET, H5I_INVALID_HID, "unable to get map access properties")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Mget_access_plist() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Mget_count
+ *
+ * Purpose: Returns the number of key-value pairs stored in the map.
+ *
+ * Description: H5Mget_count returns the number of key-value pairs stored
+ * in the specified map.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Mget_count(hid_t map_id, hsize_t *count, hid_t dxpl_id)
+{
+ H5VL_object_t *vol_obj; /* Map structure */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(H5I_INVALID_HID)
+ H5TRACE3("e", "i*hi", map_id, count, dxpl_id);
+
+ /* Check args */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(map_id, H5I_MAP)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid map identifier")
+
+ /* Get the default dataset transfer property list if the user didn't provide one */
+ if (H5P_DEFAULT == dxpl_id)
+ dxpl_id = H5P_DATASET_XFER_DEFAULT;
+ else
+ if (TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms")
+
+ /* Set DXPL for operation */
+ H5CX_set_dxpl(dxpl_id);
+
+ /* Get the number of key-value pairs stored in the map */
+ if(H5VL_optional(vol_obj, dxpl_id, H5_REQUEST_NULL, H5VL_MAP_GET, H5VL_MAP_GET_COUNT, count) < 0)
+ HGOTO_ERROR(H5E_MAP, H5E_CANTGET, H5I_INVALID_HID, "unable to get map access properties")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Mget_count() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Mput
+ *
+ * Purpose: H5Mput adds a key-value pair to the Map specified by
+ * MAP_ID, or updates the value for the specified key if one
+ * was set previously. KEY_MEM_TYPE_ID and VAL_MEM_TYPE_ID
+ * specify the datatypes for the provided KEY and VALUE
+ * buffers, and if different from those used to create the
+ * map object, the key and value will be internally converted
+ * to the datatypes for the map object. Any further options
+ * can be specified through the property list DXPL_ID.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Mput(hid_t map_id, hid_t key_mem_type_id, const void *key,
+ hid_t val_mem_type_id, const void *value, hid_t dxpl_id)
+{
+ H5VL_object_t *vol_obj = NULL;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE6("e", "ii*xi*xi", map_id, key_mem_type_id, key, val_mem_type_id, value,
+ dxpl_id);
+
+ /* Check arguments */
+ if (key_mem_type_id < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid key memory datatype ID")
+ if (val_mem_type_id < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid value memory datatype ID")
+
+ /* Get map pointer */
+ if (NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(map_id, H5I_MAP)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "map_id is not a map ID")
+
+ /* Get the default dataset transfer property list if the user didn't provide one */
+ if (H5P_DEFAULT == dxpl_id)
+ dxpl_id = H5P_DATASET_XFER_DEFAULT;
+ else
+ if (TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms")
+
+ /* Set DXPL for operation */
+ H5CX_set_dxpl(dxpl_id);
+
+ /* Set the key/value pair */
+ if(H5VL_optional(vol_obj, dxpl_id, H5_REQUEST_NULL, H5VL_MAP_PUT, key_mem_type_id, key, val_mem_type_id, value) < 0)
+ HGOTO_ERROR(H5E_MAP, H5E_CANTSET, FAIL, "unable to put key/value pair")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Mput() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Mget
+ *
+ * Purpose: H5Mget retrieves, from the Map specified by MAP_ID, the
+ * value associated with the provided key. KEY_MEM_TYPE_ID
+ * and VAL_MEM_TYPE_ID specify the datatypes for the provided
+ * KEY and VALUE buffers. If KEY_MEM_TYPE_ID is different
+ * from that used to create the map object, the key will be
+ * internally converted to the datatype for the map object
+ * for the query, and if VAL_MEM_TYPE_ID is different from
+ * that used to create the map object, the returned value
+ * will be converted to VAL_MEM_TYPE_ID before the function
+ * returns. Any further options can be specified through the
+ * property list DXPL_ID.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Mget(hid_t map_id, hid_t key_mem_type_id, const void *key,
+ hid_t val_mem_type_id, void *value, hid_t dxpl_id)
+{
+ H5VL_object_t *vol_obj = NULL;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE6("e", "ii*xi*xi", map_id, key_mem_type_id, key, val_mem_type_id, value,
+ dxpl_id);
+
+ /* Check arguments */
+ if (key_mem_type_id < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid key memory datatype ID")
+ if (val_mem_type_id < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid value memory datatype ID")
+
+ /* Get map pointer */
+ if (NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(map_id, H5I_MAP)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "map_id is not a map ID")
+
+ /* Get the default dataset transfer property list if the user didn't provide one */
+ if (H5P_DEFAULT == dxpl_id)
+ dxpl_id = H5P_DATASET_XFER_DEFAULT;
+ else
+ if (TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms")
+
+ /* Set DXPL for operation */
+ H5CX_set_dxpl(dxpl_id);
+
+ /* Get the value for the key */
+ if(H5VL_optional(vol_obj, dxpl_id, H5_REQUEST_NULL, H5VL_MAP_GET_VAL, key_mem_type_id, key, val_mem_type_id, value) < 0)
+ HGOTO_ERROR(H5E_MAP, H5E_CANTGET, FAIL, "unable to get value from map")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Mget() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Mexists
+ *
+ * Purpose: H5Mexists checks if the provided key is stored in the map
+ * specified by MAP_ID. If KEY_MEM_TYPE_ID is different from
+ * that used to create the map object the key will be
+ * internally converted to the datatype for the map object
+ * for the query.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Mexists(hid_t map_id, hid_t key_mem_type_id, const void *key, hbool_t *exists,
+ hid_t dxpl_id)
+{
+ H5VL_object_t *vol_obj = NULL;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE5("e", "ii*x*bi", map_id, key_mem_type_id, key, exists, dxpl_id);
+
+ /* Check arguments */
+ if (key_mem_type_id < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid key memory datatype ID")
+
+ /* Get map pointer */
+ if (NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(map_id, H5I_MAP)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "map_id is not a map ID")
+
+ /* Get the default dataset transfer property list if the user didn't provide one */
+ if (H5P_DEFAULT == dxpl_id)
+ dxpl_id = H5P_DATASET_XFER_DEFAULT;
+ else
+ if (TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms")
+
+ /* Set DXPL for operation */
+ H5CX_set_dxpl(dxpl_id);
+
+ /* Check if key exists */
+ if((ret_value = H5VL_optional(vol_obj, dxpl_id, H5_REQUEST_NULL, H5VL_MAP_EXISTS, key_mem_type_id, key, exists)) < 0)
+ HGOTO_ERROR(H5E_MAP, H5E_CANTGET, ret_value, "unable to check if key exists")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Mexists() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Miterate
+ *
+ * Purpose: H5Miterate iterates over all key-value pairs stored in the
+ * map specified by MAP_ID, making the callback specified by
+ * OP for each. The IDX parameter is an in/out parameter that
+ * may be used to restart a previously interrupted iteration.
+ * At the start of iteration IDX should be set to 0, and to
+ * restart iteration at the same location on a subsequent
+ * call to H5Miterate, IDX should be the same value as
+ * returned by the previous call.
+ *
+ * H5M_iterate_t is defined as:
+ * herr_t (*H5M_iterate_t)(hid_t map_id, const void *key,
+ * void *ctx)
+ *
+ * The KEY parameter is the buffer for the key for this
+ * iteration, converted to the datatype specified by
+ * KEY_MEM_TYPE_ID. The OP_DATA parameter is a simple pass
+ * through of the value passed to H5Miterate, which can be
+ * used to store application-defined data for iteration. A
+ * negative return value from this function will cause
+ * H5Miterate to issue an error, while a positive return
+ * value will cause H5Miterate to stop iterating and return
+ * this value without issuing an error. A return value of
+ * zero allows iteration to continue.
+ *
+ * Return: Last value returned by op
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Miterate(hid_t map_id, hsize_t *idx, hid_t key_mem_type_id, H5M_iterate_t op,
+ void *op_data, hid_t dxpl_id)
+{
+ H5VL_object_t *vol_obj = NULL;
+ H5VL_loc_params_t loc_params;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE6("e", "i*hix*xi", map_id, idx, key_mem_type_id, op, op_data, dxpl_id);
+
+ /* Check arguments */
+ if (key_mem_type_id < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid key memory datatype ID")
+ if (!op)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no operator specified")
+
+ /* Get map pointer */
+ if (NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(map_id, H5I_MAP)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "map_id is not a map ID")
+
+ /* Get the default dataset transfer property list if the user didn't provide one */
+ if (H5P_DEFAULT == dxpl_id)
+ dxpl_id = H5P_DATASET_XFER_DEFAULT;
+ else
+ if (TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms")
+
+ /* Set DXPL for operation */
+ H5CX_set_dxpl(dxpl_id);
+
+ /* Set location struct fields */
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(map_id);
+
+ /* Iterate over keys */
+ if((ret_value = H5VL_optional(vol_obj, dxpl_id, H5_REQUEST_NULL, H5VL_MAP_SPECIFIC, &loc_params, H5VL_MAP_ITER, idx, key_mem_type_id, op, op_data)) < 0)
+ HGOTO_ERROR(H5E_MAP, H5E_BADITER, ret_value, "unable to ierate over keys")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Miterate() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Miterate_by_name
+ *
+ * Purpose: H5Miterate_by_name iterates over all key-value pairs
+ * stored in the map specified by MAP_ID, making the callback
+ * specified by OP for each. The IDX parameter is an in/out
+ * parameter that may be used to restart a previously
+ * interrupted iteration. At the start of iteration IDX
+ * should be set to 0, and to restart iteration at the same
+ * location on a subsequent call to H5Miterate, IDX should be
+ * the same value as returned by the previous call.
+ *
+ * H5M_iterate_t is defined as:
+ * herr_t (*H5M_iterate_t)(hid_t map_id, const void *key,
+ * void *ctx)
+ *
+ * The KEY parameter is the buffer for the key for this
+ * iteration, converted to the datatype specified by
+ * KEY_MEM_TYPE_ID. The OP_DATA parameter is a simple pass
+ * through of the value passed to H5Miterate, which can be
+ * used to store application-defined data for iteration. A
+ * negative return value from this function will cause
+ * H5Miterate to issue an error, while a positive return
+ * value will cause H5Miterate to stop iterating and return
+ * this value without issuing an error. A return value of
+ * zero allows iteration to continue.
+ *
+ * Return: Last value returned by op
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Miterate_by_name(hid_t loc_id, const char *map_name, hsize_t *idx,
+ hid_t key_mem_type_id, H5M_iterate_t op, void *op_data, hid_t dxpl_id,
+ hid_t lapl_id)
+{
+ H5VL_object_t *vol_obj = NULL;
+ H5VL_loc_params_t loc_params;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE8("e", "i*s*hix*xii", loc_id, map_name, idx, key_mem_type_id, op,
+ op_data, dxpl_id, lapl_id);
+
+ /* Check arguments */
+ if(!map_name)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "map_name parameter cannot be NULL")
+ if(!*map_name)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "map_name parameter cannot be an empty string")
+ if (key_mem_type_id < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid key memory datatype ID")
+ if (!op)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no operator specified")
+
+ /* Get the location object */
+ if (NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Get the default dataset transfer property list if the user didn't provide one */
+ if (H5P_DEFAULT == dxpl_id)
+ dxpl_id = H5P_DATASET_XFER_DEFAULT;
+ else
+ if (TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms")
+
+ /* Set DXPL for operation */
+ H5CX_set_dxpl(dxpl_id);
+
+ /* Set location struct fields */
+ loc_params.type = H5VL_OBJECT_BY_NAME;
+ loc_params.obj_type = H5I_get_type(loc_id);
+ loc_params.loc_data.loc_by_name.name = map_name;
+ loc_params.loc_data.loc_by_name.lapl_id = lapl_id;
+
+ /* Iterate over keys */
+ if((ret_value = H5VL_optional(vol_obj, dxpl_id, H5_REQUEST_NULL, H5VL_MAP_SPECIFIC, &loc_params, H5VL_MAP_ITER, idx, key_mem_type_id, op, op_data)) < 0)
+ HGOTO_ERROR(H5E_MAP, H5E_BADITER, ret_value, "unable to ierate over keys")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Miterate_by_name() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Mdelete
+ *
+ * Purpose: H5Mdelete deletes a key-value pair from the Map
+ * specified by MAP_ID. KEY_MEM_TYPE_ID specifies the
+ * datatype for the provided key buffers, and if different
+ * from that used to create the Map object, the key will be
+ * internally converted to the datatype for the map object.
+ * Any further options can be specified through the property
+ * list DXPL_ID.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Mdelete(hid_t map_id, hid_t key_mem_type_id, const void *key,
+ hid_t dxpl_id)
+{
+ H5VL_object_t *vol_obj = NULL;
+ H5VL_loc_params_t loc_params;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE4("e", "ii*xi", map_id, key_mem_type_id, key, dxpl_id);
+
+ /* Check arguments */
+ if (key_mem_type_id < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid key memory datatype ID")
+
+ /* Get map pointer */
+ if (NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(map_id, H5I_MAP)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "map_id is not a map ID")
+
+ /* Get the default dataset transfer property list if the user didn't provide one */
+ if (H5P_DEFAULT == dxpl_id)
+ dxpl_id = H5P_DATASET_XFER_DEFAULT;
+ else
+ if (TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms")
+
+ /* Set DXPL for operation */
+ H5CX_set_dxpl(dxpl_id);
+
+ /* Set location struct fields */
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(map_id);
+
+ /* Delete the key/value pair */
+ if(H5VL_optional(vol_obj, dxpl_id, H5_REQUEST_NULL, H5VL_MAP_SPECIFIC, &loc_params, H5VL_MAP_DELETE, key_mem_type_id, key) < 0)
+ HGOTO_ERROR(H5E_MAP, H5E_CANTSET, FAIL, "unable to delete key/value pair")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Mdelete() */
+
+#endif /* H5_HAVE_MAP_API */
+
diff --git a/src/H5MF.c b/src/H5MF.c
index 9f415db..859750a 100644
--- a/src/H5MF.c
+++ b/src/H5MF.c
@@ -22,6 +22,8 @@
*-------------------------------------------------------------------------
*/
+#include "bsdqueue.h"
+
/****************/
/* Module Setup */
/****************/
@@ -50,6 +52,16 @@
#define H5MF_FSPACE_SHRINK 80 /* Percent of "normal" size to shrink serialized free space size */
#define H5MF_FSPACE_EXPAND 120 /* Percent of "normal" size to expand serialized free space size */
+#define H5MF_CHECK_FSM(FSM, CF) \
+ HDassert(*CF == FALSE); \
+ if(!H5F_addr_defined(FSM->addr) || !H5F_addr_defined(FSM->sect_addr)) \
+ *CF = TRUE;
+
+/* For non-paged aggregation: map allocation request type to tracked free-space type */
+/* F_SH -- pointer to H5F_shared_t; T -- H5FD_mem_t */
+#define H5MF_ALLOC_TO_FS_AGGR_TYPE(F_SH, T) \
+ ((H5FD_MEM_DEFAULT == (F_SH)->fs_type_map[T]) ? (T) : (F_SH)->fs_type_map[T])
+
/******************/
/* Local Typedefs */
/******************/
@@ -68,7 +80,6 @@ typedef struct {
size_t sect_idx; /* the current count of sections */
} H5MF_sect_iter_ud_t;
-
/********************/
/* Package Typedefs */
/********************/
@@ -78,6 +89,7 @@ typedef struct {
/* Local Prototypes */
/********************/
+static herr_t H5MF_xfree_impl(H5F_t *, H5FD_mem_t, haddr_t, hsize_t);
/* Allocator routines */
static haddr_t H5MF__alloc_pagefs(H5F_t *f, H5FD_mem_t alloc_type, hsize_t size);
@@ -88,8 +100,10 @@ static herr_t H5MF__close_shrink_eoa(H5F_t *f);
/* General routines */
static herr_t H5MF__get_free_sects(H5F_t *f, H5FS_t *fspace, H5MF_sect_iter_ud_t *sect_udata, size_t *nums);
-static hbool_t H5MF__fsm_type_is_self_referential(H5F_t *f, H5F_mem_page_t fsm_type);
-static hbool_t H5MF__fsm_is_self_referential(H5F_t *f, H5FS_t *fspace);
+static hbool_t H5MF__fsm_type_is_self_referential(H5F_shared_t *f_sh, H5F_mem_page_t fsm_type);
+static hbool_t H5MF__fsm_is_self_referential(H5F_shared_t *f_sh, H5FS_t *fspace);
+static herr_t H5MF__continue_alloc_fsm(H5F_shared_t *f_sh, H5FS_t *sm_hdr_fspace, H5FS_t *sm_sinfo_fspace,
+ H5FS_t *lg_hdr_fspace, H5FS_t *lg_sinfo_fspace, hbool_t *continue_alloc_fsm);
/* Free-space type manager routines */
static herr_t H5MF__create_fstype(H5F_t *f, H5F_mem_page_t type);
@@ -118,6 +132,48 @@ hbool_t H5_PKG_INIT_VAR = FALSE;
/* Local Variables */
/*******************/
+static herr_t
+defer_free(H5F_shared_t *shared, H5FD_mem_t alloc_type, haddr_t addr,
+ hsize_t size)
+{
+ deferred_free_t *df;
+
+ if ((df = malloc(sizeof(*df))) == NULL)
+ return FAIL;
+
+ df->alloc_type = alloc_type;
+ df->addr = addr;
+ df->size = size;
+ df->free_after_tick = shared->tick_num + shared->vfd_swmr_config.max_lag;
+
+ SIMPLEQ_INSERT_TAIL(&shared->deferred_frees, df, link);
+
+ return SUCCEED;
+}
+
+static herr_t
+process_deferred_frees(H5F_t *f)
+{
+ deferred_free_t *df;
+ herr_t err = SUCCEED;
+ H5F_shared_t *shared = f->shared;
+ const uint64_t tick_num = shared->tick_num;
+
+ while ((df = SIMPLEQ_FIRST(&shared->deferred_frees)) != NULL) {
+ if (tick_num <= df->free_after_tick)
+ break;
+ /* Have to remove the item before processing it because we
+ * could re-enter this routine through H5MF_xfree_impl. If
+ * the item was still on the queue, it would be processed
+ * a second time, and that's not good.
+ */
+ SIMPLEQ_REMOVE_HEAD(&shared->deferred_frees, link);
+ if (H5MF_xfree_impl(f, df->alloc_type, df->addr, df->size) < 0)
+ err = FAIL;
+ free(df);
+ }
+ return err;
+}
/*-------------------------------------------------------------------------
@@ -134,7 +190,7 @@ hbool_t H5_PKG_INIT_VAR = FALSE;
*-------------------------------------------------------------------------
*/
herr_t
-H5MF_init_merge_flags(H5F_t *f)
+H5MF_init_merge_flags(H5F_shared_t *f_sh)
{
H5MF_aggr_merge_t mapping_type; /* Type of free list mapping */
H5FD_mem_t type; /* Memory type for iteration */
@@ -144,9 +200,8 @@ H5MF_init_merge_flags(H5F_t *f)
FUNC_ENTER_NOAPI(FAIL)
/* check args */
- HDassert(f);
- HDassert(f->shared);
- HDassert(f->shared->lf);
+ HDassert(f_sh);
+ HDassert(f_sh->lf);
/* Iterate over all the free space types to determine if sections of that type
* can merge with the metadata or small 'raw' data aggregator
@@ -154,21 +209,21 @@ H5MF_init_merge_flags(H5F_t *f)
all_same = TRUE;
for(type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, type))
/* Check for any different type mappings */
- if(f->shared->fs_type_map[type] != f->shared->fs_type_map[H5FD_MEM_DEFAULT]) {
+ if(f_sh->fs_type_map[type] != f_sh->fs_type_map[H5FD_MEM_DEFAULT]) {
all_same = FALSE;
break;
} /* end if */
/* Check for all allocation types mapping to the same free list type */
if(all_same) {
- if(f->shared->fs_type_map[H5FD_MEM_DEFAULT] == H5FD_MEM_DEFAULT)
+ if(f_sh->fs_type_map[H5FD_MEM_DEFAULT] == H5FD_MEM_DEFAULT)
mapping_type = H5MF_AGGR_MERGE_SEPARATE;
else
mapping_type = H5MF_AGGR_MERGE_TOGETHER;
} /* end if */
else {
/* Check for raw data mapping into same list as metadata */
- if(f->shared->fs_type_map[H5FD_MEM_DRAW] == f->shared->fs_type_map[H5FD_MEM_SUPER])
+ if(f_sh->fs_type_map[H5FD_MEM_DRAW] == f_sh->fs_type_map[H5FD_MEM_SUPER])
mapping_type = H5MF_AGGR_MERGE_SEPARATE;
else {
hbool_t all_metadata_same; /* Whether all metadata go in same free list */
@@ -181,7 +236,7 @@ H5MF_init_merge_flags(H5F_t *f)
/* (global heap is treated as raw data) */
if(type != H5FD_MEM_DRAW && type != H5FD_MEM_GHEAP) {
/* Check for any different type mappings */
- if(f->shared->fs_type_map[type] != f->shared->fs_type_map[H5FD_MEM_SUPER]) {
+ if(f_sh->fs_type_map[type] != f_sh->fs_type_map[H5FD_MEM_SUPER]) {
all_metadata_same = FALSE;
break;
} /* end if */
@@ -199,30 +254,30 @@ H5MF_init_merge_flags(H5F_t *f)
switch(mapping_type) {
case H5MF_AGGR_MERGE_SEPARATE:
/* Don't merge any metadata together */
- HDmemset(f->shared->fs_aggr_merge, 0, sizeof(f->shared->fs_aggr_merge));
+ HDmemset(f_sh->fs_aggr_merge, 0, sizeof(f_sh->fs_aggr_merge));
/* Check if merging raw data should be allowed */
/* (treat global heaps as raw data) */
- if(H5FD_MEM_DRAW == f->shared->fs_type_map[H5FD_MEM_DRAW] ||
- H5FD_MEM_DEFAULT == f->shared->fs_type_map[H5FD_MEM_DRAW]) {
- f->shared->fs_aggr_merge[H5FD_MEM_DRAW] = H5F_FS_MERGE_RAWDATA;
- f->shared->fs_aggr_merge[H5FD_MEM_GHEAP] = H5F_FS_MERGE_RAWDATA;
+ if(H5FD_MEM_DRAW == f_sh->fs_type_map[H5FD_MEM_DRAW] ||
+ H5FD_MEM_DEFAULT == f_sh->fs_type_map[H5FD_MEM_DRAW]) {
+ f_sh->fs_aggr_merge[H5FD_MEM_DRAW] = H5F_FS_MERGE_RAWDATA;
+ f_sh->fs_aggr_merge[H5FD_MEM_GHEAP] = H5F_FS_MERGE_RAWDATA;
} /* end if */
break;
case H5MF_AGGR_MERGE_DICHOTOMY:
/* Merge all metadata together (but not raw data) */
- HDmemset(f->shared->fs_aggr_merge, H5F_FS_MERGE_METADATA, sizeof(f->shared->fs_aggr_merge));
+ HDmemset(f_sh->fs_aggr_merge, H5F_FS_MERGE_METADATA, sizeof(f_sh->fs_aggr_merge));
/* Allow merging raw data allocations together */
/* (treat global heaps as raw data) */
- f->shared->fs_aggr_merge[H5FD_MEM_DRAW] = H5F_FS_MERGE_RAWDATA;
- f->shared->fs_aggr_merge[H5FD_MEM_GHEAP] = H5F_FS_MERGE_RAWDATA;
+ f_sh->fs_aggr_merge[H5FD_MEM_DRAW] = H5F_FS_MERGE_RAWDATA;
+ f_sh->fs_aggr_merge[H5FD_MEM_GHEAP] = H5F_FS_MERGE_RAWDATA;
break;
case H5MF_AGGR_MERGE_TOGETHER:
/* Merge all allocation types together */
- HDmemset(f->shared->fs_aggr_merge, (H5F_FS_MERGE_METADATA | H5F_FS_MERGE_RAWDATA), sizeof(f->shared->fs_aggr_merge));
+ HDmemset(f_sh->fs_aggr_merge, (H5F_FS_MERGE_METADATA | H5F_FS_MERGE_RAWDATA), sizeof(f_sh->fs_aggr_merge));
break;
default:
@@ -247,31 +302,32 @@ done:
*-------------------------------------------------------------------------
*/
void
-H5MF__alloc_to_fs_type(H5F_t *f, H5FD_mem_t alloc_type, hsize_t size, H5F_mem_page_t *fs_type)
+H5MF__alloc_to_fs_type(H5F_shared_t *f_sh, H5FD_mem_t alloc_type, hsize_t size, H5F_mem_page_t *fs_type)
{
FUNC_ENTER_PACKAGE_NOERR
- HDassert(f);
+ /* Check arguments */
+ HDassert(f_sh);
HDassert(fs_type);
- if(H5F_PAGED_AGGR(f)) { /* paged aggregation */
- if(size >= f->shared->fs_page_size) {
- if(H5F_HAS_FEATURE(f, H5FD_FEAT_PAGED_AGGR)) { /* multi or split driver */
+ if(H5F_SHARED_PAGED_AGGR(f_sh)) { /* paged aggregation */
+ if(size >= f_sh->fs_page_size) {
+ if(H5F_SHARED_HAS_FEATURE(f_sh, H5FD_FEAT_PAGED_AGGR)) { /* multi or split driver */
/* For non-contiguous address space, map to large size free-space manager for each alloc_type */
- if(H5FD_MEM_DEFAULT == f->shared->fs_type_map[alloc_type])
- *fs_type = (H5F_mem_page_t) (alloc_type + (H5FD_MEM_NTYPES - 1));
+ if(H5FD_MEM_DEFAULT == f_sh->fs_type_map[alloc_type])
+ *fs_type = (H5F_mem_page_t)(alloc_type + (H5FD_MEM_NTYPES - 1));
else
- *fs_type = (H5F_mem_page_t) (f->shared->fs_type_map[alloc_type] + (H5FD_MEM_NTYPES - 1));
+ *fs_type = (H5F_mem_page_t)(f_sh->fs_type_map[alloc_type] + (H5FD_MEM_NTYPES - 1));
} /* end if */
else
/* For contiguous address space, map to generic large size free-space manager */
*fs_type = H5F_MEM_PAGE_GENERIC; /* H5F_MEM_PAGE_SUPER */
} /* end if */
else
- *fs_type = (H5F_mem_page_t)H5MF_ALLOC_TO_FS_AGGR_TYPE(f, alloc_type);
+ *fs_type = (H5F_mem_page_t)H5MF_ALLOC_TO_FS_AGGR_TYPE(f_sh, alloc_type);
} /* end if */
else /* non-paged aggregation */
- *fs_type = (H5F_mem_page_t)H5MF_ALLOC_TO_FS_AGGR_TYPE(f, alloc_type);
+ *fs_type = (H5F_mem_page_t)H5MF_ALLOC_TO_FS_AGGR_TYPE(f_sh, alloc_type);
FUNC_LEAVE_NOAPI_VOID
} /* end H5MF__alloc_to_fs_type() */
@@ -333,7 +389,7 @@ H5MF__open_fstype(H5F_t *f, H5F_mem_page_t type)
} /* end else */
/* Set the ring type in the API context */
- if(H5MF__fsm_type_is_self_referential(f, type))
+ if(H5MF__fsm_type_is_self_referential(f->shared, type))
fsm_ring = H5AC_RING_MDFSM;
else
fsm_ring = H5AC_RING_RDFSM;
@@ -421,7 +477,7 @@ H5MF__create_fstype(H5F_t *f, H5F_mem_page_t type)
} /* end else */
/* Set the ring type in the API context */
- if(H5MF__fsm_type_is_self_referential(f, type))
+ if(H5MF__fsm_type_is_self_referential(f->shared, type))
fsm_ring = H5AC_RING_MDFSM;
else
fsm_ring = H5AC_RING_RDFSM;
@@ -537,7 +593,7 @@ H5MF__delete_fstype(H5F_t *f, H5F_mem_page_t type)
f->shared->fs_state[type] = H5F_FS_STATE_DELETING;
/* Set the ring type in the API context */
- if(H5MF__fsm_type_is_self_referential(f, type))
+ if(H5MF__fsm_type_is_self_referential(f->shared, type))
fsm_ring = H5AC_RING_MDFSM;
else
fsm_ring = H5AC_RING_RDFSM;
@@ -613,7 +669,6 @@ done:
FUNC_LEAVE_NOAPI_TAG(ret_value)
} /* end H5MF__close_fstype() */
-
/*-------------------------------------------------------------------------
* Function: H5MF__add_sect
@@ -642,7 +697,7 @@ H5MF__add_sect(H5F_t *f, H5FD_mem_t alloc_type, H5FS_t *fspace, H5MF_free_sectio
HDassert(fspace);
HDassert(node);
- H5MF__alloc_to_fs_type(f, alloc_type, node->sect_info.size, &fs_type);
+ H5MF__alloc_to_fs_type(f->shared, alloc_type, node->sect_info.size, &fs_type);
/* Construct user data for callbacks */
udata.f = f;
@@ -651,7 +706,7 @@ H5MF__add_sect(H5F_t *f, H5FD_mem_t alloc_type, H5FS_t *fspace, H5MF_free_sectio
udata.allow_eoa_shrink_only = FALSE;
/* Set the ring type in the API context */
- if(H5MF__fsm_is_self_referential(f, fspace))
+ if(H5MF__fsm_is_self_referential(f->shared, fspace))
fsm_ring = H5AC_RING_MDFSM;
else
fsm_ring = H5AC_RING_RDFSM;
@@ -701,7 +756,7 @@ H5MF__find_sect(H5F_t *f, H5FD_mem_t alloc_type, hsize_t size, H5FS_t *fspace,
HDassert(fspace);
/* Set the ring type in the API context */
- if(H5MF__fsm_is_self_referential(f, fspace))
+ if(H5MF__fsm_is_self_referential(f->shared, fspace))
fsm_ring = H5AC_RING_MDFSM;
else
fsm_ring = H5AC_RING_RDFSM;
@@ -794,20 +849,20 @@ HDfprintf(stderr, "%s: alloc_type = %u, size = %Hu\n", FUNC, (unsigned)alloc_typ
HDassert(f->shared->lf);
HDassert(size > 0);
- if(f->shared->first_alloc_dealloc) {
- HDassert(! H5AC_cache_image_pending(f));
- if(H5MF_tidy_self_referential_fsm_hack(f) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, HADDR_UNDEF, "tidy of self referential fsm hack failed")
- } /* end if */
-
- H5MF__alloc_to_fs_type(f, alloc_type, size, &fs_type);
+ if (!f->shared->vfd_swmr_writer)
+ ; // not a VFD SWMR writer, do not process deferrals
+ else if (process_deferred_frees(f) < 0) {
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGC, HADDR_UNDEF,
+ "could not process deferrals")
+ }
+ H5MF__alloc_to_fs_type(f->shared, alloc_type, size, &fs_type);
#ifdef H5MF_ALLOC_DEBUG_MORE
HDfprintf(stderr, "%s: Check 1.0\n", FUNC);
#endif /* H5MF_ALLOC_DEBUG_MORE */
/* Set the ring type in the API context */
- if(H5MF__fsm_type_is_self_referential(f, fs_type))
+ if(H5MF__fsm_type_is_self_referential(f->shared, fs_type))
fsm_ring = H5AC_RING_MDFSM;
else
fsm_ring = H5AC_RING_RDFSM;
@@ -906,15 +961,15 @@ H5MF__alloc_pagefs(H5F_t *f, H5FD_mem_t alloc_type, hsize_t size)
HDfprintf(stderr, "%s: alloc_type = %u, size = %Hu\n", FUNC, (unsigned)alloc_type, size);
#endif /* H5MF_ALLOC_DEBUG */
- H5MF__alloc_to_fs_type(f, alloc_type, size, &ptype);
+ H5MF__alloc_to_fs_type(f->shared, alloc_type, size, &ptype);
switch(ptype) {
- case H5F_MEM_PAGE_GENERIC:
- case H5F_MEM_PAGE_LARGE_BTREE:
- case H5F_MEM_PAGE_LARGE_DRAW:
- case H5F_MEM_PAGE_LARGE_GHEAP:
- case H5F_MEM_PAGE_LARGE_LHEAP:
- case H5F_MEM_PAGE_LARGE_OHDR:
+ case H5F_MEM_PAGE_GENERIC:
+ case H5F_MEM_PAGE_LARGE_BTREE:
+ case H5F_MEM_PAGE_LARGE_DRAW:
+ case H5F_MEM_PAGE_LARGE_GHEAP:
+ case H5F_MEM_PAGE_LARGE_LHEAP:
+ case H5F_MEM_PAGE_LARGE_OHDR:
{
haddr_t eoa; /* EOA for the file */
hsize_t frag_size = 0; /* Fragment size */
@@ -951,7 +1006,7 @@ HDfprintf(stderr, "%s: alloc_type = %u, size = %Hu\n", FUNC, (unsigned)alloc_typ
}
break;
- case H5F_MEM_PAGE_META:
+ case H5F_MEM_PAGE_META:
case H5F_MEM_PAGE_DRAW:
case H5F_MEM_PAGE_BTREE:
case H5F_MEM_PAGE_GHEAP:
@@ -979,13 +1034,13 @@ HDfprintf(stderr, "%s: alloc_type = %u, size = %Hu\n", FUNC, (unsigned)alloc_typ
node = NULL;
- /* Insert the new page into the Page Buffer list of new pages so
+ /* Insert the new page into the Page Buffer list of new pages so
we don't read an empty page from disk */
- if(f->shared->pb_ptr != NULL && H5PB_add_new_page(f, alloc_type, new_page) < 0)
+ if(f->shared->pb_ptr != NULL && H5PB_add_new_page(f->shared, alloc_type, new_page) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINSERT, HADDR_UNDEF, "can't add new page to Page Buffer new page list")
ret_value = new_page;
- }
+ }
break;
case H5F_MEM_PAGE_NTYPES:
@@ -1089,11 +1144,6 @@ done:
herr_t
H5MF_xfree(H5F_t *f, H5FD_mem_t alloc_type, haddr_t addr, hsize_t size)
{
- H5F_mem_page_t fs_type; /* Free space type (mapped from allocation type) */
- H5MF_free_section_t *node = NULL; /* Free space section pointer */
- unsigned ctype; /* section class type */
- H5AC_ring_t orig_ring = H5AC_RING_INV; /* Original ring value */
- H5AC_ring_t fsm_ring; /* Ring of FSM */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_TAG(H5AC__FREESPACE_TAG, FAIL)
@@ -1107,16 +1157,36 @@ HDfprintf(stderr, "%s: Entering - alloc_type = %u, addr = %a, size = %Hu\n", FUN
HGOTO_DONE(SUCCEED)
HDassert(addr != 0); /* Can't deallocate the superblock :-) */
- if(f->shared->first_alloc_dealloc) {
- HDassert(!H5AC_cache_image_pending(f));
- if(H5MF_tidy_self_referential_fsm_hack(f) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "tidy of self referential fsm hack failed")
- } /* end if */
+ if (!f->shared->vfd_swmr_writer) {
+ // not a VFD SWMR writer, do not defer or process deferrals
+ ret_value = H5MF_xfree_impl(f, alloc_type, addr, size);
+ } else if (defer_free(f->shared, alloc_type, addr, size) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "could not defer")
+ else if (process_deferred_frees(f) < 0) {
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGC, FAIL,
+ "could not process deferrals")
+ }
- H5MF__alloc_to_fs_type(f, alloc_type, size, &fs_type);
+done:
+ FUNC_LEAVE_NOAPI_TAG(ret_value)
+}
+
+static herr_t
+H5MF_xfree_impl(H5F_t *f, H5FD_mem_t alloc_type, haddr_t addr, hsize_t size)
+{
+ H5F_mem_page_t fs_type; /* Free space type (mapped from allocation type) */
+ H5MF_free_section_t *node = NULL; /* Free space section pointer */
+ unsigned ctype; /* section class type */
+ H5AC_ring_t orig_ring = H5AC_RING_INV; /* Original ring value */
+ H5AC_ring_t fsm_ring; /* Ring of FSM */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC_TAG(H5AC__FREESPACE_TAG)
+
+ H5MF__alloc_to_fs_type(f->shared, alloc_type, size, &fs_type);
/* Set the ring type in the API context */
- if(H5MF__fsm_type_is_self_referential(f, fs_type))
+ if(H5MF__fsm_type_is_self_referential(f->shared, fs_type))
fsm_ring = H5AC_RING_MDFSM;
else
fsm_ring = H5AC_RING_RDFSM;
@@ -1138,11 +1208,10 @@ HDfprintf(stderr, "%s: Entering - alloc_type = %u, addr = %a, size = %Hu\n", FUN
/* If it's metadata, check if the space to free intersects with the file's
* metadata accumulator
*/
- if(H5FD_MEM_DRAW != alloc_type) {
+ if(H5FD_MEM_DRAW != alloc_type)
/* Check if the space to free intersects with the file's metadata accumulator */
- if(H5F__accum_free(f, alloc_type, addr, size) < 0)
+ if(H5F__accum_free(f->shared, alloc_type, addr, size) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "can't check free space intersection w/metadata accumulator")
- } /* end if */
/* Check if the free space manager for the file has been initialized */
if(!f->shared->fs_man[fs_type]) {
@@ -1238,14 +1307,21 @@ HDfprintf(stderr, "%s: After H5FS_sect_add()\n", FUNC);
node = NULL;
} /* end else */
- /* Multi-page and VFD SWMR writer: remove from PB if exists there */
+ /* Multi-page and VFD SWMR writer: remove from PB if exists there.
+ *
+ * It's ok to remove the page from the PB without flushing to
+ * the shadow file or to the underlying HDF5 file because any
+ * writes to the page in this tick have not yet become visible
+ * to the reader, and any writes to the page in previous ticks are
+ * recorded in the shadow file.
+ */
if(size > f->shared->fs_page_size && f->shared->vfd_swmr_writer) {
HDassert(f->shared->pb_ptr != NULL);
HDassert(H5F_USE_VFD_SWMR(f));
- HDassert(H5F_PAGED_AGGR(f));
+ HDassert(H5F_SHARED_PAGED_AGGR(f->shared));
- if(H5PB_remove_entry(f, addr) < 0)
+ if(H5PB_remove_entry(f->shared, addr) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "can't remove the page from page buffer")
}
@@ -1313,12 +1389,6 @@ HDfprintf(stderr, "%s: Entering: alloc_type = %u, addr = %a, size = %Hu, extra_r
HDassert(f);
HDassert(H5F_INTENT(f) & H5F_ACC_RDWR);
- if(f->shared->first_alloc_dealloc) {
- HDassert(! H5AC_cache_image_pending(f));
- if(H5MF_tidy_self_referential_fsm_hack(f) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "tidy of self referential fsm hack failed")
- } /* end if */
-
/* Set mapped type, treating global heap as raw data */
map_type = (alloc_type == H5FD_MEM_GHEAP) ? H5FD_MEM_DRAW : alloc_type;
@@ -1348,10 +1418,10 @@ HDfprintf(stderr, "%s: Entering: alloc_type = %u, addr = %a, size = %Hu, extra_r
} /* end if */
/* Get free space type from allocation type */
- H5MF__alloc_to_fs_type(f, alloc_type, size, &fs_type);
+ H5MF__alloc_to_fs_type(f->shared, alloc_type, size, &fs_type);
/* Set the ring type in the API context */
- if(H5MF__fsm_type_is_self_referential(f, fs_type))
+ if(H5MF__fsm_type_is_self_referential(f->shared, fs_type))
fsm_ring = H5AC_RING_MDFSM;
else
fsm_ring = H5AC_RING_RDFSM;
@@ -1499,10 +1569,10 @@ HDfprintf(stderr, "%s: Entering - alloc_type = %u, addr = %a, size = %Hu\n", FUN
HDassert(sect_cls);
/* Get free space type from allocation type */
- H5MF__alloc_to_fs_type(f, alloc_type, size, &fs_type);
+ H5MF__alloc_to_fs_type(f->shared, alloc_type, size, &fs_type);
/* Set the ring type in the API context */
- if(H5MF__fsm_type_is_self_referential(f, fs_type))
+ if(H5MF__fsm_type_is_self_referential(f->shared, fs_type))
fsm_ring = H5AC_RING_MDFSM;
else
fsm_ring = H5AC_RING_RDFSM;
@@ -1575,11 +1645,11 @@ HDfprintf(stderr, "%s: Entering\n", FUNC);
if(H5F_PAGED_AGGR(f)) {
if((ret_value = H5MF__close_pagefs(f)) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTFREE, FAIL, "can't close free-space managers for 'page' file space")
- }
+ } /* end if */
else {
if((ret_value = H5MF__close_aggrfs(f)) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTFREE, FAIL, "can't close free-space managers for 'aggr' file space")
- }
+ } /* end else */
done:
#ifdef H5MF_ALLOC_DEBUG
@@ -1685,22 +1755,12 @@ HDfprintf(stderr, "%s: Entering\n", FUNC);
*
* The situation is further complicated if a cache image exists
* and had not yet been loaded into the metadata cache. In this
- * case, call H5AC_force_cache_image_load() instead of
+ * case, call H5AC_force_cache_image_load() instead of
* H5MF_tidy_self_referential_fsm_hack(). H5AC_force_cache_image_load()
- * will load the cache image, and then call
- * H5MF_tidy_self_referential_fsm_hack() to discard the cache image
+ * will load the cache image, and then call
+ * H5MF_tidy_self_referential_fsm_hack() to discard the cache image
* block.
*/
- if(f->shared->first_alloc_dealloc) {
- if(H5AC_cache_image_pending(f)) {
- if(H5AC_force_cache_image_load(f) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "forced cache image load failed")
- } /* end if */
- else {
- if(H5MF_tidy_self_referential_fsm_hack(f) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "tidy of self referential fsm hack failed")
- } /* end else */
- } /* end if */
/* Set the ring type in the API context. In most cases, we will
* need H5AC_RING_RDFSM, so initially set the ring in
@@ -1712,12 +1772,12 @@ HDfprintf(stderr, "%s: Entering\n", FUNC);
if(H5F_PAGED_AGGR(f)) {
H5F_mem_page_t ptype; /* Memory type for iteration */
- /* Iterate over all the free space types that have managers and
- * get each free list's space
+ /* Iterate over all the free space types that have managers and
+ * get each free list's space
*/
for(ptype = H5F_MEM_PAGE_META; ptype < H5F_MEM_PAGE_NTYPES; H5_INC_ENUM(H5F_mem_page_t, ptype)) {
/* Test to see if we need to switch rings -- do so if required */
- if(H5MF__fsm_type_is_self_referential(f, ptype))
+ if(H5MF__fsm_type_is_self_referential(f->shared, ptype))
needed_ring = H5AC_RING_MDFSM;
else
needed_ring = H5AC_RING_RDFSM;
@@ -1734,12 +1794,12 @@ HDfprintf(stderr, "%s: Entering\n", FUNC);
else {
H5FD_mem_t type; /* Memory type for iteration */
- /* Iterate over all the free space types that have managers and
- * get each free list's space
+ /* Iterate over all the free space types that have managers and
+ * get each free list's space
*/
for(type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, type)) {
/* Test to see if we need to switch rings -- do so if required */
- if(H5MF__fsm_type_is_self_referential(f, (H5F_mem_page_t)type))
+ if(H5MF__fsm_type_is_self_referential(f->shared, (H5F_mem_page_t)type))
needed_ring = H5AC_RING_MDFSM;
else
needed_ring = H5AC_RING_RDFSM;
@@ -1845,7 +1905,8 @@ HDfprintf(stderr, "%s: Entering\n", FUNC);
fsinfo.threshold = f->shared->fs_threshold;
fsinfo.page_size = f->shared->fs_page_size;
fsinfo.pgend_meta_thres = f->shared->pgend_meta_thres;
- fsinfo.eoa_pre_fsm_fsalloc = f->shared->eoa_pre_fsm_fsalloc;
+ fsinfo.eoa_pre_fsm_fsalloc = f->shared->eoa_fsm_fsalloc;
+ fsinfo.version = f->shared->fs_version;
/* Write the free space manager message -- message must already exist */
if(H5F__super_ext_write_msg(f, H5O_FSINFO_ID, &fsinfo, FALSE, H5O_MSG_FLAG_MARK_IF_UNKNOWN) < 0)
@@ -1855,9 +1916,9 @@ HDfprintf(stderr, "%s: Entering\n", FUNC);
for(type = H5FD_MEM_SUPER; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, type)) {
if(f->shared->fs_man[type]) {
/* Test to see if we need to switch rings -- do so if required */
- if(H5MF__fsm_type_is_self_referential(f, (H5F_mem_page_t)type))
+ if(H5MF__fsm_type_is_self_referential(f->shared, (H5F_mem_page_t)type))
needed_ring = H5AC_RING_MDFSM;
- else
+ else
needed_ring = H5AC_RING_RDFSM;
if(needed_ring != curr_ring) {
@@ -1902,7 +1963,7 @@ HDfprintf(stderr, "%s: Entering\n", FUNC);
* been no file space allocation or deallocation since file
* open.
*/
- HDassert((f->shared->first_alloc_dealloc) || (final_eoa == f->shared->eoa_post_fsm_fsalloc));
+ HDassert(H5F_NULL_FSM_ADDR(f) || final_eoa == f->shared->eoa_fsm_fsalloc);
} /* end if */
else { /* super_vers can be 0, 1, 2 */
for(type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, type))
@@ -1984,6 +2045,8 @@ HDfprintf(stderr, "%s: Entering\n", FUNC);
fsinfo.page_size = f->shared->fs_page_size;
fsinfo.pgend_meta_thres = f->shared->pgend_meta_thres;
fsinfo.eoa_pre_fsm_fsalloc = HADDR_UNDEF;
+ fsinfo.version = f->shared->fs_version;
+
for(ptype = H5F_MEM_PAGE_META; ptype < H5F_MEM_PAGE_NTYPES; H5_INC_ENUM(H5F_mem_page_t, ptype))
fsinfo.fs_addr[ptype - 1] = HADDR_UNDEF;
@@ -2003,12 +2066,12 @@ HDfprintf(stderr, "%s: Entering\n", FUNC);
/* gather data for the free space manager superblock extension message.
* Only need addresses of FSMs and eoa prior to allocation of
- * file space for the self referential free space managers. Other
+ * file space for the self referential free space managers. Other
* data was gathered above.
*/
for(ptype = H5F_MEM_PAGE_META; ptype < H5F_MEM_PAGE_NTYPES; H5_INC_ENUM(H5F_mem_page_t, ptype))
fsinfo.fs_addr[ptype-1] = f->shared->fs_addr[ptype];
- fsinfo.eoa_pre_fsm_fsalloc = f->shared->eoa_pre_fsm_fsalloc;
+ fsinfo.eoa_pre_fsm_fsalloc = f->shared->eoa_fsm_fsalloc;
/* Write the free space manager message -- message must already exist */
if(H5F__super_ext_write_msg(f, H5O_FSINFO_ID, &fsinfo, FALSE, H5O_MSG_FLAG_MARK_IF_UNKNOWN) < 0)
@@ -2019,7 +2082,7 @@ HDfprintf(stderr, "%s: Entering\n", FUNC);
for(ptype = H5F_MEM_PAGE_META; ptype < H5F_MEM_PAGE_NTYPES; H5_INC_ENUM(H5F_mem_page_t, ptype)) {
if(f->shared->fs_man[ptype]) {
/* Test to see if we need to switch rings -- do so if required */
- if(H5MF__fsm_type_is_self_referential(f, ptype))
+ if(H5MF__fsm_type_is_self_referential(f->shared, ptype))
needed_ring = H5AC_RING_MDFSM;
else
needed_ring = H5AC_RING_RDFSM;
@@ -2069,8 +2132,8 @@ HDfprintf(stderr, "%s: Entering\n", FUNC);
* the file driver layer. However, as this possibility seems remote,
* it is ignored in the following assert.
*/
- HDassert((f->shared->first_alloc_dealloc) ||
- (final_eoa == f->shared->eoa_post_fsm_fsalloc) ||
+ HDassert((H5F_NULL_FSM_ADDR(f)) ||
+ (final_eoa == f->shared->eoa_fsm_fsalloc) ||
((H5F_addr_defined(f->shared->eoa_post_mdci_fsalloc)) &&
(final_eoa == f->shared->eoa_post_mdci_fsalloc)));
} /* end if */
@@ -2154,7 +2217,7 @@ H5MF__close_shrink_eoa(H5F_t *f)
for(ptype = H5F_MEM_PAGE_META; ptype < H5F_MEM_PAGE_NTYPES; H5_INC_ENUM(H5F_mem_page_t, ptype)) {
if(f->shared->fs_man[ptype]) {
/* Test to see if we need to switch rings -- do so if required */
- if(H5MF__fsm_type_is_self_referential(f, ptype))
+ if(H5MF__fsm_type_is_self_referential(f->shared, ptype))
needed_ring = H5AC_RING_MDFSM;
else
needed_ring = H5AC_RING_RDFSM;
@@ -2178,7 +2241,7 @@ H5MF__close_shrink_eoa(H5F_t *f)
for(type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, type)) {
if(f->shared->fs_man[type]) {
/* Test to see if we need to switch rings -- do so if required */
- if(H5MF__fsm_type_is_self_referential(f, (H5F_mem_page_t)type))
+ if(H5MF__fsm_type_is_self_referential(f->shared, (H5F_mem_page_t)type))
needed_ring = H5AC_RING_MDFSM;
else
needed_ring = H5AC_RING_RDFSM;
@@ -2298,7 +2361,7 @@ H5MF_get_freespace(H5F_t *f, hsize_t *tot_space, hsize_t *meta_size)
} /* end if */
/* Test to see if we need to switch rings -- do so if required */
- if(H5MF__fsm_type_is_self_referential(f, (H5F_mem_page_t)type))
+ if(H5MF__fsm_type_is_self_referential(f->shared, (H5F_mem_page_t)type))
needed_ring = H5AC_RING_MDFSM;
else
needed_ring = H5AC_RING_RDFSM;
@@ -2328,7 +2391,7 @@ H5MF_get_freespace(H5F_t *f, hsize_t *tot_space, hsize_t *meta_size)
/* Close the free-space managers if they were opened earlier in this routine */
for(type = start_type; type < end_type; H5_INC_ENUM(H5F_mem_page_t, type)) {
/* Test to see if we need to switch rings -- do so if required */
- if(H5MF__fsm_type_is_self_referential(f, (H5F_mem_page_t)type))
+ if(H5MF__fsm_type_is_self_referential(f->shared, (H5F_mem_page_t)type))
needed_ring = H5AC_RING_MDFSM;
else
needed_ring = H5AC_RING_RDFSM;
@@ -2403,16 +2466,6 @@ H5MF_get_free_sections(H5F_t *f, H5FD_mem_t type, size_t nsects, H5F_sect_info_t
* H5MF_tidy_self_referential_fsm_hack() to discard the cache image
* block.
*/
- if(f->shared->first_alloc_dealloc) {
- if(H5AC_cache_image_pending(f)) {
- if(H5AC_force_cache_image_load(f) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, (-1), "forced cache image load failed")
- } /* end if */
- else {
- if(H5MF_tidy_self_referential_fsm_hack(f) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, (-1), "tidy of self referential fsm hack failed")
- } /* end else */
- } /* end if */
if(type == H5FD_MEM_DEFAULT) {
start_type = H5F_MEM_PAGE_SUPER;
@@ -2444,7 +2497,7 @@ H5MF_get_free_sections(H5F_t *f, H5FD_mem_t type, size_t nsects, H5F_sect_info_t
size_t nums = 0; /* The number of free-space sections */
/* Test to see if we need to switch rings -- do so if required */
- if(H5MF__fsm_type_is_self_referential(f, ty))
+ if(H5MF__fsm_type_is_self_referential(f->shared, ty))
needed_ring = H5AC_RING_MDFSM;
else
needed_ring = H5AC_RING_RDFSM;
@@ -2684,10 +2737,11 @@ H5MF_settle_raw_data_fsm(H5F_t *f, hbool_t *fsm_settled)
HDassert(f->shared);
HDassert(fsm_settled);
- /* Only need to settle things if we are persisting the free space info
- * and allocation/deallocation has occurred.
+ /*
+ * Only need to settle things if we are persisting free space and
+ * the private property in f->shared->null_fsm_addr is not enabled.
*/
- if(f->shared->fs_persist && !f->shared->first_alloc_dealloc) {
+ if(f->shared->fs_persist && !H5F_NULL_FSM_ADDR(f)) {
hbool_t fsm_opened[H5F_MEM_PAGE_NTYPES]; /* State of FSM */
hbool_t fsm_visited[H5F_MEM_PAGE_NTYPES]; /* State of FSM */
@@ -2769,7 +2823,7 @@ H5MF_settle_raw_data_fsm(H5F_t *f, hbool_t *fsm_settled)
break;
for(mem_type = H5FD_MEM_SUPER; mem_type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5F_mem_t, mem_type)) {
- H5MF__alloc_to_fs_type(f, mem_type, alloc_size, &fsm_type);
+ H5MF__alloc_to_fs_type(f->shared, mem_type, alloc_size, &fsm_type);
if(pass_count == 0) { /* this is the first pass */
HDassert(fsm_type > H5F_MEM_PAGE_DEFAULT);
@@ -2802,7 +2856,7 @@ H5MF_settle_raw_data_fsm(H5F_t *f, hbool_t *fsm_settled)
if(f->shared->fs_man[fsm_type]) {
/* Test to see if we need to switch rings -- do so if required */
- if(H5MF__fsm_type_is_self_referential(f, fsm_type))
+ if(H5MF__fsm_type_is_self_referential(f->shared, fsm_type))
needed_ring = H5AC_RING_MDFSM;
else
needed_ring = H5AC_RING_RDFSM;
@@ -2914,7 +2968,7 @@ H5MF_settle_raw_data_fsm(H5F_t *f, hbool_t *fsm_settled)
break;
for(mem_type = H5FD_MEM_SUPER; mem_type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5F_mem_t, mem_type)) {
- H5MF__alloc_to_fs_type(f, mem_type, alloc_size, &fsm_type);
+ H5MF__alloc_to_fs_type(f->shared, mem_type, alloc_size, &fsm_type);
if(pass_count == 0) { /* this is the first pass */
HDassert(fsm_type > H5F_MEM_PAGE_DEFAULT);
@@ -2928,7 +2982,7 @@ H5MF_settle_raw_data_fsm(H5F_t *f, hbool_t *fsm_settled)
HDassert(FALSE);
/* Test to see if we need to switch rings -- do so if required */
- if(H5MF__fsm_type_is_self_referential(f, fsm_type))
+ if(H5MF__fsm_type_is_self_referential(f->shared, fsm_type))
needed_ring = H5AC_RING_MDFSM;
else
needed_ring = H5AC_RING_RDFSM;
@@ -2951,7 +3005,7 @@ H5MF_settle_raw_data_fsm(H5F_t *f, hbool_t *fsm_settled)
* that this is also the deciding factor as to whether a FSM
* in in the raw data FSM ring.
*/
- if(!H5MF__fsm_type_is_self_referential(f, fsm_type)) {
+ if(!H5MF__fsm_type_is_self_referential(f->shared, fsm_type)) {
/* The current ring should be H5AC_RING_RDFSM */
HDassert(curr_ring == H5AC_RING_RDFSM);
@@ -3025,6 +3079,7 @@ done:
FUNC_LEAVE_NOAPI_TAG(ret_value)
} /* H5MF_settle_raw_data_fsm() */
+
/*-------------------------------------------------------------------------
* Function: H5MF_settle_meta_data_fsm()
@@ -3043,7 +3098,7 @@ done:
* On entry to this function, the raw data settle routine
* (H5MF_settle_raw_data_fsm()) should have:
*
- * 1) Freed the aggregators.
+ * 1) Freed the aggregators.
*
* 2) Freed all file space allocated to the free space managers.
*
@@ -3079,12 +3134,12 @@ done:
* 1) Verify that the free space manager(s) involved in file
* space allocation for free space managers are still floating.
*
- * 2) Free the aggregators.
+ * 2) Free the aggregators.
*
- * 3) Reduce the EOA to the extent possible, and make note
+ * 3) Reduce the EOA to the extent possible, and make note
* of the resulting value. This value will be stored
* in the fsinfo superblock extension message and be used
- * in the subsequent file open.
+ * in the subsequent file open.
*
* 4) Re-allocate space for any free space manager(s) that:
*
@@ -3105,21 +3160,15 @@ done:
* allocation has changed the size of the section info --
* forcing us to deallocate and start the loop over again.
*
- * To avoid this, simply allocate file space for these
- * FSM(s) directly from the VFD layer if allocation is
- * indicated. This avoids the issue by bypassing the FSMs
- * in this case.
- *
- * Note that this may increase the size of the file needlessly.
- * A better solution would be to modify the FSM code to
+ * The solution is to modify the FSM code to
* save empty FSMs to file, and to allow section info blocks
- * to be oversized. However, given that the FSM code is
- * also used by the fractal heaps, and that we are under
- * severe time pressure at the moment, the above brute
- * force solution is attractive.
+ * to be oversized. That is, only allow section info to increase
+ * in size, not shrink. The solution is now implemented.
*
- * 5) Make note of the EOA -- used for sanity checking on
- * FSM shutdown.
+ * 5) Make note of the EOA -- used for sanity checking on
+ * FSM shutdown. This is saved as eoa_pre_fsm_fsalloc in
+ * the free-space info message for backward compatibility
+ * with the 1.10 library that has the hack.
*
* Return: SUCCEED/FAIL
*
@@ -3139,10 +3188,9 @@ H5MF_settle_meta_data_fsm(H5F_t *f, hbool_t *fsm_settled)
H5FS_t *sm_sinfo_fspace = NULL; /* ptr to sm FSM sinfo alloc FSM */
H5FS_t *lg_hdr_fspace = NULL; /* ptr to lg FSM hdr alloc FSM */
H5FS_t *lg_sinfo_fspace = NULL; /* ptr to lg FSM sinfo alloc FSM */
- haddr_t eoa_pre_fsm_fsalloc; /* eoa pre file space allocation */
- /* for self referential FSMs */
- haddr_t eoa_post_fsm_fsalloc; /* eoa post file space allocation */
+ haddr_t eoa_fsm_fsalloc; /* eoa after file space allocation */
/* for self referential FSMs */
+ hbool_t continue_alloc_fsm = FALSE; /* Continue allocating addr and sect_addr for FSMs */
H5AC_ring_t orig_ring = H5AC_RING_INV; /* Original ring value */
herr_t ret_value = SUCCEED; /* Return value */
@@ -3153,18 +3201,19 @@ H5MF_settle_meta_data_fsm(H5F_t *f, hbool_t *fsm_settled)
HDassert(f->shared);
HDassert(fsm_settled);
- /* Only need to settle things if we are persisting the free space info
- * and allocation/deallocation has occurred.
+ /*
+ * Only need to settle things if we are persisting free space and
+ * the private property in f->shared->null_fsm_addr is not enabled.
*/
- if(f->shared->fs_persist && !f->shared->first_alloc_dealloc) {
+ if(f->shared->fs_persist && !H5F_NULL_FSM_ADDR(f)) {
/* Sanity check */
HDassert(f->shared->lf);
/* should only be called if file is opened R/W */
HDassert(H5F_INTENT(f) & H5F_ACC_RDWR);
- H5MF__alloc_to_fs_type(f, H5FD_MEM_FSPACE_HDR, (size_t)1, &sm_fshdr_fs_type);
- H5MF__alloc_to_fs_type(f, H5FD_MEM_FSPACE_SINFO, (size_t)1, &sm_fssinfo_fs_type);
+ H5MF__alloc_to_fs_type(f->shared, H5FD_MEM_FSPACE_HDR, (size_t)1, &sm_fshdr_fs_type);
+ H5MF__alloc_to_fs_type(f->shared, H5FD_MEM_FSPACE_SINFO, (size_t)1, &sm_fssinfo_fs_type);
HDassert(sm_fshdr_fs_type > H5F_MEM_PAGE_DEFAULT);
HDassert(sm_fshdr_fs_type < H5F_MEM_PAGE_LARGE_SUPER);
@@ -3180,8 +3229,8 @@ H5MF_settle_meta_data_fsm(H5F_t *f, hbool_t *fsm_settled)
sm_sinfo_fspace = f->shared->fs_man[sm_fssinfo_fs_type];
if(H5F_PAGED_AGGR(f)) {
- H5MF__alloc_to_fs_type(f, H5FD_MEM_FSPACE_HDR, f->shared->fs_page_size + 1, &lg_fshdr_fs_type);
- H5MF__alloc_to_fs_type(f, H5FD_MEM_FSPACE_SINFO, f->shared->fs_page_size + 1, &lg_fssinfo_fs_type);
+ H5MF__alloc_to_fs_type(f->shared, H5FD_MEM_FSPACE_HDR, f->shared->fs_page_size + 1, &lg_fshdr_fs_type);
+ H5MF__alloc_to_fs_type(f->shared, H5FD_MEM_FSPACE_SINFO, f->shared->fs_page_size + 1, &lg_fssinfo_fs_type);
HDassert(lg_fshdr_fs_type >= H5F_MEM_PAGE_LARGE_SUPER);
HDassert(lg_fshdr_fs_type < H5F_MEM_PAGE_NTYPES);
@@ -3204,7 +3253,6 @@ H5MF_settle_meta_data_fsm(H5F_t *f, hbool_t *fsm_settled)
{
H5FS_stat_t fs_stat; /* Information for hdr FSM */
- /* Verify that sm_hdr_fspace is floating if it exists */
if(sm_hdr_fspace) {
/* Query free space manager info for this type */
if(H5FS_stat_info(f, sm_hdr_fspace, &fs_stat) < 0)
@@ -3261,7 +3309,6 @@ H5MF_settle_meta_data_fsm(H5F_t *f, hbool_t *fsm_settled)
* Note that the aggregators will not exist if paged aggregation
* is enabled -- don't attempt to free if this is the case.
*/
- /* Vailin -- is this correct? */
/* (for space not at EOF, it may be put into free space managers) */
if((!H5F_PAGED_AGGR(f)) && (H5MF_free_aggrs(f) < 0))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "can't free aggregators")
@@ -3270,21 +3317,7 @@ H5MF_settle_meta_data_fsm(H5F_t *f, hbool_t *fsm_settled)
if(H5MF__close_shrink_eoa(f) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTSHRINK, FAIL, "can't shrink eoa")
- /* At this point, the EOA should be set to a value that contains
- * the allocation for all user data, all non self referential FSMs,
- * the superblock and all superblock extension messages.
- *
- * Make note of the current EOA. We will store this value in the
- * free space manager superblock extension message. Since space for
- * everything other than the self referential FSMs (and possibly the
- * cache image) has been allocated at this point, this allows us to
- * to float the self referential FSMs on the first file space allocation /
- * deallocation and then set the EOA to this value before we handle
- * the allocation / deallocation. (If a cache image exists, the
- * first allocation / deallocation will be the deallocation of space
- * for the cache image).
- *
- * WARNING: This approach settling the self referential free space
+ /* WARNING: This approach settling the self referential free space
* managers and allocating space for them in the file will
* not work as currently implemented with the split and
* multi file drivers, as the self referential free space
@@ -3303,97 +3336,66 @@ H5MF_settle_meta_data_fsm(H5F_t *f, hbool_t *fsm_settled)
* We should be able to support the split file driver
* without a file format change. However, the code to
* do so does not exist at present.
+ * NOTE: not sure whether to remove or keep the above comments
*/
- if(HADDR_UNDEF == (eoa_pre_fsm_fsalloc = H5FD_get_eoa(f->shared->lf, H5FD_MEM_DEFAULT)))
- HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get EOA")
-
- /* ******************* PROBLEM: ********************
- *
- * If the file has an alignment other than 1, and if
- * the EOA is not a multiple of this alignment, allocating space
- * for the section via the VFD info has the potential of generating
- * a fragment that will be added to the free space manager. This
- * of course undoes everything we have been doing here.
- *
- * Need a way around this. Obvious solution is to force the EOA to
- * be a multiple of the alignment.
- *
- * Fortunately, alignment is typically 1, so this is a non-issue in
- * most cases. In cases where the alignment is not 1, for now we
- * have decided to drop the fragment on the floor.
- *
- * Eventually, we should fix this by modifying the on disk representations
- * of free space managers to allow for empty space, so as to bypass the
- * issues created by self-referential free space managers, and make
- * this issue moot.
+ /*
+ * Continue allocating file space for the header and section info until
+ * they are all settled,
*/
- /* HDassert(f->shared->alignment == 1); */
-
-
- /* The free space manager(s) that handle space allocations for free
- * space managers should be settled now, albeit without file space
- * allocated to them. To avoid the possibility of changing the sizes
- * of their section info blocks, allocate space for them now at the
- * end of file via H5FD_alloc().
- *
- * In the past, this issue of allocating space without touching the
- * free space managers has been dealt with by calling
- * H5MF_aggr_vfd_alloc(), which in turn calls H5MF_aggr_alloc().
- * This is problematic since (if I read the code correctly) it will
- * re-constitute the metadata aggregator, which will add any leftover
- * space to one of the free space managers when freed.
- *
- * This is a non-starter, since the entire objective is to settle the
- * free space managers.
- *
- * Hence the decision to call H5FD_alloc() directly.
- *
- * As discussed in PROBLEM above, if f->shared->alignment is not 1,
- * this has the possibility of generating a fragment of file space
- * that would typically be inserted into one of the free space managers.
- *
- * This is isn't good, but due to schedule pressure, we will just drop
- * the fragment on the floor for now.
- */
- if(sm_hdr_fspace)
- if(H5FS_vfd_alloc_hdr_and_section_info_if_needed(f, sm_hdr_fspace, &(f->shared->fs_addr[sm_fshdr_fs_type])) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't vfd allocate sm hdr FSM file space")
+ do {
+ continue_alloc_fsm = FALSE;
+ if(sm_hdr_fspace)
+ if(H5FS_vfd_alloc_hdr_and_section_info_if_needed(f, sm_hdr_fspace, &(f->shared->fs_addr[sm_fshdr_fs_type])) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't vfd allocate sm hdr FSM file space")
+
+ if(sm_sinfo_fspace && (sm_sinfo_fspace != sm_hdr_fspace))
+ if(H5FS_vfd_alloc_hdr_and_section_info_if_needed(f, sm_sinfo_fspace, &(f->shared->fs_addr[sm_fssinfo_fs_type])) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't vfd allocate sm sinfo FSM file space")
+
+ if(H5F_PAGED_AGGR(f)) {
+ if(lg_hdr_fspace)
+ if(H5FS_vfd_alloc_hdr_and_section_info_if_needed(f, lg_hdr_fspace, &(f->shared->fs_addr[lg_fshdr_fs_type])) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't vfd allocate lg hdr FSM file space")
+
+ if(lg_sinfo_fspace && (lg_sinfo_fspace != lg_hdr_fspace))
+ if(H5FS_vfd_alloc_hdr_and_section_info_if_needed(f, lg_sinfo_fspace, &(f->shared->fs_addr[lg_fssinfo_fs_type])) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't vfd allocate lg sinfo FSM file space")
+ } /* end if */
- if(sm_sinfo_fspace && (sm_sinfo_fspace != sm_hdr_fspace))
- if(H5FS_vfd_alloc_hdr_and_section_info_if_needed(f, sm_sinfo_fspace, &(f->shared->fs_addr[sm_fssinfo_fs_type])) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't vfd allocate sm sinfo FSM file space")
+ sm_hdr_fspace = f->shared->fs_man[sm_fshdr_fs_type];
+ sm_sinfo_fspace = f->shared->fs_man[sm_fssinfo_fs_type];
+ if(H5F_PAGED_AGGR(f)) {
+ lg_hdr_fspace = f->shared->fs_man[lg_fshdr_fs_type];
+ lg_sinfo_fspace = f->shared->fs_man[lg_fssinfo_fs_type];
+ }
- if(H5F_PAGED_AGGR(f)) {
- if(lg_hdr_fspace)
- if(H5FS_vfd_alloc_hdr_and_section_info_if_needed(f, lg_hdr_fspace, &(f->shared->fs_addr[lg_fshdr_fs_type])) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't vfd allocate lg hdr FSM file space")
+ if(H5MF__continue_alloc_fsm(f->shared, sm_hdr_fspace, sm_sinfo_fspace, lg_hdr_fspace, lg_sinfo_fspace, &continue_alloc_fsm) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't vfd allocate lg sinfo FSM file space")
+ } while(continue_alloc_fsm);
- if(lg_sinfo_fspace && (lg_sinfo_fspace != lg_hdr_fspace))
- if(H5FS_vfd_alloc_hdr_and_section_info_if_needed(f, lg_sinfo_fspace, &(f->shared->fs_addr[lg_fssinfo_fs_type])) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't vfd allocate lg sinfo FSM file space")
- } /* end if */
+ /* All free space managers should have file space allocated for them
+ * now, and should see no further allocations / deallocations.
+ * For backward compatibility, store the eoa in f->shared->eoa_fsm_fsalloc
+ * which will be set to fsinfo.eoa_pre_fsm_fsalloc when we actually write
+ * the free-space info message to the superblock extension.
+ * This will allow the 1.10 library with the hack to open the file with
+ * the new solution.
+ */
/* Get the eoa after allocation of file space for the self referential
- * free space managers. Assuming no cache image, this should be the
+ * free space managers. Assuming no cache image, this should be the
* final EOA of the file.
*/
- if(HADDR_UNDEF == (eoa_post_fsm_fsalloc = H5FD_get_eoa(f->shared->lf, H5FD_MEM_DEFAULT)))
+ if(HADDR_UNDEF == (eoa_fsm_fsalloc = H5FD_get_eoa(f->shared->lf, H5FD_MEM_DEFAULT)))
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get file size")
-
- /* All free space managers should have file space allocated for them
- * now, and should see no further allocations / deallocations. Store
- * the pre and post file space allocation for self referential FSMs EOA
- * for use when we actually write the free space manager superblock
- * extension message.
- */
- f->shared->eoa_pre_fsm_fsalloc = eoa_pre_fsm_fsalloc;
- f->shared->eoa_post_fsm_fsalloc = eoa_post_fsm_fsalloc;
+ f->shared->eoa_fsm_fsalloc = eoa_fsm_fsalloc;
/* Indicate that the FSM was settled successfully */
*fsm_settled = TRUE;
} /* end if */
+
done:
/* Reset the ring in the API context */
if(orig_ring != H5AC_RING_INV)
@@ -3404,6 +3406,58 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5MF__continue_alloc_fsm
+ *
+ * Purpose: To determine whether any of the input FSMs has allocated
+ * its "addr" and "sect_addr".
+ * Return TRUE or FALSE in *continue_alloc_fsm.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Vailin Choi
+ * 6/24/2019
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5MF__continue_alloc_fsm(H5F_shared_t *f_sh, H5FS_t *sm_hdr_fspace, H5FS_t *sm_sinfo_fspace,
+ H5FS_t *lg_hdr_fspace, H5FS_t *lg_sinfo_fspace, hbool_t *continue_alloc_fsm)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ /* Sanity checks */
+ HDassert(f_sh);
+ HDassert(continue_alloc_fsm);
+
+ /* Check sm_hdr_fspace */
+ if(sm_hdr_fspace && sm_hdr_fspace->serial_sect_count > 0 && sm_hdr_fspace->sinfo) {
+ H5MF_CHECK_FSM(sm_hdr_fspace, continue_alloc_fsm);
+ } /* end if */
+
+ if(!(*continue_alloc_fsm))
+ if(sm_sinfo_fspace && sm_sinfo_fspace != sm_hdr_fspace &&
+ sm_sinfo_fspace->serial_sect_count > 0 && sm_sinfo_fspace->sinfo) {
+ H5MF_CHECK_FSM(sm_hdr_fspace, continue_alloc_fsm);
+ } /* end if */
+
+ if(H5F_SHARED_PAGED_AGGR(f_sh) && !(*continue_alloc_fsm)) {
+ /* Check lg_hdr_fspace */
+ if(lg_hdr_fspace && lg_hdr_fspace->serial_sect_count > 0 && lg_hdr_fspace->sinfo) {
+ H5MF_CHECK_FSM(lg_hdr_fspace, continue_alloc_fsm);
+ } /* end if */
+
+ /* Check lg_sinfo_fspace */
+ if(!(*continue_alloc_fsm))
+ if(lg_sinfo_fspace && lg_sinfo_fspace != lg_hdr_fspace &&
+ lg_sinfo_fspace->serial_sect_count > 0 && lg_sinfo_fspace->sinfo) {
+ H5MF_CHECK_FSM(lg_sinfo_fspace, continue_alloc_fsm);
+ } /* end if */
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5MF__continue_alloc_fsm() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5MF__fsm_type_is_self_referential()
*
* Purpose: Return TRUE if the indicated free space manager allocates
@@ -3416,8 +3470,8 @@ done:
*
*-------------------------------------------------------------------------
*/
-hbool_t
-H5MF__fsm_type_is_self_referential(H5F_t *f, H5F_mem_page_t fsm_type)
+static hbool_t
+H5MF__fsm_type_is_self_referential(H5F_shared_t *f_sh, H5F_mem_page_t fsm_type)
{
H5F_mem_page_t sm_fshdr_fsm;
H5F_mem_page_t sm_fssinfo_fsm;
@@ -3425,26 +3479,25 @@ H5MF__fsm_type_is_self_referential(H5F_t *f, H5F_mem_page_t fsm_type)
H5F_mem_page_t lg_fssinfo_fsm;
hbool_t result = FALSE;
- FUNC_ENTER_PACKAGE_NOERR
+ FUNC_ENTER_STATIC_NOERR
/* Sanity check */
- HDassert(f);
- HDassert(f->shared);
+ HDassert(f_sh);
HDassert(fsm_type >= H5F_MEM_PAGE_DEFAULT);
HDassert(fsm_type < H5F_MEM_PAGE_NTYPES);
- H5MF__alloc_to_fs_type(f, H5FD_MEM_FSPACE_HDR, (size_t)1, &sm_fshdr_fsm);
- H5MF__alloc_to_fs_type(f, H5FD_MEM_FSPACE_SINFO, (size_t)1, &sm_fssinfo_fsm);
+ H5MF__alloc_to_fs_type(f_sh, H5FD_MEM_FSPACE_HDR, (size_t)1, &sm_fshdr_fsm);
+ H5MF__alloc_to_fs_type(f_sh, H5FD_MEM_FSPACE_SINFO, (size_t)1, &sm_fssinfo_fsm);
- if(H5F_PAGED_AGGR(f)) {
- H5MF__alloc_to_fs_type(f, H5FD_MEM_FSPACE_HDR, f->shared->fs_page_size + 1, &lg_fshdr_fsm);
- H5MF__alloc_to_fs_type(f, H5FD_MEM_FSPACE_SINFO, f->shared->fs_page_size + 1, &lg_fssinfo_fsm);
+ if(H5F_SHARED_PAGED_AGGR(f_sh)) {
+ H5MF__alloc_to_fs_type(f_sh, H5FD_MEM_FSPACE_HDR, f_sh->fs_page_size + 1, &lg_fshdr_fsm);
+ H5MF__alloc_to_fs_type(f_sh, H5FD_MEM_FSPACE_SINFO, f_sh->fs_page_size + 1, &lg_fssinfo_fsm);
result = (fsm_type == sm_fshdr_fsm) || (fsm_type == sm_fssinfo_fsm)
|| (fsm_type == lg_fshdr_fsm) || (fsm_type == lg_fssinfo_fsm);
} /* end if */
else {
- /* In principle, fsm_type should always be less than
+ /* In principle, fsm_type should always be less than
* H5F_MEM_PAGE_LARGE_SUPER whenever paged aggregation
* is not enabled. However, since there is code that does
* not observe this principle, force the result to FALSE if
@@ -3474,7 +3527,7 @@ H5MF__fsm_type_is_self_referential(H5F_t *f, H5F_mem_page_t fsm_type)
*-------------------------------------------------------------------------
*/
static hbool_t
-H5MF__fsm_is_self_referential(H5F_t *f, H5FS_t *fspace)
+H5MF__fsm_is_self_referential(H5F_shared_t *f_sh, H5FS_t *fspace)
{
H5F_mem_page_t sm_fshdr_fsm;
H5F_mem_page_t sm_fssinfo_fsm;
@@ -3483,347 +3536,27 @@ H5MF__fsm_is_self_referential(H5F_t *f, H5FS_t *fspace)
FUNC_ENTER_STATIC_NOERR
/* Sanity check */
- HDassert(f);
- HDassert(f->shared);
+ HDassert(f_sh);
HDassert(fspace);
- H5MF__alloc_to_fs_type(f, H5FD_MEM_FSPACE_HDR, (size_t)1, &sm_fshdr_fsm);
- H5MF__alloc_to_fs_type(f, H5FD_MEM_FSPACE_SINFO, (size_t)1, &sm_fssinfo_fsm);
+ H5MF__alloc_to_fs_type(f_sh, H5FD_MEM_FSPACE_HDR, (size_t)1, &sm_fshdr_fsm);
+ H5MF__alloc_to_fs_type(f_sh, H5FD_MEM_FSPACE_SINFO, (size_t)1, &sm_fssinfo_fsm);
- if(H5F_PAGED_AGGR(f)) {
+ if(H5F_SHARED_PAGED_AGGR(f_sh)) {
H5F_mem_page_t lg_fshdr_fsm;
H5F_mem_page_t lg_fssinfo_fsm;
- H5MF__alloc_to_fs_type(f, H5FD_MEM_FSPACE_HDR, f->shared->fs_page_size + 1, &lg_fshdr_fsm);
- H5MF__alloc_to_fs_type(f, H5FD_MEM_FSPACE_SINFO, f->shared->fs_page_size + 1, &lg_fssinfo_fsm);
+ H5MF__alloc_to_fs_type(f_sh, H5FD_MEM_FSPACE_HDR, f_sh->fs_page_size + 1, &lg_fshdr_fsm);
+ H5MF__alloc_to_fs_type(f_sh, H5FD_MEM_FSPACE_SINFO, f_sh->fs_page_size + 1, &lg_fssinfo_fsm);
- result = (fspace == f->shared->fs_man[sm_fshdr_fsm]) ||
- (fspace == f->shared->fs_man[sm_fssinfo_fsm]) ||
- (fspace == f->shared->fs_man[lg_fshdr_fsm]) ||
- (fspace == f->shared->fs_man[lg_fssinfo_fsm]);
+ result = (fspace == f_sh->fs_man[sm_fshdr_fsm]) ||
+ (fspace == f_sh->fs_man[sm_fssinfo_fsm]) ||
+ (fspace == f_sh->fs_man[lg_fshdr_fsm]) ||
+ (fspace == f_sh->fs_man[lg_fssinfo_fsm]);
} /* end if */
else
- result = (fspace == f->shared->fs_man[sm_fshdr_fsm]) ||
- (fspace == f->shared->fs_man[sm_fssinfo_fsm]);
+ result = (fspace == f_sh->fs_man[sm_fshdr_fsm]) ||
+ (fspace == f_sh->fs_man[sm_fssinfo_fsm]);
FUNC_LEAVE_NOAPI(result)
} /* H5MF__fsm_is_self_referential() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5MF_tidy_self_referential_fsm_hack
- *
- * Purpose: As discussed in the comments of the settle routines above,
- * the existence of self referential free space managers
- * as currently implemented creates the possibility of
- * infinite loops at file close.
- *
- * As a hack to avoid this, we have added code to settle
- * self referential free space managers, and then allocate
- * space for them directly from the file driver.
- *
- * To avoid dropping ever increasing amounts of file space
- * on the floor with each subsequent file close/open cycle,
- * we need to clean this up on file open. To avoid this,
- * this function is called on the first file space allocation
- * or deallocation after file open to float the self referential
- * free space managers and reduce the EOA to the value it
- * had before the direct allocation of space for the self
- * referential free space managers.
- *
- * The function proceeds as follows:
- *
- * 1) Verify that f->shared->first_alloc_dealloc is TRUE,
- * and then set it to FALSE.
- *
- * 2) Get the current EOA. Verify that it is greater than
- * or equal to f->shared->eoa_pre_fsm_fsalloc. If the
- * current eoa is equal to f->shared->eoa_pre_fsm_fsalloc,
- * no self referential FSMs were stored, and we are done.
- *
- * NOTE: This will have to be reworked somewhat for
- * cache image.
- *
- * 3) Load the self referential FSMs. In passing verify that
- * the lowest address of a FSM header is equal to
- * f->shared->eoa_pre_fsm_fsalloc.
- *
- * Note that we don't have to use any special I/O for
- * this -- we can use the regular I/O methods even if
- * paged aggregation and page buffering is enabled.
- *
- * 4) Float the FSMs. Ensure that the file space is NOT
- * released.
- *
- * 5) Set EOA equal to f->shared->eoa_pre_fsm_fsalloc,
- * and then set f->shared->eoa_pre_fsm_fsalloc to
- * HADDR_UNDEF.
- *
- * If page buffering, verify that the new EOA is
- * on a page boundary, and expunge any pages in the
- * page buffer after the new EOA.
- *
- * Note that this function is also called from test code
- * when it is necessary to startup a self referential
- * free space manager prior to the first file space
- * allocation / deallocation. Failure to do so will
- * result in assertion failures in this function on
- * the first file space allocation / deallocation.
- *
- * Return: SUCCEED/FAIL
- *
- * Programmer: John Mainzer
- * 12/11/16
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5MF_tidy_self_referential_fsm_hack(H5F_t *f)
-{
- haddr_t eoa; /* EOA of file */
- hsize_t tail_size = 0; /* Size of chunk to free */
- H5AC_ring_t orig_ring = H5AC_RING_INV; /* Original ring value */
- haddr_t first_srfsm_hdr = HADDR_UNDEF; /* Addr of first self referential */
- /* fsm header in file */
- H5FS_stat_t fs_stat; /* Information for hdr FSM */
- H5F_mem_page_t sm_fshdr_fs_type; /* Small fs hdr fsm */
- H5F_mem_page_t sm_fssinfo_fs_type; /* Small fs sinfo fsm */
- H5F_mem_page_t lg_fshdr_fs_type; /* Large fs hdr fsm */
- H5F_mem_page_t lg_fssinfo_fs_type; /* Large fs sinfo fsm */
- H5PB_t *saved_pb_ptr = NULL; /* Pointer to page buffer */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_TAG(H5AC__FREESPACE_TAG, FAIL)
-
- /* check args */
- HDassert(f);
- HDassert(f->shared);
- HDassert(f->shared->fs_persist);
- HDassert(f->shared->first_alloc_dealloc);
-
- /* Set the ring type in the API context. Since we are only dealing with
- * self referential FSMs, we will only need H5AC_RING_MDFSM.
- */
- H5AC_set_ring(H5AC_RING_MDFSM, &orig_ring);
-
- /* 1) Verify that f->shared->first_alloc_dealloc is TRUE,
- * and then set it to FALSE.
- */
- HDassert(f->shared->first_alloc_dealloc);
- f->shared->first_alloc_dealloc = FALSE;
-
-
- /* 2) Get the current EOA. Verify that it is greater than
- * or equal to f->shared->eoa_pre_fsm_fsalloc. If the
- * current eoa is equal to f->shared->eoa_pre_fsm_fsalloc,
- * no self referential FSMs were stored, and we are done.
- *
- * NOTE: This will have to be reworked somewhat for
- * cache image.
- */
- if(HADDR_UNDEF == (eoa = H5FD_get_eoa(f->shared->lf, H5FD_MEM_DEFAULT)))
- HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get EOA")
- HDassert(H5F_addr_le(f->shared->eoa_pre_fsm_fsalloc, eoa));
-
- if(H5F_addr_eq(f->shared->eoa_pre_fsm_fsalloc, eoa))
- HGOTO_DONE(SUCCEED)
-
-
- /* 3) Load the self referential FSMs. In passing verify that
- * the lowest address of a FSM header is equal to
- * f->shared->eoa_pre_fsm_fsalloc.'
- *
- * Note that we don't have to use any special I/O for
- * this -- we can use the regular I/O methods even if
- * paged aggregation and page buffering is enabled.
- */
- H5MF__alloc_to_fs_type(f, H5FD_MEM_FSPACE_HDR, (size_t)1, &sm_fshdr_fs_type);
- H5MF__alloc_to_fs_type(f, H5FD_MEM_FSPACE_SINFO, (size_t)1, &sm_fssinfo_fs_type);
- HDassert(sm_fshdr_fs_type > H5F_MEM_PAGE_DEFAULT);
- HDassert(sm_fshdr_fs_type < H5F_MEM_PAGE_LARGE_SUPER);
-
- HDassert(sm_fssinfo_fs_type > H5F_MEM_PAGE_DEFAULT);
- HDassert(sm_fssinfo_fs_type < H5F_MEM_PAGE_LARGE_SUPER);
-
- HDassert(NULL == f->shared->fs_man[sm_fshdr_fs_type]);
- HDassert(NULL == f->shared->fs_man[sm_fssinfo_fs_type]);
-
- /* Disable page buffering when paged aggregation strategy with
- * persistent FS and page buffering are used.
- * This is in response to an assertion failure in H5PB.c when
- * running test/fheap.c.
- * This is due to header/section info got loaded into the page buffer
- * when freeing them via H5FS_free() called in this routine.
- */
- if(H5F_PAGED_AGGR(f) && f->shared->pb_ptr) {
- saved_pb_ptr = f->shared->pb_ptr;
- f->shared->pb_ptr = NULL;
- }
-
- if(H5F_addr_defined(f->shared->fs_addr[sm_fshdr_fs_type])) {
- first_srfsm_hdr = f->shared->fs_addr[sm_fshdr_fs_type];
-
- /* open the FSM */
- if(H5MF__open_fstype(f, sm_fshdr_fs_type) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize file free space manager")
-
- HDassert(f->shared->fs_man[sm_fshdr_fs_type]);
- } /* end if */
-
- if((sm_fshdr_fs_type != sm_fssinfo_fs_type) &&
- (H5F_addr_defined(f->shared->fs_addr[sm_fssinfo_fs_type]))) {
-
- if(!H5F_addr_defined(first_srfsm_hdr) ||
- (H5F_addr_defined(first_srfsm_hdr) &&
- H5F_addr_lt(f->shared->fs_addr[sm_fssinfo_fs_type], first_srfsm_hdr)))
- first_srfsm_hdr = f->shared->fs_addr[sm_fssinfo_fs_type];
-
- HDassert(NULL == f->shared->fs_man[sm_fssinfo_fs_type]);
-
- /* open the FSM */
- if(H5MF__open_fstype(f, sm_fssinfo_fs_type) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize file free space manager")
-
- HDassert(f->shared->fs_man[sm_fssinfo_fs_type]);
- } /* end if */
-
- if(H5F_PAGED_AGGR(f)) {
- H5MF__alloc_to_fs_type(f, H5FD_MEM_FSPACE_HDR, f->shared->fs_page_size + 1, &lg_fshdr_fs_type);
- H5MF__alloc_to_fs_type(f, H5FD_MEM_FSPACE_SINFO, f->shared->fs_page_size + 1, &lg_fssinfo_fs_type);
-
- HDassert(lg_fshdr_fs_type >= H5F_MEM_PAGE_LARGE_SUPER);
- HDassert(lg_fshdr_fs_type < H5F_MEM_PAGE_NTYPES);
-
- HDassert(lg_fssinfo_fs_type >= H5F_MEM_PAGE_LARGE_SUPER);
- HDassert(lg_fssinfo_fs_type < H5F_MEM_PAGE_NTYPES);
-
- HDassert(NULL == f->shared->fs_man[lg_fshdr_fs_type]);
- HDassert(NULL == f->shared->fs_man[lg_fssinfo_fs_type]);
-
- if(H5F_addr_defined(f->shared->fs_addr[lg_fshdr_fs_type])) {
- if(!H5F_addr_defined(first_srfsm_hdr) ||
- (H5F_addr_defined(first_srfsm_hdr) &&
- H5F_addr_lt(f->shared->fs_addr[lg_fshdr_fs_type], first_srfsm_hdr)))
- first_srfsm_hdr = f->shared->fs_addr[lg_fshdr_fs_type];
-
- HDassert(NULL == f->shared->fs_man[lg_fshdr_fs_type]);
-
- /* open the FSM */
- if(H5MF__open_fstype(f, lg_fshdr_fs_type) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize file free space manager")
- HDassert(f->shared->fs_man[lg_fshdr_fs_type]);
- } /* end if */
-
- if(lg_fshdr_fs_type != lg_fssinfo_fs_type && H5F_addr_defined(f->shared->fs_addr[lg_fssinfo_fs_type])) {
- if(!H5F_addr_defined(first_srfsm_hdr) ||
- (H5F_addr_defined(first_srfsm_hdr) &&
- H5F_addr_lt(f->shared->fs_addr[lg_fssinfo_fs_type], first_srfsm_hdr)))
- first_srfsm_hdr = f->shared->fs_addr[lg_fssinfo_fs_type];
-
- HDassert(NULL == f->shared->fs_man[lg_fssinfo_fs_type]);
-
- /* open the FSM */
- if(H5MF__open_fstype(f, lg_fssinfo_fs_type) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize file free space manager")
- HDassert(f->shared->fs_man[lg_fssinfo_fs_type]);
- } /* end if */
- } /* end if */
- HDassert(H5F_addr_eq(first_srfsm_hdr, f->shared->eoa_pre_fsm_fsalloc));
-
- /* 4) Float the FSMs. Ensure that the file space is NOT released. */
- if(f->shared->fs_man[sm_fshdr_fs_type]) {
- /* Sanity check: Query free space manager info for this type */
- if(H5FS_stat_info(f, f->shared->fs_man[sm_fshdr_fs_type], &fs_stat) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't get free-space info")
-
- HDassert(H5F_addr_defined(fs_stat.addr));
- HDassert(H5F_addr_defined(fs_stat.sect_addr));
- if(H5FS_free(f, f->shared->fs_man[sm_fshdr_fs_type], FALSE) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't release free-space headers")
- f->shared->fs_addr[sm_fshdr_fs_type] = HADDR_UNDEF;
- } /* end if */
-
- if(sm_fshdr_fs_type != sm_fssinfo_fs_type && f->shared->fs_man[sm_fssinfo_fs_type]) {
- /* Sanity check: Query free space manager info for this type */
- if(H5FS_stat_info(f, f->shared->fs_man[sm_fssinfo_fs_type], &fs_stat) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't get free-space info")
-
- HDassert(H5F_addr_defined(fs_stat.addr));
- HDassert(H5F_addr_defined(fs_stat.sect_addr));
- if(H5FS_free(f, f->shared->fs_man[sm_fssinfo_fs_type], FALSE) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't release free-space headers")
- f->shared->fs_addr[sm_fssinfo_fs_type] = HADDR_UNDEF;
- } /* end if */
-
- if(H5F_PAGED_AGGR(f)) {
- if(f->shared->fs_man[lg_fshdr_fs_type]) {
- /* Sanity check: Query free space manager info for this type */
- if(H5FS_stat_info(f, f->shared->fs_man[lg_fshdr_fs_type], &fs_stat) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "can't get free-space info")
-
- HDassert(H5F_addr_defined(fs_stat.addr));
- HDassert(H5F_addr_defined(fs_stat.sect_addr));
- if(H5FS_free(f, f->shared->fs_man[lg_fshdr_fs_type], FALSE) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't float free-space headers")
- f->shared->fs_addr[lg_fshdr_fs_type] = HADDR_UNDEF;
- } /* end if */
-
- if(lg_fshdr_fs_type != lg_fssinfo_fs_type && f->shared->fs_man[lg_fssinfo_fs_type]) {
- /* Sanity check: Query free space manager info for this type */
- if(H5FS_stat_info(f, f->shared->fs_man[lg_fssinfo_fs_type], &fs_stat) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "can't get free-space info")
-
- HDassert(H5F_addr_defined(fs_stat.addr));
- HDassert(H5F_addr_defined(fs_stat.sect_addr));
- if(H5FS_free(f, f->shared->fs_man[lg_fssinfo_fs_type], FALSE) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't float free-space headers")
- f->shared->fs_addr[lg_fssinfo_fs_type] = HADDR_UNDEF;
- } /* end if */
- } /* end if */
-
- /* 5) Set EOA equal to f->shared->eoa_pre_fsm_fsalloc,
- * and then set f->shared->eoa_pre_fsm_fsalloc to
- * HADDR_UNDEF.
- *
- * If page buffering, verify that the new EOA is
- * on a page boundary, and expunge any pages in the
- * page buffer after the new EOA.
- */
- if(!H5F_PAGED_AGGR(f)) {
- /* Verify that the aggregators are still shutdown. */
- HDassert(f->shared->sdata_aggr.tot_size == 0);
- HDassert(f->shared->sdata_aggr.addr == 0);
- HDassert(f->shared->sdata_aggr.size == 0);
-
- HDassert(f->shared->meta_aggr.tot_size == 0);
- HDassert(f->shared->meta_aggr.addr == 0);
- HDassert(f->shared->meta_aggr.size == 0);
- } /* end if */
-
- tail_size = (hsize_t)(eoa - f->shared->eoa_pre_fsm_fsalloc);
-
- /* Release file space allocated to self referential FSMs */
- if(H5F__free(f, H5FD_MEM_DEFAULT, f->shared->eoa_pre_fsm_fsalloc, tail_size) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "driver free request failed")
- if(HADDR_UNDEF == (eoa = H5FD_get_eoa(f->shared->lf, H5FD_MEM_DEFAULT)))
- HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get EOA")
- HDassert(H5F_addr_eq(f->shared->eoa_pre_fsm_fsalloc, eoa));
-
- f->shared->eoa_pre_fsm_fsalloc = HADDR_UNDEF;
-
- HDassert((!H5F_PAGED_AGGR(f)) || (0 == (eoa % f->shared->fs_page_size)));
-
-done:
- /* Enable page buffering as needed */
- if(H5F_PAGED_AGGR(f) && saved_pb_ptr) {
- HDassert(f->shared->pb_ptr == NULL);
- f->shared->pb_ptr = saved_pb_ptr;
- }
-
- /* Reset the ring in the API context */
- if(orig_ring != H5AC_RING_INV)
- H5AC_set_ring(orig_ring, NULL);
-
- FUNC_LEAVE_NOAPI_TAG(ret_value)
-} /* H5MF_tidy_self_referential_fsm_hack() */
-
diff --git a/src/H5MFaggr.c b/src/H5MFaggr.c
index 3db7f73..d716ae2 100644
--- a/src/H5MFaggr.c
+++ b/src/H5MFaggr.c
@@ -183,7 +183,21 @@ HDfprintf(stderr, "%s: type = %u, size = %Hu\n", FUNC, (unsigned)type, size);
* allocate "generic" space and sub-allocate out of that, if possible.
* Otherwise just allocate through H5F__alloc().
*/
- if((f->shared->feature_flags & aggr->feature_flag) && f->shared->fs_strategy != H5F_FSPACE_STRATEGY_NONE) {
+
+ /*
+ * Replace the following line with the line in #ifdef REPLACE/#endif.
+ * The line in #ifdef REPLACE triggers the following problem:
+ * test/objcopy.c: test_copy_group_deep() test fails with the family driver
+ *
+ * When closing the destination file after H5Ocopy, the library flushes the fractal
+ * heap direct block via H5HF__cache_dblock_pre_serialize(). While doing so,
+ * the cache eventually adjusts/evicts ageout entries and ends up flushing out the
+ * same entry that is being serialized (flush_in_progress).
+ */
+ if((f->shared->feature_flags & aggr->feature_flag) && f->shared->fs_strategy != H5F_FSPACE_STRATEGY_NONE && (!f->shared->closing || !f->shared->fs_persist)) {
+#ifdef REPLACE
+ if((f->shared->feature_flags & aggr->feature_flag) && f->shared->fs_strategy != H5F_FSPACE_STRATEGY_NONE && !f->shared->closing) {
+#endif
haddr_t aggr_frag_addr = HADDR_UNDEF; /* Address of aggregrator fragment */
hsize_t aggr_frag_size = 0; /* Size of aggregator fragment */
hsize_t alignment; /* Alignment of this section */
diff --git a/src/H5MFdbg.c b/src/H5MFdbg.c
index eedb72e..e11476b 100644
--- a/src/H5MFdbg.c
+++ b/src/H5MFdbg.c
@@ -215,14 +215,14 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5MF_sects_dump(H5F_t *f, FILE *stream)
+H5MF__sects_dump(H5F_t *f, FILE *stream)
{
haddr_t eoa; /* End of allocated space in the file */
int indent = 0; /* Amount to indent */
int fwidth = 50; /* Field width */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_PACKAGE_TAG(H5AC__FREESPACE_TAG, FAIL)
+ FUNC_ENTER_PACKAGE_TAG(H5AC__FREESPACE_TAG)
#ifdef H5MF_ALLOC_DEBUG
HDfprintf(stderr, "%s: Dumping file free space sections\n", FUNC);
#endif /* H5MF_ALLOC_DEBUG */
@@ -261,7 +261,7 @@ HDfprintf(stderr, "%s: for type = H5FD_MEM_DEFAULT, eoa = %a\n", FUNC, eoa);
udata.fwidth = MAX(0, fwidth - 6);
/* Iterate over all the free space sections */
- if(H5FS_sect_iterate(f, f->shared->fs_man[ptype], H5MF_sects_debug_cb, &udata) < 0)
+ if(H5FS_sect_iterate(f, f->shared->fs_man[ptype], H5MF__sects_debug_cb, &udata) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_BADITER, FAIL, "can't iterate over heap's free space")
} /* end if */
else
@@ -314,7 +314,7 @@ HDfprintf(stderr, "%s: sda_addr = %a, sda_size = %Hu, end of sda = %a\n", FUNC,
udata.fwidth = MAX(0, fwidth - 6);
/* Iterate over all the free space sections */
- if(H5FS_sect_iterate(f, f->shared->fs_man[atype], H5MF_sects_debug_cb, &udata) < 0)
+ if(H5FS_sect_iterate(f, f->shared->fs_man[atype], H5MF__sects_debug_cb, &udata) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_BADITER, FAIL, "can't iterate over heap's free space")
} /* end if */
else /* No sections of this type */
diff --git a/src/H5MFpkg.h b/src/H5MFpkg.h
index ec4aab4..fc398db 100644
--- a/src/H5MFpkg.h
+++ b/src/H5MFpkg.h
@@ -55,11 +55,6 @@
#define H5MF_FSPACE_SECT_SMALL 1 /* For paged aggregation: "small" meta/raw data section which is < fsp_size) */
#define H5MF_FSPACE_SECT_LARGE 2 /* For paged aggregation: "large" Section which is >= fsp_size) */
-/* For non-paged aggregation: map allocation request type to tracked free-space type */
-/* F -- pointer to H5F_t; T -- H5FD_mem_t */
-#define H5MF_ALLOC_TO_FS_AGGR_TYPE(F, T) \
- ((H5FD_MEM_DEFAULT == (F)->shared->fs_type_map[T]) ? (T) : (F)->shared->fs_type_map[T])
-
/* Get section class type based on size */
#define H5MF_SECT_CLASS_TYPE(F, S) \
((H5F_PAGED_AGGR(F)) ? \
@@ -182,13 +177,10 @@ H5_DLLVAR H5FS_section_class_t H5MF_FSPACE_SECT_CLS_LARGE[1];
/* Allocator routines */
H5_DLL herr_t H5MF__open_fstype(H5F_t *f, H5F_mem_page_t type);
H5_DLL herr_t H5MF__start_fstype(H5F_t *f, H5F_mem_page_t type);
-
H5_DLL htri_t H5MF__find_sect(H5F_t *f, H5FD_mem_t alloc_type, hsize_t size, H5FS_t *fspace, haddr_t *addr);
H5_DLL herr_t H5MF__add_sect(H5F_t *f, H5FD_mem_t alloc_type, H5FS_t *fspace, H5MF_free_section_t *node);
-
-H5_DLL herr_t H5MF__sects_dump(H5F_t *f, FILE *stream);
-
-H5_DLL void H5MF__alloc_to_fs_type(H5F_t *f, H5FD_mem_t alloc_type, hsize_t size, H5F_mem_page_t *fs_type);
+H5_DLL void H5MF__alloc_to_fs_type(H5F_shared_t *f_sh, H5FD_mem_t alloc_type,
+ hsize_t size, H5F_mem_page_t *fs_type);
/* 'simple/small/large' section routines */
H5_DLL H5MF_free_section_t *H5MF__sect_new(unsigned ctype, haddr_t sect_off,
@@ -206,6 +198,11 @@ H5_DLL herr_t H5MF__aggr_absorb(const H5F_t *f, H5F_blk_aggr_t *aggr,
H5_DLL herr_t H5MF__aggr_query(const H5F_t *f, const H5F_blk_aggr_t *aggr,
haddr_t *addr, hsize_t *size);
+/* Debugging routines */
+#ifdef H5MF_ALLOC_DEBUG_DUMP
+H5_DLL herr_t H5MF__sects_dump(H5F_t *f, FILE *stream);
+#endif /* H5MF_ALLOC_DEBUG_DUMP */
+
/* Testing routines */
#ifdef H5MF_TESTING
#endif /* H5MF_TESTING */
diff --git a/src/H5MFprivate.h b/src/H5MFprivate.h
index bd57f05..de1bdfb 100644
--- a/src/H5MFprivate.h
+++ b/src/H5MFprivate.h
@@ -48,7 +48,7 @@
/***************************************/
/* File space manager routines */
-H5_DLL herr_t H5MF_init_merge_flags(H5F_t *f);
+H5_DLL herr_t H5MF_init_merge_flags(H5F_shared_t *f_sh);
H5_DLL herr_t H5MF_get_freespace(H5F_t *f, hsize_t *tot_space, hsize_t *meta_size);
H5_DLL herr_t H5MF_close(H5F_t *f);
H5_DLL herr_t H5MF_try_close(H5F_t *f);
diff --git a/src/H5MFsection.c b/src/H5MFsection.c
index f35ff21..ad1f074 100644
--- a/src/H5MFsection.c
+++ b/src/H5MFsection.c
@@ -774,9 +774,12 @@ H5MF__sect_small_merge(H5FS_section_info_t **_sect1, H5FS_section_info_t *_sect2
/* Need to free possible raw/metadata page in the page buffer.
* This is in response to the data corruption bug from test/fheap.c
* when page buffering + page aggregation strategy are used.
- * Note: Large raw/metadata page bypasses the page buffer */
+ * Note: Large raw/metadata page bypasses the page buffer.
+ * Note: Update of raw data page (large or small sized) is handled
+ * by the PB cache
+ */
if(udata->f->shared->pb_ptr != NULL)
- if(H5PB_remove_entry(udata->f, (*sect1)->sect_info.addr) < 0)
+ if(H5PB_remove_entry(udata->f->shared, (*sect1)->sect_info.addr) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "can't free merged section from page buffer")
if(H5MF__sect_free((H5FS_section_info_t *)(*sect1)) < 0)
@@ -819,12 +822,21 @@ H5MF__sect_large_can_merge(const H5FS_section_info_t *_sect1,
const H5MF_free_section_t *sect2 = (const H5MF_free_section_t *)_sect2; /* File free section */
htri_t ret_value = FALSE; /* Return value */
- FUNC_ENTER_STATIC_NOERR
+ FUNC_ENTER_STATIC
/* Check arguments. */
HDassert(sect1);
HDassert(sect2);
HDassert(sect1->sect_info.type == sect2->sect_info.type); /* Checks "MERGE_SYM" flag */
+ if (!H5F_addr_lt(sect1->sect_info.addr, sect2->sect_info.addr)) {
+ fprintf(stderr, "%s.%d: sect1->sect_info.addr %" PRIuHADDR
+ ", sect2->sect_info.addr %" PRIuHADDR "\n", __func__, __LINE__,
+ sect1->sect_info.addr, sect2->sect_info.addr);
+ fprintf(stderr, "%s.%d: sect1->sect_info.size %" PRIuHSIZE
+ ", sect2->sect_info.size %" PRIuHSIZE "\n", __func__, __LINE__,
+ sect1->sect_info.size, sect2->sect_info.size);
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't merge")
+ }
HDassert(H5F_addr_lt(sect1->sect_info.addr, sect2->sect_info.addr));
ret_value = H5F_addr_eq(sect1->sect_info.addr + sect1->sect_info.size, sect2->sect_info.addr);
@@ -833,6 +845,7 @@ H5MF__sect_large_can_merge(const H5FS_section_info_t *_sect1,
HDfprintf(stderr, "%s: Leaving: ret_value = %t\n", FUNC, ret_value);
#endif /* H5MF_ALLOC_DEBUG_MORE */
+done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5MF__sect_large_can_merge() */
diff --git a/src/H5MM.c b/src/H5MM.c
index 866dfbe..ac3c26e 100644
--- a/src/H5MM.c
+++ b/src/H5MM.c
@@ -43,7 +43,7 @@
#define H5MM_SIG_SIZE 4
#define H5MM_HEAD_GUARD_SIZE 8
#define H5MM_TAIL_GUARD_SIZE 8
-#define H5MM_BLOCK_FROM_BUF(mem) ((H5MM_block_t *)((unsigned char *)mem - (offsetof(H5MM_block_t, b) + H5MM_HEAD_GUARD_SIZE)))
+#define H5MM_BLOCK_FROM_BUF(mem) ((H5MM_block_t *)((void *)((unsigned char *)mem - (offsetof(H5MM_block_t, b) + H5MM_HEAD_GUARD_SIZE))))
#endif /* H5_MEMORY_ALLOC_SANITY_CHECK */
@@ -154,7 +154,7 @@ H5MM__is_our_block(void *mem)
*
*-------------------------------------------------------------------------
*/
-H5_ATTR_PURE static void
+static void
H5MM__sanity_check_block(const H5MM_block_t *block)
{
HDassert(block->u.info.size > 0);
@@ -180,7 +180,7 @@ H5MM__sanity_check_block(const H5MM_block_t *block)
*
*-------------------------------------------------------------------------
*/
-H5_ATTR_PURE static void
+static void
H5MM__sanity_check(void *mem)
{
H5MM_block_t *block = H5MM_BLOCK_FROM_BUF(mem);
@@ -201,7 +201,7 @@ H5MM__sanity_check(void *mem)
*
*-------------------------------------------------------------------------
*/
-H5_ATTR_PURE void
+void
H5MM_sanity_check_all(void)
{
H5MM_block_t *curr = NULL;
@@ -226,7 +226,7 @@ H5MM_sanity_check_all(void)
*
*-------------------------------------------------------------------------
*/
-H5_ATTR_PURE void
+void
H5MM_final_sanity_check(void)
{
HDassert(0 == H5MM_curr_alloc_bytes_s);
@@ -274,7 +274,7 @@ H5MM_malloc(size_t size)
#if defined H5_MEMORY_ALLOC_SANITY_CHECK
/* Initialize block list head singleton */
if(!H5MM_init_s) {
- HDmemcpy(H5MM_block_head_s.sig, H5MM_block_signature_s, H5MM_SIG_SIZE);
+ H5MM_memcpy(H5MM_block_head_s.sig, H5MM_block_signature_s, H5MM_SIG_SIZE);
H5MM_block_head_s.next = &H5MM_block_head_s;
H5MM_block_head_s.prev = &H5MM_block_head_s;
H5MM_block_head_s.u.info.size = SIZET_MAX;
@@ -291,15 +291,15 @@ H5MM_malloc(size_t size)
if(NULL != (block = (H5MM_block_t *)HDmalloc(alloc_size))) {
/* Set up block */
- HDmemcpy(block->sig, H5MM_block_signature_s, H5MM_SIG_SIZE);
+ H5MM_memcpy(block->sig, H5MM_block_signature_s, H5MM_SIG_SIZE);
block->next = H5MM_block_head_s.next;
H5MM_block_head_s.next = block;
block->next->prev = block;
block->prev = &H5MM_block_head_s;
block->u.info.size = size;
block->u.info.in_use = TRUE;
- HDmemcpy(block->b, H5MM_block_head_guard_s, H5MM_HEAD_GUARD_SIZE);
- HDmemcpy(block->b + H5MM_HEAD_GUARD_SIZE + size, H5MM_block_tail_guard_s, H5MM_TAIL_GUARD_SIZE);
+ H5MM_memcpy(block->b, H5MM_block_head_guard_s, H5MM_HEAD_GUARD_SIZE);
+ H5MM_memcpy(block->b + H5MM_HEAD_GUARD_SIZE + size, H5MM_block_tail_guard_s, H5MM_TAIL_GUARD_SIZE);
/* Update statistics */
H5MM_total_alloc_bytes_s += size;
@@ -417,7 +417,7 @@ H5MM_realloc(void *mem, size_t size)
H5MM__sanity_check(mem);
ret_value = H5MM_malloc(size);
- HDmemcpy(ret_value, mem, MIN(size, old_size));
+ H5MM_memcpy(ret_value, mem, MIN(size, old_size));
H5MM_xfree(mem);
} /* end if */
else
@@ -564,3 +564,39 @@ H5MM_xfree(void *mem)
FUNC_LEAVE_NOAPI(NULL)
} /* end H5MM_xfree() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5MM_memcpy
+ *
+ * Purpose: Like memcpy(3) but with sanity checks on the parameters,
+ * particularly buffer overlap.
+ *
+ * Return: Success: pointer to dest
+ * Failure: NULL
+ *
+ * Programmer: Dana Robinson
+ * Spring 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5MM_memcpy(void *dest, const void *src, size_t n)
+{
+ void *ret = NULL;
+
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ HDassert(dest);
+ HDassert(src);
+
+ /* Check for buffer overlap */
+ HDassert((char *)dest >= (const char *)src + n || (const char *)src >= (char *)dest + n);
+
+ /* Copy */
+ ret = HDmemcpy(dest, src, n);
+
+ FUNC_LEAVE_NOAPI(ret)
+
+} /* end H5MM_memcpy() */
+
diff --git a/src/H5MMprivate.h b/src/H5MMprivate.h
index 0524601..2053215 100644
--- a/src/H5MMprivate.h
+++ b/src/H5MMprivate.h
@@ -45,6 +45,7 @@ H5_DLL void *H5MM_realloc(void *mem, size_t size);
H5_DLL char *H5MM_xstrdup(const char *s);
H5_DLL char *H5MM_strdup(const char *s);
H5_DLL void *H5MM_xfree(void *mem);
+H5_DLL void *H5MM_memcpy(void *dest, const void *src, size_t n);
#if defined H5_MEMORY_ALLOC_SANITY_CHECK
H5_DLL void H5MM_sanity_check_all(void);
H5_DLL void H5MM_final_sanity_check(void);
diff --git a/src/H5MP.c b/src/H5MP.c
index 8c9b411..7947e7d 100644
--- a/src/H5MP.c
+++ b/src/H5MP.c
@@ -44,7 +44,7 @@
/* First block in page */
#define H5MP_PAGE_FIRST_BLOCK(p) \
- (H5MP_page_blk_t *)((unsigned char *)(p) + H5MP_BLOCK_ALIGN(sizeof(H5MP_page_t)))
+ (H5MP_page_blk_t *)((void *)((unsigned char *)(p) + H5MP_BLOCK_ALIGN(sizeof(H5MP_page_t))))
/******************/
@@ -294,7 +294,7 @@ found:
H5MP_page_blk_t *new_free; /* New free block created */
/* Carve out new free block after block to allocate */
- new_free = (H5MP_page_blk_t *)(((unsigned char *)alloc_free) + needed);
+ new_free = (H5MP_page_blk_t *)((void *)(((unsigned char *)alloc_free) + needed));
/* Link into existing lists */
new_free->next = alloc_free->next;
@@ -361,7 +361,7 @@ H5MP_free(H5MP_pool_t *mp, void *spc)
HDassert(spc);
/* Get block header for space to free */
- spc_blk = (H5MP_page_blk_t *)(((unsigned char *)spc) - H5MP_BLOCK_ALIGN(sizeof(H5MP_page_blk_t)));
+ spc_blk = (H5MP_page_blk_t *)((void *)(((unsigned char *)spc) - H5MP_BLOCK_ALIGN(sizeof(H5MP_page_blk_t))));
/* Mark block as free */
HDassert(spc_blk->is_free == FALSE);
diff --git a/src/H5MPtest.c b/src/H5MPtest.c
index b3f2e24..0cba847 100644
--- a/src/H5MPtest.c
+++ b/src/H5MPtest.c
@@ -134,7 +134,7 @@ H5MP_pool_is_free_size_correct(const H5MP_pool_t *mp)
size_t page_free; /* Size of blocks on free list */
/* Iterate through the blocks in page, accumulating free space */
- blk = (H5MP_page_blk_t *)((unsigned char *)page + H5MP_BLOCK_ALIGN(sizeof(H5MP_page_t)));
+ blk = (H5MP_page_blk_t *)((void *)((unsigned char *)page + H5MP_BLOCK_ALIGN(sizeof(H5MP_page_t))));
page_free = 0;
while(blk != NULL) {
if(blk->is_free)
diff --git a/src/H5MV.c b/src/H5MV.c
index f31030b..e11d0d1 100644
--- a/src/H5MV.c
+++ b/src/H5MV.c
@@ -310,17 +310,17 @@ HDfprintf(stderr, "%s: size = %Hu\n", FUNC, size);
/* Start up the free-space manager if not so */
if(f->shared->fs_man_md == NULL) {
if(H5MV__create(f) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize free space manager")
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, HADDR_UNDEF, "can't initialize free space manager")
}
HDassert(f->shared->fs_man_md);
/* Create the free-space section for the fragment */
if(NULL == (node = H5MV__sect_new(eoa, frag_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize free space section")
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, HADDR_UNDEF, "can't initialize free space section")
/* Add the section */
if(H5FS_sect_add(f, f->shared->fs_man_md, (H5FS_section_info_t *)node, H5FS_ADD_RETURNED_SPACE, f) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINSERT, FAIL, "can't re-add section to file free space")
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINSERT, HADDR_UNDEF, "can't re-add section to file free space")
node = NULL;
}
diff --git a/src/H5HLpublic.h b/src/H5Mmodule.h
index 143bb78..00a586f 100644
--- a/src/H5HLpublic.h
+++ b/src/H5Mmodule.h
@@ -1,6 +1,5 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* 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 *
@@ -11,27 +10,22 @@
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-/*-------------------------------------------------------------------------
- *
- * Created: H5HLpublic.h
- * Jul 16 1997
- * Robb Matzke <matzke@llnl.gov>
- *
- * Purpose: Public declarations for the H5HL (local heap) package.
- *
- *-------------------------------------------------------------------------
+/*
+ * Purpose: This file contains declarations which define macros for the
+ * H5M package. Including this header means that the source file
+ * is part of the H5M package.
*/
-#ifndef _H5HLpublic_H
-#define _H5HLpublic_H
+#ifndef _H5Mmodule_H
+#define _H5Mmodule_H
-/* Public headers needed by this file */
-#include "H5public.h"
+/* Define the proper control macros for the generic FUNC_ENTER/LEAVE and error
+ * reporting macros.
+ */
+#define H5M_MODULE
+#define H5_MY_PKG H5M
+#define H5_MY_PKG_ERR H5E_MAP
+#define H5_MY_PKG_INIT YES
+
+#endif /* _H5Dmodule_H */
-#ifdef __cplusplus
-extern "C" {
-#endif
-#ifdef __cplusplus
-}
-#endif
-#endif
diff --git a/src/H5FSpublic.h b/src/H5Mpkg.h
index 3090d0d..86ff45c 100644
--- a/src/H5FSpublic.h
+++ b/src/H5Mpkg.h
@@ -11,42 +11,41 @@
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-/*-------------------------------------------------------------------------
- *
- * Created: H5FSpublic.h
- * May 2 2006
- * Quincey Koziol <koziol@hdfgroup.org>
- *
- * Purpose: Public declarations for the file free space package.
- *
- *-------------------------------------------------------------------------
+/*
+ * Purpose: This file contains declarations which are visible only within
+ * the H5M package. Source files outside the H5M package should
+ * include H5Mprivate.h instead.
*/
+#if !(defined H5M_FRIEND || defined H5M_MODULE)
+#error "Do not include this file outside the H5M package!"
+#endif
-#ifndef _H5FSpublic_H
-#define _H5FSpublic_H
+#ifndef _H5Mpkg_H
+#define _H5Mpkg_H
-/* Public headers needed by this file */
-#include "H5public.h"
+/* Get package's private header */
+#include "H5Mprivate.h"
-/*****************/
-/* Public Macros */
-/*****************/
+/* Other private headers needed by this file */
-/*******************/
-/* Public Typedefs */
-/*******************/
+/**************************/
+/* Package Private Macros */
+/**************************/
-/**********************************/
-/* Public API Function Prototypes */
-/**********************************/
-#ifdef __cplusplus
-extern "C" {
-#endif
+/****************************/
+/* Package Private Typedefs */
+/****************************/
-#ifdef __cplusplus
-}
-#endif
-#endif /* _H5FSpublic_H */
+/*****************************/
+/* Package Private Variables */
+/*****************************/
+
+
+/******************************/
+/* Package Private Prototypes */
+/******************************/
+
+#endif /*_H5Dpkg_H*/
diff --git a/src/H5Mprivate.h b/src/H5Mprivate.h
new file mode 100644
index 0000000..c841e75
--- /dev/null
+++ b/src/H5Mprivate.h
@@ -0,0 +1,80 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * This file contains private information about the H5M module
+ */
+#ifndef _H5Mprivate_H
+#define _H5Mprivate_H
+
+/* Include package's public header */
+#include "H5Mpublic.h"
+
+/* Private headers needed by this file */
+#include "H5FDprivate.h" /* File drivers */
+#include "H5Oprivate.h" /* Object headers */
+#include "H5Sprivate.h" /* Dataspaces */
+#include "H5Zprivate.h" /* Data filters */
+
+
+/**************************/
+/* Library Private Macros */
+/**************************/
+
+/*
+ * Feature: Define H5M_DEBUG on the compiler command line if you want to
+ * debug maps. NDEBUG must not be defined in order for this
+ * to have any effect.
+ */
+#ifdef NDEBUG
+# undef H5M_DEBUG
+#endif
+
+/* ======== Map creation property names ======== */
+
+/* ======== Map access property names ======== */
+#define H5M_ACS_KEY_PREFETCH_SIZE_NAME "key_prefetch_size" /* Number of keys to prefetch during map iteration */
+#define H5M_ACS_KEY_ALLOC_SIZE_NAME "key_alloc_size" /* Initial allocation size for keys prefetched during map iteration */
+
+/* Default temporary buffer size */
+#define H5D_TEMP_BUF_SIZE (1024 * 1024)
+
+/* Default I/O vector size */
+#define H5D_IO_VECTOR_SIZE 1024
+
+/* Default VL allocation & free info */
+#define H5D_VLEN_ALLOC NULL
+#define H5D_VLEN_ALLOC_INFO NULL
+#define H5D_VLEN_FREE NULL
+#define H5D_VLEN_FREE_INFO NULL
+
+/* Default virtual dataset list size */
+#define H5D_VIRTUAL_DEF_LIST_SIZE 8
+
+
+/****************************/
+/* Library Private Typedefs */
+/****************************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/******************************/
+/* Library Private Prototypes */
+/******************************/
+
+#endif /* _H5Mprivate_H */
+
diff --git a/src/H5Mpublic.h b/src/H5Mpublic.h
new file mode 100644
index 0000000..9cbdb32
--- /dev/null
+++ b/src/H5Mpublic.h
@@ -0,0 +1,126 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * This file contains public declarations for the H5M module.
+ *
+ * NOTE: This is an experimental API. Everything in the H5M package
+ * is subject to revision in a future release.
+ */
+#ifndef _H5Mpublic_H
+#define _H5Mpublic_H
+
+/* System headers needed by this file */
+
+/* Public headers needed by this file */
+#include "H5public.h"
+#include "H5Ipublic.h"
+
+
+/*****************/
+/* Public Macros */
+/*****************/
+
+/* Macros defining operation IDs for map VOL callbacks (implemented using the
+ * "optional" VOL callback) */
+#define H5VL_MAP_CREATE 1
+#define H5VL_MAP_OPEN 2
+#define H5VL_MAP_GET_VAL 3
+#define H5VL_MAP_EXISTS 4
+#define H5VL_MAP_PUT 5
+#define H5VL_MAP_GET 6
+#define H5VL_MAP_SPECIFIC 7
+#define H5VL_MAP_CLOSE 8
+
+
+/*******************/
+/* Public Typedefs */
+/*******************/
+
+/* types for map GET callback */
+typedef enum H5VL_map_get_t {
+ H5VL_MAP_GET_MAPL, /* map access property list */
+ H5VL_MAP_GET_MCPL, /* map creation property list */
+ H5VL_MAP_GET_KEY_TYPE, /* key type */
+ H5VL_MAP_GET_VAL_TYPE, /* value type */
+ H5VL_MAP_GET_COUNT /* key count */
+} H5VL_map_get_t;
+
+/* types for map SPECIFIC callback */
+typedef enum H5VL_map_specific_t {
+ H5VL_MAP_ITER, /* H5Miterate */
+ H5VL_MAP_DELETE /* H5Mdelete */
+} H5VL_map_specific_t;
+
+/* Callback for H5Miterate() */
+typedef herr_t (*H5M_iterate_t)(hid_t map_id, const void *key, void *op_data);
+
+
+/********************/
+/* Public Variables */
+/********************/
+
+
+/*********************/
+/* Public Prototypes */
+/*********************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* The map API is only built when requested since there's no support in
+ * the native file format at this time. It's only supported in a few VOL
+ * connectors.
+ */
+#ifdef H5_HAVE_MAP_API
+
+H5_DLL hid_t H5Mcreate(hid_t loc_id, const char *name, hid_t key_type_id,
+ hid_t val_type_id, hid_t lcpl_id, hid_t mcpl_id, hid_t mapl_id);
+H5_DLL hid_t H5Mcreate_anon(hid_t loc_id, hid_t key_type_id, hid_t val_type_id,
+ hid_t mcpl_id, hid_t mapl_id);
+H5_DLL hid_t H5Mopen(hid_t loc_id, const char *name, hid_t mapl_id);
+H5_DLL herr_t H5Mclose(hid_t map_id);
+H5_DLL hid_t H5Mget_key_type(hid_t map_id);
+H5_DLL hid_t H5Mget_val_type(hid_t map_id);
+H5_DLL hid_t H5Mget_create_plist(hid_t map_id);
+H5_DLL hid_t H5Mget_access_plist(hid_t map_id);
+H5_DLL herr_t H5Mget_count(hid_t map_id, hsize_t *count, hid_t dxpl_id);
+H5_DLL herr_t H5Mput(hid_t map_id, hid_t key_mem_type_id, const void *key,
+ hid_t val_mem_type_id, const void *value, hid_t dxpl_id);
+H5_DLL herr_t H5Mget(hid_t map_id, hid_t key_mem_type_id, const void *key,
+ hid_t val_mem_type_id, void *value, hid_t dxpl_id);
+H5_DLL herr_t H5Mexists(hid_t map_id, hid_t key_mem_type_id, const void *key,
+ hbool_t *exists, hid_t dxpl_id);
+H5_DLL herr_t H5Miterate(hid_t map_id, hsize_t *idx, hid_t key_mem_type_id,
+ H5M_iterate_t op, void *op_data, hid_t dxpl_id);
+H5_DLL herr_t H5Miterate_by_name(hid_t loc_id, const char *map_name,
+ hsize_t *idx, hid_t key_mem_type_id, H5M_iterate_t op, void *op_data,
+ hid_t dxpl_id, hid_t lapl_id);
+H5_DLL herr_t H5Mdelete(hid_t map_id, hid_t key_mem_type_id,
+ const void *key, hid_t dxpl_id);
+
+/* Symbols defined for compatibility with previous versions of the HDF5 API.
+ *
+ * Use of these symbols is deprecated.
+ */
+#ifndef H5_NO_DEPRECATED_SYMBOLS
+#endif /* H5_NO_DEPRECATED_SYMBOLS */
+
+#endif /* H5_HAVE_MAP_API */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _H5Mpublic_H */
+
diff --git a/src/H5O.c b/src/H5O.c
index b33e6e2..ffb49d9 100644
--- a/src/H5O.c
+++ b/src/H5O.c
@@ -38,6 +38,8 @@
#include "H5Lprivate.h" /* Links */
#include "H5Opkg.h" /* Object headers */
+#include "H5VLnative_private.h" /* Native VOL connector */
+
/****************/
/* Local Macros */
@@ -100,15 +102,16 @@
hid_t
H5Oopen(hid_t loc_id, const char *name, hid_t lapl_id)
{
- H5G_loc_t loc; /* Location of group */
+ H5VL_object_t *vol_obj; /* Object token of loc_id */
+ H5I_type_t opened_type;
+ void *opened_obj = NULL;
+ H5VL_loc_params_t loc_params;
hid_t ret_value = H5I_INVALID_HID;
FUNC_ENTER_API(H5I_INVALID_HID)
H5TRACE3("i", "i*si", loc_id, name, lapl_id);
/* Check args */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a location")
if(!name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "name parameter cannot be NULL")
if(!*name)
@@ -118,10 +121,24 @@ H5Oopen(hid_t loc_id, const char *name, hid_t lapl_id)
if(H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, FALSE) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info")
+ /* Get the location object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier")
+
+ /* Set location struct fields */
+ loc_params.type = H5VL_OBJECT_BY_NAME;
+ loc_params.loc_data.loc_by_name.name = name;
+ loc_params.loc_data.loc_by_name.lapl_id = lapl_id;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
/* Open the object */
- if((ret_value = H5O_open_name(&loc, name, TRUE)) < 0)
+ if(NULL == (opened_obj = H5VL_object_open(vol_obj, &loc_params, &opened_type, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open object")
+ /* Get an atom for the object */
+ if((ret_value = H5VL_register(opened_type, opened_obj, vol_obj->connector, TRUE)) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to atomize object handle")
+
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Oopen() */
@@ -154,15 +171,16 @@ hid_t
H5Oopen_by_idx(hid_t loc_id, const char *group_name, H5_index_t idx_type,
H5_iter_order_t order, hsize_t n, hid_t lapl_id)
{
- H5G_loc_t loc; /* Location of group */
+ H5VL_object_t *vol_obj; /* Object token of loc_id */
+ H5I_type_t opened_type;
+ void *opened_obj = NULL;
+ H5VL_loc_params_t loc_params;
hid_t ret_value = H5I_INVALID_HID;
FUNC_ENTER_API(H5I_INVALID_HID)
H5TRACE6("i", "i*sIiIohi", loc_id, group_name, idx_type, order, n, lapl_id);
/* Check args */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a location")
if(!group_name || !*group_name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "no name specified")
if(idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N)
@@ -174,10 +192,25 @@ H5Oopen_by_idx(hid_t loc_id, const char *group_name, H5_index_t idx_type,
if(H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, FALSE) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info")
+ loc_params.type = H5VL_OBJECT_BY_IDX;
+ loc_params.loc_data.loc_by_idx.name = group_name;
+ loc_params.loc_data.loc_by_idx.idx_type = idx_type;
+ loc_params.loc_data.loc_by_idx.order = order;
+ loc_params.loc_data.loc_by_idx.n = n;
+ loc_params.loc_data.loc_by_idx.lapl_id = lapl_id;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* get the location object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier")
+
/* Open the object */
- if((ret_value = H5O_open_by_idx(&loc, group_name, idx_type, order, n)) < 0)
+ if(NULL == (opened_obj = H5VL_object_open(vol_obj, &loc_params, &opened_type, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open object")
+ if((ret_value = H5VL_register(opened_type, opened_obj, vol_obj->connector, TRUE)) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to atomize object handle")
+
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Oopen_by_idx() */
@@ -221,23 +254,60 @@ done:
hid_t
H5Oopen_by_addr(hid_t loc_id, haddr_t addr)
{
- H5G_loc_t loc; /* Location within file */
- hid_t ret_value = H5I_INVALID_HID; /* Return value */
+ H5VL_object_t *vol_obj; /* Object token of loc_id */
+ H5I_type_t vol_obj_type = H5I_BADID;/* Object type of loc_id */
+ H5I_type_t opened_type; /* Opened object type */
+ void *opened_obj = NULL; /* Opened object */
+ H5VL_loc_params_t loc_params; /* Location parameters */
+ H5VL_token_t obj_token = {0}; /* Object token */
+ hid_t file_id = H5I_INVALID_HID; /* File ID */
+ void *vol_obj_file = NULL; /* Object token of file_id */
+ H5F_t *f = NULL;
+ uint8_t *p = NULL;
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
FUNC_ENTER_API(H5I_INVALID_HID)
H5TRACE2("i", "ia", loc_id, addr);
- /* Check args */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a location")
- if(!H5F_addr_defined(addr))
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "no address supplied")
+ /* Get the location object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier")
+
+ /* Get object type */
+ if((vol_obj_type = H5I_get_type(loc_id)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier")
+
+ /* Get the file for the object */
+ if((file_id = H5F_get_file_id(loc_id, vol_obj_type, FALSE)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a file or file object")
+
+ /* Retrieve VOL object */
+ if(NULL == (vol_obj_file = H5VL_vol_object(file_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier")
+
+ /* Retrieve file from VOL object */
+ if(NULL == (f = (H5F_t *)H5VL_object_data(vol_obj_file)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid VOL object")
+
+ /* This is a native specific routine that requires serialization of the token */
+ p = obj_token;
+ H5F_addr_encode(f, &p, addr);
+
+ loc_params.type = H5VL_OBJECT_BY_TOKEN;
+ loc_params.loc_data.loc_by_token.token = obj_token;
+ loc_params.obj_type = vol_obj_type;
/* Open the object */
- if((ret_value = H5O_open_by_addr(&loc, addr)) < 0)
+ if(NULL == (opened_obj = H5VL_object_open(vol_obj, &loc_params, &opened_type, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open object")
+ /* Register the dataset ID */
+ if((ret_value = H5VL_register(opened_type, opened_obj, vol_obj->connector, TRUE)) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to atomize object handle")
+
done:
+ if(file_id != H5I_INVALID_HID && H5I_dec_ref(file_id) < 0)
+ HDONE_ERROR(H5E_REFERENCE, H5E_CANTDEC, H5I_INVALID_HID, "unable to decrement refcount on file")
FUNC_LEAVE_API(ret_value)
} /* end H5Oopen_by_addr() */
@@ -267,20 +337,19 @@ herr_t
H5Olink(hid_t obj_id, hid_t new_loc_id, const char *new_name, hid_t lcpl_id,
hid_t lapl_id)
{
- H5G_loc_t new_loc; /* Location of group to link from */
- H5G_loc_t obj_loc; /* Location of object to link to */
- herr_t ret_value = SUCCEED; /* Return value */
+ H5VL_object_t *vol_obj1 = NULL; /* object token of obj_id */
+ H5VL_object_t *vol_obj2 = NULL; /* object token of new_loc_id */
+ H5VL_object_t tmp_vol_obj; /* Temporary object token of */
+ H5VL_loc_params_t loc_params1;
+ H5VL_loc_params_t loc_params2;
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE5("e", "ii*sii", obj_id, new_loc_id, new_name, lcpl_id, lapl_id);
/* Check arguments */
- if(H5G_loc(obj_id, &obj_loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(new_loc_id == H5L_SAME_LOC)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "cannot use H5L_SAME_LOC when only one location is specified")
- if(H5G_loc(new_loc_id, &new_loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!new_name || !*new_name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified")
/* Avoid compiler warning on 32-bit machines */
@@ -291,12 +360,42 @@ H5Olink(hid_t obj_id, hid_t new_loc_id, const char *new_name, hid_t lcpl_id,
if(lcpl_id != H5P_DEFAULT && (TRUE != H5P_isa_class(lcpl_id, H5P_LINK_CREATE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a link creation property list")
+ /* Check the group access property list */
+ if(H5P_DEFAULT == lcpl_id)
+ lcpl_id = H5P_LINK_CREATE_DEFAULT;
+
/* Verify access property list and set up collective metadata if appropriate */
if(H5CX_set_apl(&lapl_id, H5P_CLS_LACC, obj_id, TRUE) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set access property list info")
- /* Link to the object */
- if(H5L_link(&new_loc, new_name, &obj_loc, lcpl_id) < 0)
+ loc_params1.type = H5VL_OBJECT_BY_SELF;
+ loc_params1.obj_type = H5I_get_type(obj_id);
+
+ loc_params2.type = H5VL_OBJECT_BY_NAME;
+ loc_params2.obj_type = H5I_get_type(new_loc_id);
+ loc_params2.loc_data.loc_by_name.name = new_name;
+ loc_params2.loc_data.loc_by_name.lapl_id = lapl_id;
+
+ if(H5L_SAME_LOC != obj_id)
+ /* get the location object */
+ if(NULL == (vol_obj1 = H5VL_vol_object(obj_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+ if(H5L_SAME_LOC != new_loc_id)
+ /* get the location object */
+ if(NULL == (vol_obj2 = H5VL_vol_object(new_loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Make sure that the VOL connectors are the same */
+ if(vol_obj1 && vol_obj2)
+ if (vol_obj1->connector->cls->value != vol_obj2->connector->cls->value)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "Objects are accessed through different VOL connectors and can't be linked")
+
+ /* Construct a temporary VOL object */
+ tmp_vol_obj.data = vol_obj2->data;
+ tmp_vol_obj.connector = (vol_obj1 != NULL ? vol_obj1->connector : vol_obj2->connector);
+
+ /* Create a link to the object */
+ if(H5VL_link_create(H5VL_LINK_CREATE_HARD, &tmp_vol_obj, &loc_params2, lcpl_id, lapl_id, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, vol_obj1->data, &loc_params1) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTCREATE, FAIL, "unable to create link")
done:
@@ -327,22 +426,26 @@ done:
herr_t
H5Oincr_refcount(hid_t object_id)
{
- H5O_loc_t *oloc; /* Object location */
- herr_t ret_value = SUCCEED; /* Return value */
+ H5VL_object_t *vol_obj; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
+ herr_t ret_value = SUCCEED;
FUNC_ENTER_API(FAIL)
H5TRACE1("e", "i", object_id);
- /* Get the object's oloc so we can adjust its link count */
- if((oloc = H5O_get_loc(object_id)) == NULL)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get object location from ID")
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(object_id);
+
+ /* Get the location object */
+ if(NULL == (vol_obj = H5VL_vol_object(object_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
/* Set up collective metadata if appropriate */
if(H5CX_set_loc(object_id) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set access property list info")
/* Change the object's reference count */
- if(H5O_link(oloc, 1) < 0)
+ if(H5VL_object_specific(vol_obj, &loc_params, H5VL_OBJECT_CHANGE_REF_COUNT, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, 1) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "modifying object link count failed")
done:
@@ -373,22 +476,26 @@ done:
herr_t
H5Odecr_refcount(hid_t object_id)
{
- H5O_loc_t *oloc; /* Object location */
+ H5VL_object_t *vol_obj; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE1("e", "i", object_id);
- /* Get the object's oloc so we can adjust its link count */
- if((oloc = H5O_get_loc(object_id)) == NULL)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get object location from ID")
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(object_id);
+
+ /* Get the location object */
+ if(NULL == (vol_obj = H5VL_vol_object(object_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
/* Set up collective metadata if appropriate */
if(H5CX_set_loc(object_id) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set access property list info")
/* Change the object's reference count */
- if(H5O_link(oloc, -1) < 0)
+ if(H5VL_object_specific(vol_obj, &loc_params, H5VL_OBJECT_CHANGE_REF_COUNT, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, -1) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "modifying object link count failed")
done:
@@ -412,15 +519,14 @@ done:
htri_t
H5Oexists_by_name(hid_t loc_id, const char *name, hid_t lapl_id)
{
- H5G_loc_t loc; /* Location info */
+ H5VL_object_t *vol_obj; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
htri_t ret_value = FAIL; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE3("t", "i*si", loc_id, name, lapl_id);
/* Check args */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "name parameter cannot be NULL")
if(!*name)
@@ -430,8 +536,18 @@ H5Oexists_by_name(hid_t loc_id, const char *name, hid_t lapl_id)
if(H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, FALSE) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set access property list info")
+ /* Get the location object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Set the location struct fields */
+ loc_params.type = H5VL_OBJECT_BY_NAME;
+ loc_params.loc_data.loc_by_name.name = name;
+ loc_params.loc_data.loc_by_name.lapl_id = lapl_id;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
/* Check if the object exists */
- if((ret_value = H5G_loc_exists(&loc, name)) < 0)
+ if(H5VL_object_specific(vol_obj, &loc_params, H5VL_OBJECT_EXISTS, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &ret_value) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to determine if '%s' exists", name)
done:
@@ -456,22 +572,29 @@ done:
herr_t
H5Oget_info2(hid_t loc_id, H5O_info_t *oinfo, unsigned fields)
{
- H5G_loc_t loc; /* Location of group */
+ H5VL_object_t *vol_obj; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE3("e", "i*xIu", loc_id, oinfo, fields);
/* Check args */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!oinfo)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "oinfo parameter cannot be NULL")
if(fields & ~H5O_INFO_ALL)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid fields")
+ /* Set location struct fields */
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* Get the location object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
/* Retrieve the object's information */
- if(H5G_loc_info(&loc, ".", oinfo, fields) < 0)
+ if(H5VL_object_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_OBJECT_GET_INFO, &loc_params, oinfo, fields) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't get info for object")
done:
@@ -497,15 +620,14 @@ herr_t
H5Oget_info_by_name2(hid_t loc_id, const char *name, H5O_info_t *oinfo,
unsigned fields, hid_t lapl_id)
{
- H5G_loc_t loc; /* Location of group */
+ H5VL_object_t *vol_obj; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE5("e", "i*s*xIui", loc_id, name, oinfo, fields, lapl_id);
/* Check args */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "name parameter cannot be NULL")
if(!*name)
@@ -519,8 +641,18 @@ H5Oget_info_by_name2(hid_t loc_id, const char *name, H5O_info_t *oinfo,
if(H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, FALSE) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set access property list info")
+ /* Fill out location struct */
+ loc_params.type = H5VL_OBJECT_BY_NAME;
+ loc_params.loc_data.loc_by_name.name = name;
+ loc_params.loc_data.loc_by_name.lapl_id = lapl_id;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* Get the location object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
/* Retrieve the object's information */
- if(H5G_loc_info(&loc, name, oinfo/*out*/, fields) < 0)
+ if(H5VL_object_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_OBJECT_GET_INFO, &loc_params, oinfo, fields) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't get info for object: '%s'", name)
done:
@@ -548,7 +680,8 @@ herr_t
H5Oget_info_by_idx2(hid_t loc_id, const char *group_name, H5_index_t idx_type,
H5_iter_order_t order, hsize_t n, H5O_info_t *oinfo, unsigned fields, hid_t lapl_id)
{
- H5G_loc_t loc; /* Location of group */
+ H5VL_object_t *vol_obj; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -556,8 +689,6 @@ H5Oget_info_by_idx2(hid_t loc_id, const char *group_name, H5_index_t idx_type,
fields, lapl_id);
/* Check args */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!group_name || !*group_name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified")
if(idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N)
@@ -573,8 +704,20 @@ H5Oget_info_by_idx2(hid_t loc_id, const char *group_name, H5_index_t idx_type,
if(H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, FALSE) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set access property list info")
+ loc_params.type = H5VL_OBJECT_BY_IDX;
+ loc_params.loc_data.loc_by_idx.name = group_name;
+ loc_params.loc_data.loc_by_idx.idx_type = idx_type;
+ loc_params.loc_data.loc_by_idx.order = order;
+ loc_params.loc_data.loc_by_idx.n = n;
+ loc_params.loc_data.loc_by_idx.lapl_id = lapl_id;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* Get the location object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
/* Retrieve the object's information */
- if(H5O__get_info_by_idx(&loc, group_name, idx_type, order, n, oinfo, fields) < 0)
+ if(H5VL_object_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_OBJECT_GET_INFO, &loc_params, oinfo, fields) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't get info for object")
done:
@@ -602,22 +745,27 @@ done:
herr_t
H5Oset_comment(hid_t obj_id, const char *comment)
{
- H5G_loc_t loc; /* Location of group */
+ H5VL_object_t *vol_obj; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE2("e", "i*s", obj_id, comment);
- /* Check args */
- if(H5G_loc(obj_id, &loc) < 0)
+ /* Get the location object */
+ if(NULL == (vol_obj = H5VL_vol_object(obj_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
/* Set up collective metadata if appropriate */
if(H5CX_set_loc(obj_id) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set collective metadata read info")
+ /* Fill in location struct fields */
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(obj_id);
+
/* (Re)set the object's comment */
- if(H5G_loc_set_comment(&loc, ".", comment) < 0)
+ if(H5VL_object_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_OBJECT_SET_COMMENT, &loc_params, comment) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set comment for object")
done:
@@ -646,15 +794,14 @@ herr_t
H5Oset_comment_by_name(hid_t loc_id, const char *name, const char *comment,
hid_t lapl_id)
{
- H5G_loc_t loc; /* Location of group */
+ H5VL_object_t *vol_obj; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE4("e", "i*s*si", loc_id, name, comment, lapl_id);
/* Check args */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!name || !*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name")
@@ -662,8 +809,18 @@ H5Oset_comment_by_name(hid_t loc_id, const char *name, const char *comment,
if(H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, TRUE) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set access property list info")
+ /* Fill in location struct fields */
+ loc_params.type = H5VL_OBJECT_BY_NAME;
+ loc_params.loc_data.loc_by_name.name = name;
+ loc_params.loc_data.loc_by_name.lapl_id = lapl_id;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* Get the location object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
/* (Re)set the object's comment */
- if(H5G_loc_set_comment(&loc, name, comment) < 0)
+ if(H5VL_object_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_OBJECT_SET_COMMENT, &loc_params, comment) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set comment for object: '%s'", name)
done:
@@ -690,18 +847,23 @@ done:
ssize_t
H5Oget_comment(hid_t obj_id, char *comment, size_t bufsize)
{
- H5G_loc_t loc; /* Location of group */
+ H5VL_object_t *vol_obj; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
ssize_t ret_value = -1; /* Return value */
FUNC_ENTER_API((-1))
H5TRACE3("Zs", "i*sz", obj_id, comment, bufsize);
- /* Check args */
- if(H5G_loc(obj_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "not a location")
+ /* Get the object */
+ if(NULL == (vol_obj = H5VL_vol_object(obj_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "invalid location identifier")
+
+ /* Set fields in the location struct */
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(obj_id);
/* Retrieve the object's comment */
- if((ret_value = H5G_loc_get_comment(&loc, ".", comment/*out*/, bufsize)) < 0)
+ if(H5VL_object_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_OBJECT_GET_COMMENT, &loc_params, comment, bufsize, &ret_value) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, (-1), "can't get comment for object")
done:
@@ -729,15 +891,14 @@ ssize_t
H5Oget_comment_by_name(hid_t loc_id, const char *name, char *comment, size_t bufsize,
hid_t lapl_id)
{
- H5G_loc_t loc; /* Location of group */
+ H5VL_object_t *vol_obj; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
ssize_t ret_value = -1; /* Return value */
FUNC_ENTER_API((-1))
H5TRACE5("Zs", "i*s*szi", loc_id, name, comment, bufsize, lapl_id);
/* Check args */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "not a location")
if(!name || !*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, (-1), "no name")
@@ -745,8 +906,18 @@ H5Oget_comment_by_name(hid_t loc_id, const char *name, char *comment, size_t buf
if(H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, FALSE) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, (-1), "can't set access property list info")
+ /* Fill in location struct fields */
+ loc_params.type = H5VL_OBJECT_BY_NAME;
+ loc_params.loc_data.loc_by_name.name = name;
+ loc_params.loc_data.loc_by_name.lapl_id = lapl_id;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* Get the location object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "invalid location identifier")
+
/* Retrieve the object's comment */
- if((ret_value = H5G_loc_get_comment(&loc, name, comment/*out*/, bufsize)) < 0)
+ if(H5VL_object_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_OBJECT_GET_COMMENT, &loc_params, comment, bufsize, &ret_value) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, (-1), "can't get comment for object: '%s'", name)
done:
@@ -793,15 +964,14 @@ herr_t
H5Ovisit2(hid_t obj_id, H5_index_t idx_type, H5_iter_order_t order,
H5O_iterate_t op, void *op_data, unsigned fields)
{
- H5G_loc_t loc;
+ H5VL_object_t *vol_obj; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
herr_t ret_value; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE6("e", "iIiIox*xIu", obj_id, idx_type, order, op, op_data, fields);
/* Check args */
- if(H5G_loc(obj_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index type specified")
if(order <= H5_ITER_UNKNOWN || order >= H5_ITER_N)
@@ -811,8 +981,16 @@ H5Ovisit2(hid_t obj_id, H5_index_t idx_type, H5_iter_order_t order,
if(fields & ~H5O_INFO_ALL)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid fields")
+ /* Get the location object */
+ if(NULL == (vol_obj = H5VL_vol_object(obj_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Set location parameters */
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(obj_id);
+
/* Visit the objects */
- if((ret_value = H5O__visit(&loc, ".", idx_type, order, op, op_data, fields)) < 0)
+ if((ret_value = H5VL_object_specific(vol_obj, &loc_params, H5VL_OBJECT_VISIT, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, (int)idx_type, (int)order, op, op_data, fields)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "object iteration failed")
done:
@@ -859,7 +1037,8 @@ herr_t
H5Ovisit_by_name2(hid_t loc_id, const char *obj_name, H5_index_t idx_type,
H5_iter_order_t order, H5O_iterate_t op, void *op_data, unsigned fields, hid_t lapl_id)
{
- H5G_loc_t loc;
+ H5VL_object_t *vol_obj; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
herr_t ret_value; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -867,8 +1046,6 @@ H5Ovisit_by_name2(hid_t loc_id, const char *obj_name, H5_index_t idx_type,
fields, lapl_id);
/* Check args */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!obj_name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "obj_name parameter cannot be NULL")
if(!*obj_name)
@@ -886,8 +1063,18 @@ H5Ovisit_by_name2(hid_t loc_id, const char *obj_name, H5_index_t idx_type,
if(H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, FALSE) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set access property list info")
+ /* Get the location object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Set location parameters */
+ loc_params.type = H5VL_OBJECT_BY_NAME;
+ loc_params.loc_data.loc_by_name.name = obj_name;
+ loc_params.loc_data.loc_by_name.lapl_id = lapl_id;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
/* Visit the objects */
- if((ret_value = H5O__visit(&loc, obj_name, idx_type, order, op, op_data, fields)) < 0)
+ if((ret_value = H5VL_object_specific(vol_obj, &loc_params, H5VL_OBJECT_VISIT, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, (int)idx_type, (int)order, op, op_data, fields)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "object iteration failed")
done:
@@ -925,6 +1112,7 @@ H5Oclose(hid_t object_id)
case H5I_GROUP:
case H5I_DATATYPE:
case H5I_DATASET:
+ case H5I_MAP:
if(H5I_object(object_id) == NULL)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a valid object")
if(H5I_dec_app_ref(object_id) < 0)
@@ -936,13 +1124,14 @@ H5Oclose(hid_t object_id)
case H5I_FILE:
case H5I_DATASPACE:
case H5I_ATTR:
- case H5I_REFERENCE:
case H5I_VFL:
+ case H5I_VOL:
case H5I_GENPROP_CLS:
case H5I_GENPROP_LST:
case H5I_ERROR_CLASS:
case H5I_ERROR_MSG:
case H5I_ERROR_STACK:
+ case H5I_SPACE_SEL_ITER:
case H5I_NTYPES:
default:
HGOTO_ERROR(H5E_ARGS, H5E_CANTRELEASE, FAIL, "not a valid file object ID (dataset, group, or datatype)")
@@ -955,113 +1144,215 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5Odisable_mdc_flushes
+ * Function: H5O_disable_mdc_flushes
*
- * Purpose: To "cork" an object:
- * --keep dirty entries associated with the object in the metadata cache
+ * Purpose: Private version of the metadata cache cork function.
*
- * Return: Success: Non-negative
- * Failure: Negative
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5O_disable_mdc_flushes(H5O_loc_t *oloc)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(FAIL);
+
+ if (H5AC_cork(oloc->file, oloc->addr, H5AC__SET_CORK, NULL) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTCORK, FAIL, "unable to cork object");
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* H5O_disable_mdc_flushes() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Odisable_mdc_flushes
+ *
+ * Purpose: "Cork" an object, keeping dirty entries associated with the
+ * object in the metadata cache.
*
- * Programmer: Vailin Choi
- * January 2014
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Vailin Choi
+ * January 2014
*
*-------------------------------------------------------------------------
*/
herr_t
H5Odisable_mdc_flushes(hid_t object_id)
{
- H5O_loc_t *oloc; /* Object location */
- herr_t ret_value = SUCCEED; /* Return value */
+ H5VL_object_t *vol_obj; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params; /* Location parameters */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_API(FAIL)
+ FUNC_ENTER_API(FAIL);
H5TRACE1("e", "i", object_id);
- /* Get the object's oloc */
- if(NULL == (oloc = H5O_get_loc(object_id)))
- HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "unable to get object location from ID")
+ /* Make sure the ID is a file object */
+ if (H5I_is_file_object(object_id) != TRUE)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID is not a file object");
+
+ /* Get the VOL object */
+ if (NULL == (vol_obj = H5VL_vol_object(object_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object ID");
- if(H5AC_cork(oloc->file, oloc->addr, H5AC__SET_CORK, NULL) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTCORK, FAIL, "unable to cork an object")
+ /* Fill in location struct fields */
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(object_id);
+
+ /* Cork the object */
+ if(H5VL_object_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_OBJECT_DISABLE_MDC_FLUSHES, &loc_params) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTCORK, FAIL, "unable to cork object");
done:
- FUNC_LEAVE_API(ret_value)
+ FUNC_LEAVE_API(ret_value);
} /* H5Odisable_mdc_flushes() */
/*-------------------------------------------------------------------------
- * Function: H5Oenable_mdc_flushes
+ * Function: H5O_enable_mdc_flushes
*
- * Purpose: To "uncork" an object
- * --release keeping dirty entries associated with the object
- * in the metadata cache
+ * Purpose: Private version of the metadata cache uncork function.
*
- * Return: Success: Non-negative
- * Failure: Negative
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5O_enable_mdc_flushes(H5O_loc_t *oloc)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(FAIL);
+
+ if (H5AC_cork(oloc->file, oloc->addr, H5AC__UNCORK, NULL) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTUNCORK, FAIL, "unable to uncork object");
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* H5O_enable_mdc_flushes() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Oenable_mdc_flushes
+ *
+ * Purpose: "Uncork" an object, allowing dirty entries associated with
+ * the object to be flushed.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
*
- * Programmer: Vailin Choi
- * January 2014
+ * Programmer: Vailin Choi
+ * January 2014
*
*-------------------------------------------------------------------------
*/
herr_t
H5Oenable_mdc_flushes(hid_t object_id)
{
- H5O_loc_t *oloc; /* Object location */
- herr_t ret_value = SUCCEED; /* Return value */
+ H5VL_object_t *vol_obj; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params; /* Location parameters */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_API(FAIL)
+ FUNC_ENTER_API(FAIL);
H5TRACE1("e", "i", object_id);
- /* Get the object's oloc */
- if(NULL == (oloc = H5O_get_loc(object_id)))
- HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "unable to get object location from ID")
+ /* Make sure the ID is a file object */
+ if (H5I_is_file_object(object_id) != TRUE)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID is not a file object");
+
+ /* Get the VOL object */
+ if (NULL == (vol_obj = H5VL_vol_object(object_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object ID");
+
+ /* Fill in location struct fields */
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(object_id);
- /* Set the value */
- if(H5AC_cork(oloc->file, oloc->addr, H5AC__UNCORK, NULL) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTUNCORK, FAIL, "unable to uncork an object")
+ /* Uncork the object */
+ if (H5VL_object_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_OBJECT_ENABLE_MDC_FLUSHES, &loc_params) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTUNCORK, FAIL, "unable to uncork object");
done:
- FUNC_LEAVE_API(ret_value)
+ FUNC_LEAVE_API(ret_value);
} /* H5Oenable_mdc_flushes() */
/*-------------------------------------------------------------------------
- * Function: H5Oare_mdc_flushes_disabled
+ * Function: H5O_are_mdc_flushes_disabled
*
- * Purpose: Retrieve the object's "cork" status in the parameter "are_disabled":
- * TRUE if mdc flushes for the object is disabled
- * FALSE if mdc flushes for the object is not disabled
- * Return error if the parameter "are_disabled" is not supplied
+ * Purpose: Private version of cork status getter.
*
- * Return: Success: Non-negative
- * Failure: Negative
+ * Return: SUCCEED/FAIL
*
- * Programmer: Vailin Choi
- * January 2014
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5O_are_mdc_flushes_disabled(H5O_loc_t *oloc, hbool_t *are_disabled)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(FAIL);
+
+ HDassert(are_disabled);
+
+ if (H5AC_cork(oloc->file, oloc->addr, H5AC__GET_CORKED, are_disabled) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to retrieve object's cork status");
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5O_are_mdc_flushes_disabled() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Oare_mdc_flushes_disabled
+ *
+ * Purpose: Retrieve the object's "cork" status in the parameter "are_disabled":
+ * TRUE if mdc flushes for the object is disabled
+ * FALSE if mdc flushes for the object is not disabled
+ *
+ * Return error if the parameter "are_disabled" is not supplied
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Vailin Choi
+ * January 2014
*
*-------------------------------------------------------------------------
*/
herr_t
H5Oare_mdc_flushes_disabled(hid_t object_id, hbool_t *are_disabled)
{
- H5O_loc_t *oloc; /* Object location */
- herr_t ret_value = SUCCEED; /* Return value */
+ H5VL_object_t *vol_obj; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params; /* Location parameters */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_API(FAIL)
+ FUNC_ENTER_API(FAIL);
H5TRACE2("e", "i*b", object_id, are_disabled);
- /* Check args */
+ /* Sanity check */
+ if (!are_disabled)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get object location from ID");
+
+ /* Make sure the ID is a file object */
+ if (H5I_is_file_object(object_id) != TRUE)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID is not a file object");
+
+ /* Get the VOL object */
+ if (NULL == (vol_obj = H5VL_vol_object(object_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object ID");
- /* Get the object's oloc */
- if(NULL == (oloc = H5O_get_loc(object_id)))
- HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "unable to get object location from ID")
- if(!are_disabled)
- HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "unable to get object location from ID")
+ /* Fill in location struct fields */
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(object_id);
/* Get the cork status */
- if(H5AC_cork(oloc->file, oloc->addr, H5AC__GET_CORKED, are_disabled) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to retrieve an object's cork status")
+ if (H5VL_object_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_OBJECT_ARE_MDC_FLUSHES_DISABLED, &loc_params, are_disabled) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to retrieve object's cork status");
done:
FUNC_LEAVE_API(ret_value)
diff --git a/src/H5Oalloc.c b/src/H5Oalloc.c
index 23dd928..c1f90cb 100644
--- a/src/H5Oalloc.c
+++ b/src/H5Oalloc.c
@@ -36,6 +36,7 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5FLprivate.h" /* Free lists */
#include "H5MFprivate.h" /* File memory management */
+#include "H5MMprivate.h" /* Memory management */
#include "H5Opkg.h" /* Object headers */
/****************/
@@ -949,7 +950,7 @@ H5O__alloc_chunk(H5F_t *f, H5O_t *oh, size_t size, size_t found_null,
* # at the beginning of the chunk image.
*/
if(oh->version > H5O_VERSION_1) {
- HDmemcpy(p, H5O_CHK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ H5MM_memcpy(p, H5O_CHK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
p += H5_SIZEOF_MAGIC;
} /* end if */
@@ -988,7 +989,7 @@ H5O__alloc_chunk(H5F_t *f, H5O_t *oh, size_t size, size_t found_null,
HDassert(curr_msg->type->id != H5O_CONT_ID);
/* Copy the raw data */
- HDmemcpy(p, curr_msg->raw - (size_t)H5O_SIZEOF_MSGHDR_OH(oh),
+ H5MM_memcpy(p, curr_msg->raw - (size_t)H5O_SIZEOF_MSGHDR_OH(oh),
curr_msg->raw_size + (size_t)H5O_SIZEOF_MSGHDR_OH(oh));
/* Update the message info */
@@ -1044,7 +1045,7 @@ H5O__alloc_chunk(H5F_t *f, H5O_t *oh, size_t size, size_t found_null,
null_msg->chunkno = oh->mesg[found_msg->msgno].chunkno;
/* Copy the message to move (& its prefix) to its new location */
- HDmemcpy(p, oh->mesg[found_msg->msgno].raw - H5O_SIZEOF_MSGHDR_OH(oh),
+ H5MM_memcpy(p, oh->mesg[found_msg->msgno].raw - H5O_SIZEOF_MSGHDR_OH(oh),
oh->mesg[found_msg->msgno].raw_size + (size_t)H5O_SIZEOF_MSGHDR_OH(oh));
/* Switch moved message to point to new location */
@@ -1519,7 +1520,7 @@ H5O__move_cont(H5F_t *f, H5O_t *oh, unsigned cont_u)
move_size = curr_msg->raw_size + (size_t)H5O_SIZEOF_MSGHDR_OH(oh);
/* Move message out of deleted chunk */
- HDmemcpy(move_start, curr_msg->raw - H5O_SIZEOF_MSGHDR_OH(oh), move_size);
+ H5MM_memcpy(move_start, curr_msg->raw - H5O_SIZEOF_MSGHDR_OH(oh), move_size);
curr_msg->raw = move_start + H5O_SIZEOF_MSGHDR_OH(oh);
curr_msg->chunkno = cont_chunkno;
chk_dirtied = TRUE;
@@ -1791,7 +1792,7 @@ H5O__move_msgs_forward(H5F_t *f, H5O_t *oh)
} /* end if */
/* Copy raw data for non-null message to new chunk */
- HDmemcpy(null_msg->raw - H5O_SIZEOF_MSGHDR_OH(oh), curr_msg->raw - H5O_SIZEOF_MSGHDR_OH(oh), curr_msg->raw_size + (size_t)H5O_SIZEOF_MSGHDR_OH(oh));
+ H5MM_memcpy(null_msg->raw - H5O_SIZEOF_MSGHDR_OH(oh), curr_msg->raw - H5O_SIZEOF_MSGHDR_OH(oh), curr_msg->raw_size + (size_t)H5O_SIZEOF_MSGHDR_OH(oh));
/* Point non-null message at null message's space */
curr_msg->chunkno = null_msg->chunkno;
diff --git a/src/H5Oattr.c b/src/H5Oattr.c
index c93bf32..f685a00c 100644
--- a/src/H5Oattr.c
+++ b/src/H5Oattr.c
@@ -176,7 +176,12 @@ H5O_attr_decode(H5F_t *f, H5O_t *open_oh, unsigned H5_ATTR_UNUSED mesg_flags,
/* Decode and store the name */
if(NULL == (attr->shared->name = H5MM_strdup((const char *)p)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+
+ /* Make an attempt to detect corrupted name or name length - HDFFV-10588 */
+ if(name_len != (HDstrlen(attr->shared->name) + 1))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTDECODE, NULL, "attribute name has different length than stored length")
+
if(attr->shared->version < H5O_ATTR_VERSION_2)
p += H5O_ALIGN_OLD(name_len); /* advance the memory pointer */
else
@@ -195,7 +200,7 @@ H5O_attr_decode(H5F_t *f, H5O_t *open_oh, unsigned H5_ATTR_UNUSED mesg_flags,
* What's actually shared, though, is only the extent.
*/
if(NULL == (attr->shared->ds = H5FL_CALLOC(H5S_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* Decode attribute's dataspace extent */
if((extent = (H5S_extent_t *)(H5O_MSG_SDSPACE->decode)(f, open_oh,
@@ -203,7 +208,7 @@ H5O_attr_decode(H5F_t *f, H5O_t *open_oh, unsigned H5_ATTR_UNUSED mesg_flags,
HGOTO_ERROR(H5E_ATTR, H5E_CANTDECODE, NULL, "can't decode attribute dataspace")
/* Copy the extent information to the dataspace */
- HDmemcpy(&(attr->shared->ds->extent), extent, sizeof(H5S_extent_t));
+ H5MM_memcpy(&(attr->shared->ds->extent), extent, sizeof(H5S_extent_t));
/* Release temporary extent information */
extent = H5FL_FREE(H5S_extent_t, extent);
@@ -235,7 +240,7 @@ H5O_attr_decode(H5F_t *f, H5O_t *open_oh, unsigned H5_ATTR_UNUSED mesg_flags,
if(attr->shared->data_size) {
if(NULL == (attr->shared->data = H5FL_BLK_MALLOC(attr_buf, attr->shared->data_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- HDmemcpy(attr->shared->data, p, attr->shared->data_size);
+ H5MM_memcpy(attr->shared->data, p, attr->shared->data_size);
} /* end if */
/* Increment the reference count for this object header message in cache(compact
@@ -248,15 +253,11 @@ H5O_attr_decode(H5F_t *f, H5O_t *open_oh, unsigned H5_ATTR_UNUSED mesg_flags,
done:
if(NULL == ret_value)
if(attr) {
- if(attr->shared) {
- /* Free any dynamically allocated items */
- if(H5A__free(attr) < 0)
+ /* Free any dynamically allocated items */
+ if(attr->shared)
+ if(H5A__shared_free(attr) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, NULL, "can't release attribute info")
- /* Destroy shared attribute struct */
- attr->shared = H5FL_FREE(H5A_shared_t, attr->shared);
- } /* end if */
-
attr = H5FL_FREE(H5A_t, attr);
} /* end if */
@@ -331,7 +332,7 @@ H5O_attr_encode(H5F_t *f, uint8_t *p, const void *mesg)
*p++ = attr->shared->encoding;
/* Write the name including null terminator */
- HDmemcpy(p, attr->shared->name, name_len);
+ H5MM_memcpy(p, attr->shared->name, name_len);
if(attr->shared->version < H5O_ATTR_VERSION_2) {
/* Pad to the correct number of bytes */
HDmemset(p + name_len, 0, H5O_ALIGN_OLD(name_len) - name_len);
@@ -364,7 +365,7 @@ H5O_attr_encode(H5F_t *f, uint8_t *p, const void *mesg)
/* Store attribute data. If there's no data, store 0 as fill value. */
if(attr->shared->data)
- HDmemcpy(p, attr->shared->data, attr->shared->data_size);
+ H5MM_memcpy(p, attr->shared->data, attr->shared->data_size);
else
HDmemset(p, 0, attr->shared->data_size);
diff --git a/src/H5Oattribute.c b/src/H5Oattribute.c
index 5183026..57ec9b8 100644
--- a/src/H5Oattribute.c
+++ b/src/H5Oattribute.c
@@ -713,7 +713,7 @@ H5O__attr_find_opened_attr(const H5O_loc_t *loc, H5A_t **attr, const char* name_
unsigned long attr_fnum; /* Attributes file serial number */
/* Get pointer to attribute */
- if(NULL == (*attr = (H5A_t *)H5I_object_verify(attr_id_list[u], H5I_ATTR)))
+ if(NULL == (*attr = (H5A_t *)H5VL_object_verify(attr_id_list[u], H5I_ATTR)))
HGOTO_ERROR(H5E_ATTR, H5E_BADTYPE, FAIL, "not an attribute")
/* Get file serial number for attribute */
@@ -862,7 +862,7 @@ H5O__attr_write_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
/* (Needs to occur before updating the shared message, or the hash
* value on the old & new messages will be the same) */
- HDmemcpy(((H5A_t *)mesg->native)->shared->data, udata->attr->shared->data, udata->attr->shared->data_size);
+ H5MM_memcpy(((H5A_t *)mesg->native)->shared->data, udata->attr->shared->data, udata->attr->shared->data_size);
} /* end if */
/* Mark the message as modified */
@@ -1304,7 +1304,7 @@ H5O_attr_iterate_real(hid_t loc_id, const H5O_loc_t *loc, H5_index_t idx_type,
/* Iterate over attributes in table */
if((ret_value = H5A__attr_iterate_table(&atable, skip, last_attr, loc_id, attr_op, op_data)) < 0)
- HERROR(H5E_ATTR, H5E_CANTNEXT, "iteration operator failed");
+ HERROR(H5E_ATTR, H5E_BADITER, "iteration operator failed");
} /* end else */
done:
diff --git a/src/H5Obogus.c b/src/H5Obogus.c
index fbf04f2..f3cca0f 100644
--- a/src/H5Obogus.c
+++ b/src/H5Obogus.c
@@ -49,7 +49,7 @@ const H5O_msg_class_t H5O_MSG_BOGUS_VALID[1] = {{
H5O_BOGUS_VALID_ID, /*message id number */
"bogus valid", /*message name for debugging */
0, /*native message size */
- 0, /* messages are sharable? */
+ H5O_SHARE_IS_SHARABLE, /* messages are sharable? */
H5O__bogus_decode, /*decode message */
H5O_bogus_encode, /*encode message */
NULL, /*copy the native value */
@@ -73,7 +73,7 @@ const H5O_msg_class_t H5O_MSG_BOGUS_INVALID[1] = {{
H5O_BOGUS_INVALID_ID, /*message id number */
"bogus invalid", /*message name for debugging */
0, /*native message size */
- 0, /* messages are sharable? */
+ H5O_SHARE_IS_SHARABLE, /* messages are sharable? */
H5O__bogus_decode, /*decode message */
H5O_bogus_encode, /*encode message */
NULL, /*copy the native value */
diff --git a/src/H5Ocache.c b/src/H5Ocache.c
index 7e1dd82..cfe2d10 100644
--- a/src/H5Ocache.c
+++ b/src/H5Ocache.c
@@ -36,6 +36,7 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5FLprivate.h" /* Free lists */
#include "H5MFprivate.h" /* File memory management */
+#include "H5MMprivate.h" /* Memory management */
#include "H5Opkg.h" /* Object headers */
#include "H5WBprivate.h" /* Wrapped Buffers */
@@ -544,7 +545,7 @@ H5O__cache_serialize(const H5F_t *f, void *image, size_t len, void *_thing)
* Can we rework things so that the object header and the cache
* share a buffer?
*/
- HDmemcpy(image, oh->chunk[0].image, len);
+ H5MM_memcpy(image, oh->chunk[0].image, len);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -902,7 +903,7 @@ H5O__cache_chk_serialize(const H5F_t *f, void *image, size_t len, void *_thing)
/* copy the chunk into the image -- this is potentially expensive.
* Can we rework things so that the chunk and the cache share a buffer?
*/
- HDmemcpy(image, chk_proxy->oh->chunk[chk_proxy->chunkno].image, len);
+ H5MM_memcpy(image, chk_proxy->oh->chunk[chk_proxy->chunkno].image, len);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -1354,7 +1355,7 @@ H5O__chunk_deserialize(H5O_t *oh, haddr_t addr, size_t len, const uint8_t *image
oh->chunk[chunkno].chunk_proxy = NULL;
/* Copy disk image into chunk's image */
- HDmemcpy(oh->chunk[chunkno].image, image, oh->chunk[chunkno].size);
+ H5MM_memcpy(oh->chunk[chunkno].image, image, oh->chunk[chunkno].size);
/* Point into chunk image to decode */
chunk_image = oh->chunk[chunkno].image;
@@ -1392,7 +1393,8 @@ H5O__chunk_deserialize(H5O_t *oh, haddr_t addr, size_t len, const uint8_t *image
/* Message size */
UINT16DECODE(chunk_image, mesg_size);
- HDassert(mesg_size == H5O_ALIGN_OH(oh, mesg_size));
+ if(mesg_size != H5O_ALIGN_OH(oh, mesg_size))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "message not aligned")
/* Message flags */
flags = *chunk_image++;
@@ -1404,10 +1406,9 @@ H5O__chunk_deserialize(H5O_t *oh, haddr_t addr, size_t len, const uint8_t *image
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "bad flag combination for message")
if((flags & H5O_MSG_FLAG_WAS_UNKNOWN) && !(flags & H5O_MSG_FLAG_MARK_IF_UNKNOWN))
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "bad flag combination for message")
- if((flags & H5O_MSG_FLAG_SHAREABLE)
- && H5O_msg_class_g[id]
- && !(H5O_msg_class_g[id]->share_flags & H5O_SHARE_IS_SHARABLE))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "message of unsharable class flagged as sharable")
+ /* Delay checking the "shareable" flag until we've made sure id
+ * references a valid message class that this version of the library
+ * knows about */
/* Reserved bytes/creation index */
if(oh->version == H5O_VERSION_1)
@@ -1519,9 +1520,17 @@ H5O__chunk_deserialize(H5O_t *oh, haddr_t addr, size_t len, const uint8_t *image
mesgs_modified = TRUE;
} /* end if */
} /* end if */
- else
+ else {
+ /* Check for message of unshareable class marked as "shareable"
+ */
+ if((flags & H5O_MSG_FLAG_SHAREABLE)
+ && H5O_msg_class_g[id]
+ && !(H5O_msg_class_g[id]->share_flags & H5O_SHARE_IS_SHARABLE))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "message of unshareable class flagged as shareable")
+
/* Set message class for "known" messages */
mesg->type = H5O_msg_class_g[id];
+ } /* end else */
/* Do some inspection/interpretation of new messages from this chunk */
/* (detect continuation messages, ref. count messages, etc.) */
@@ -1621,7 +1630,7 @@ H5O__chunk_deserialize(H5O_t *oh, haddr_t addr, size_t len, const uint8_t *image
done:
if(ret_value < 0 && udata->cont_msg_info->msgs) {
- udata->cont_msg_info->msgs = (H5O_chunk_t *)H5FL_SEQ_FREE(H5O_cont_t, udata->cont_msg_info->msgs);
+ udata->cont_msg_info->msgs = H5FL_SEQ_FREE(H5O_cont_t, udata->cont_msg_info->msgs);
udata->cont_msg_info->alloc_nmsgs = 0;
}
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5Ocache_image.c b/src/H5Ocache_image.c
index 591ac4a..70d9ef5 100644
--- a/src/H5Ocache_image.c
+++ b/src/H5Ocache_image.c
@@ -27,11 +27,12 @@
*/
#include "H5Omodule.h" /* This source code file is part of the H5O module */
+#define H5F_FRIEND /*suppress error about including H5Fpkg */
#include "H5private.h" /* Generic Functions */
#include "H5Eprivate.h" /* Error handling */
-#include "H5Fprivate.h" /* Files */
+#include "H5Fpkg.h" /* Files */
#include "H5FLprivate.h" /* Free Lists */
#include "H5Opkg.h" /* Object headers */
#include "H5MFprivate.h" /* File space management */
@@ -275,16 +276,16 @@ H5O__mdci_free(void *mesg)
*-------------------------------------------------------------------------
*/
static herr_t
-H5O__mdci_delete(H5F_t *f, H5O_t *open_oh, void *_mesg)
+H5O__mdci_delete(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh, void *_mesg)
{
H5O_mdci_t *mesg = (H5O_mdci_t *)_mesg;
- herr_t ret_value = SUCCEED; /* Return value */
+ haddr_t final_eoa; /* For sanity check */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC
/* check args */
HDassert(f);
- HDassert(open_oh);
HDassert(mesg);
/* Free file space for cache image */
@@ -321,16 +322,24 @@ H5O__mdci_delete(H5F_t *f, H5O_t *open_oh, void *_mesg)
* before the first metadata cache access. However, given
* time constraints, I don't want to go there now.
*/
- if(H5F_FIRST_ALLOC_DEALLOC(f)) {
- HDassert(HADDR_UNDEF != H5F_EOA_PRE_FSM_FSALLOC(f));
- HDassert(H5F_addr_ge(mesg->addr, H5F_EOA_PRE_FSM_FSALLOC(f)));
- if(H5MF_tidy_self_referential_fsm_hack(f) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "tidy of self referential fsm hack failed")
- } /* end if */
- else {
+
+
+
+ if(f->shared->closing) {
+
+ /* Get the eoa, and verify that it has the expected value */
+ if(HADDR_UNDEF == (final_eoa = H5FD_get_eoa(f->shared->lf, H5FD_MEM_DEFAULT)) )
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTGET, FAIL, "unable to get file size")
+
+ HDassert(H5F_addr_eq(final_eoa, mesg->addr + mesg->size));
+
+ if(H5FD_free(f->shared->lf, H5FD_MEM_SUPER, f, mesg->addr, mesg->size) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFREE, FAIL, "can't free MDC image")
+ } else {
if(H5MF_xfree(f, H5FD_MEM_SUPER, mesg->addr, mesg->size) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free file space for cache image block")
- } /* end else */
+ }
+
} /* end if */
done:
diff --git a/src/H5Ochunk.c b/src/H5Ochunk.c
index 94301b3..9ce5a46 100644
--- a/src/H5Ochunk.c
+++ b/src/H5Ochunk.c
@@ -331,7 +331,7 @@ H5O__chunk_update_idx(H5F_t *f, H5O_t *oh, unsigned idx)
H5O_chk_cache_ud_t chk_udata; /* User data for loading chunk */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_PACKAGE
+ FUNC_ENTER_PACKAGE_TAG(oh->cache_info.addr)
/* check args */
HDassert(f);
diff --git a/src/H5Ocopy.c b/src/H5Ocopy.c
index 1ba4901..6e0db25 100644
--- a/src/H5Ocopy.c
+++ b/src/H5Ocopy.c
@@ -43,6 +43,7 @@
#include "H5MMprivate.h" /* Memory management */
#include "H5Opkg.h" /* Object headers */
#include "H5Pprivate.h" /* Property lists */
+#include "H5VLprivate.h" /* Virtual Object Layer */
/****************/
@@ -84,8 +85,6 @@ static herr_t H5O__copy_header(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*
hid_t ocpypl_id, hid_t lcpl_id);
static herr_t H5O__copy_obj(H5G_loc_t *src_loc, H5G_loc_t *dst_loc,
const char *dst_name, hid_t ocpypl_id, hid_t lcpl_id);
-static herr_t H5O__copy_obj_by_ref(H5O_loc_t *src_oloc, H5O_loc_t *dst_oloc,
- H5G_loc_t *dst_root_loc, H5O_copy_t *cpy_info);
static herr_t H5O__copy_free_comm_dt_cb(void *item, void *key, void *op_data);
static int H5O__copy_comm_dt_cmp(const void *dt1, const void *dt2);
static herr_t H5O__copy_search_comm_dt_cb(hid_t group, const char *name,
@@ -109,7 +108,6 @@ H5FL_DEFINE(H5O_copy_search_comm_dt_key_t);
/* Declare a free list to manage haddr_t variables */
H5FL_DEFINE(haddr_t);
-
/*****************************/
/* Library Private Variables */
/*****************************/
@@ -197,10 +195,12 @@ H5FL_DEFINE(haddr_t);
*/
herr_t
H5Ocopy(hid_t src_loc_id, const char *src_name, hid_t dst_loc_id,
- const char *dst_name, hid_t ocpypl_id, hid_t lcpl_id)
+ const char *dst_name, hid_t ocpypl_id, hid_t lcpl_id)
{
- H5G_loc_t loc; /* Source group group location */
- H5G_loc_t dst_loc; /* Destination group location */
+ H5VL_object_t *vol_obj1 = NULL; /* object token of src_id */
+ H5VL_loc_params_t loc_params1;
+ H5VL_object_t *vol_obj2 = NULL; /* object token of dst_id */
+ H5VL_loc_params_t loc_params2;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -208,10 +208,6 @@ H5Ocopy(hid_t src_loc_id, const char *src_name, hid_t dst_loc_id,
ocpypl_id, lcpl_id);
/* Check arguments */
- if(H5G_loc(src_loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
- if(H5G_loc(dst_loc_id, &dst_loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!src_name || !*src_name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no source name specified")
if(!dst_name || !*dst_name)
@@ -235,8 +231,20 @@ H5Ocopy(hid_t src_loc_id, const char *src_name, hid_t dst_loc_id,
if(H5CX_set_loc(src_loc_id) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set collective metadata read info")
+ /* get the object */
+ if(NULL == (vol_obj1 = (H5VL_object_t *)H5I_object(src_loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+ loc_params1.type = H5VL_OBJECT_BY_SELF;
+ loc_params1.obj_type = H5I_get_type(src_loc_id);
+
+ /* get the object */
+ if(NULL == (vol_obj2 = (H5VL_object_t *)H5I_object(dst_loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+ loc_params2.type = H5VL_OBJECT_BY_SELF;
+ loc_params2.obj_type = H5I_get_type(dst_loc_id);
+
/* Copy the object */
- if(H5O_copy(&loc, src_name, &dst_loc, dst_name, ocpypl_id, lcpl_id) < 0)
+ if(H5VL_object_copy(vol_obj1, &loc_params1, src_name, vol_obj2, &loc_params2, dst_name, ocpypl_id, lcpl_id, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object")
done:
@@ -721,7 +729,7 @@ H5O__copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out*/,
* header. This will be written when the header is flushed to disk.
*/
if(oh_dst->version > H5O_VERSION_1)
- HDmemcpy(current_pos, H5O_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ H5MM_memcpy(current_pos, H5O_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
current_pos += H5O_SIZEOF_HDR(oh_dst) - H5O_SIZEOF_CHKSUM_OH(oh_dst);
/* Loop through destination messages, updating their "raw" info */
@@ -744,7 +752,7 @@ H5O__copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out*/,
/* Copy each message that wasn't dirtied above */
if(!mesg_dst->dirty)
/* Copy the message header plus the message's raw data. */
- HDmemcpy(current_pos, mesg_src->raw - msghdr_size, msghdr_size + mesg_src->raw_size);
+ H5MM_memcpy(current_pos, mesg_src->raw - msghdr_size, msghdr_size + mesg_src->raw_size);
/* Set message's raw pointer to destination chunk's new "image" */
mesg_dst->raw = current_pos + msghdr_size;
@@ -1224,201 +1232,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5O__copy_obj_by_ref
- *
- * Purpose: Copy the object pointed by _src_ref.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Peter Cao
- * Aug 7 2006
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5O__copy_obj_by_ref(H5O_loc_t *src_oloc, H5O_loc_t *dst_oloc,
- H5G_loc_t *dst_root_loc, H5O_copy_t *cpy_info)
-{
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_STATIC
-
- HDassert(src_oloc);
- HDassert(dst_oloc);
-
- /* Perform the copy, or look up existing copy */
- if((ret_value = H5O_copy_header_map(src_oloc, dst_oloc, cpy_info, FALSE, NULL, NULL)) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object")
-
- /* Check if a new valid object is copied to the destination */
- if(H5F_addr_defined(dst_oloc->addr) && (ret_value > SUCCEED)) {
- char tmp_obj_name[80];
- H5G_name_t new_path;
- H5O_loc_t new_oloc;
- H5G_loc_t new_loc;
-
- /* Set up group location for new object */
- new_loc.oloc = &new_oloc;
- new_loc.path = &new_path;
- H5G_loc_reset(&new_loc);
- new_oloc.file = dst_oloc->file;
- new_oloc.addr = dst_oloc->addr;
-
- /* Pick a default name for the new object */
- HDsnprintf(tmp_obj_name, sizeof(tmp_obj_name), "~obj_pointed_by_%llu", (unsigned long long)dst_oloc->addr);
-
- /* Create a link to the newly copied object */
- /* Note: since H5O_copy_header_map actually copied the target object, it
- * must exist either in cache or on disk, therefore it is is safe to not
- * pass the obj_type and udata fields returned by H5O_copy_header_map.
- * This could be changed in the future to slightly improve performance
- * --NAF */
- if(H5L_link(dst_root_loc, tmp_obj_name, &new_loc, cpy_info->lcpl_id) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to insert link")
-
- H5G_loc_free(&new_loc);
- } /* if (H5F_addr_defined(dst_oloc.addr)) */
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5O__copy_obj_by_ref() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5O_copy_expand_ref
- *
- * Purpose: Copy the object pointed by _src_ref.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Peter Cao
- * Aug 7 2006
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5O_copy_expand_ref(H5F_t *file_src, void *_src_ref, H5F_t *file_dst,
- void *_dst_ref, size_t ref_count, H5R_type_t ref_type, H5O_copy_t *cpy_info)
-{
- H5O_loc_t dst_oloc; /* Copied object object location */
- H5O_loc_t src_oloc; /* Temporary object location for source object */
- H5G_loc_t dst_root_loc; /* The location of root group of the destination file */
- const uint8_t *q; /* Pointer to source OID to store */
- uint8_t *p; /* Pointer to destination OID to store */
- size_t i; /* Local index variable */
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI(FAIL)
-
- /* Sanity checks */
- HDassert(file_src);
- HDassert(_src_ref);
- HDassert(file_dst);
- HDassert(_dst_ref);
- HDassert(ref_count);
- HDassert(cpy_info);
-
- /* Initialize object locations */
- H5O_loc_reset(&src_oloc);
- H5O_loc_reset(&dst_oloc);
- src_oloc.file = file_src;
- dst_oloc.file = file_dst;
-
- /* Set up the root group in the destination file */
- if(NULL == (dst_root_loc.oloc = H5G_oloc(H5G_rootof(file_dst))))
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get object location for root group")
- if(NULL == (dst_root_loc.path = H5G_nameof(H5G_rootof(file_dst))))
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get path for root group")
-
- /* Copy object references */
- if(H5R_OBJECT == ref_type) {
- hobj_ref_t *src_ref = (hobj_ref_t *)_src_ref;
- hobj_ref_t *dst_ref = (hobj_ref_t *)_dst_ref;
-
- /* Making equivalent references in the destination file */
- for(i = 0; i < ref_count; i++) {
- /* Set up for the object copy for the reference */
- q = (uint8_t *)(&src_ref[i]);
- H5F_addr_decode(src_oloc.file, (const uint8_t **)&q, &(src_oloc.addr));
- dst_oloc.addr = HADDR_UNDEF;
-
- /* Attempt to copy object from source to destination file */
- if(src_oloc.addr != (haddr_t)0) {
- if(H5O__copy_obj_by_ref(&src_oloc, &dst_oloc, &dst_root_loc, cpy_info) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object")
- } /* end if */
- else
- /* Set parameters so the reference is written as all 0's */
- HDmemset(&dst_oloc.addr, 0, sizeof(dst_oloc.addr));
-
- /* Set the object reference info for the destination file */
- p = (uint8_t *)(&dst_ref[i]);
- H5F_addr_encode(dst_oloc.file, &p, dst_oloc.addr);
- } /* end for */
- } /* end if */
- /* Copy region references */
- else if(H5R_DATASET_REGION == ref_type) {
- hdset_reg_ref_t *src_ref = (hdset_reg_ref_t *)_src_ref;
- hdset_reg_ref_t *dst_ref = (hdset_reg_ref_t *)_dst_ref;
- uint8_t *buf = NULL; /* Buffer to store serialized selection in */
- H5HG_t hobjid; /* Heap object ID */
- size_t buf_size; /* Length of object in heap */
-
- /* Making equivalent references in the destination file */
- for(i = 0; i < ref_count; i++) {
- /* Get the heap ID for the dataset region */
- q = (const uint8_t *)(&src_ref[i]);
- H5F_addr_decode(src_oloc.file, (const uint8_t **)&q, &(hobjid.addr));
- UINT32DECODE(q, hobjid.idx);
-
- if(hobjid.addr != (haddr_t)0) {
- /* Get the dataset region from the heap (allocate inside routine) */
- if((buf = (uint8_t *)H5HG_read(src_oloc.file, &hobjid, NULL, &buf_size)) == NULL)
- HGOTO_ERROR(H5E_REFERENCE, H5E_READERROR, FAIL, "Unable to read dataset region information")
-
- /* Get the object oid for the dataset */
- q = (const uint8_t *)buf;
- H5F_addr_decode(src_oloc.file, (const uint8_t **)&q, &(src_oloc.addr));
- dst_oloc.addr = HADDR_UNDEF;
-
- /* copy the object pointed by the ref to the destination */
- if(H5O__copy_obj_by_ref(&src_oloc, &dst_oloc, &dst_root_loc, cpy_info) < 0) {
- H5MM_xfree(buf);
- HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object")
- } /* end if */
-
- /* Serialize object ID */
- p = (uint8_t *)buf;
- H5F_addr_encode(dst_oloc.file, &p, dst_oloc.addr);
-
- /* Save the serialized buffer to the destination */
- if(H5HG_insert(dst_oloc.file, buf_size, buf, &hobjid) < 0) {
- H5MM_xfree(buf);
- HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "Unable to write dataset region information")
- } /* end if */
- } /* end if */
- else
- /* Set parameters so the reference is written as all 0's */
- HDmemset(&hobjid, 0, sizeof(hobjid));
-
- /* Set the dataset region reference info for the destination file */
- p = (uint8_t *)(&dst_ref[i]);
- H5F_addr_encode(dst_oloc.file, &p, hobjid.addr);
- UINT32ENCODE(p, hobjid.idx);
-
- /* Free the buffer allocated in H5HG_read() */
- H5MM_xfree(buf);
- } /* end for */
- } /* end if */
- else
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid reference type")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5O_copy_expand_ref() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5O__copy_free_comm_dt_cb
*
* Purpose: Frees the merge committed dt skip list key and object.
@@ -1784,7 +1597,7 @@ H5O__copy_search_comm_dt(H5F_t *file_src, H5O_t *oh_src,
HDassert(oh_src);
HDassert(oloc_dst);
HDassert(oloc_dst->file);
- HDassert(H5F_FILE_ID(oloc_dst->file) >= 0);
+ HDassert(H5F_ID_EXISTS(oloc_dst->file));
HDassert(cpy_info);
/* Allocate key */
diff --git a/src/H5Ocopy_ref.c b/src/H5Ocopy_ref.c
new file mode 100644
index 0000000..3b18073
--- /dev/null
+++ b/src/H5Ocopy_ref.c
@@ -0,0 +1,498 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5Ocopy_ref.c
+ *
+ * Purpose: Object with references copying routines.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#include "H5Omodule.h" /* This source code file is part of the H5O module */
+#define H5F_FRIEND /* Suppress error about including H5Fpkg */
+#define H5R_FRIEND /* Suppress error about including H5Rpkg */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Fpkg.h" /* File */
+#include "H5Iprivate.h" /* IDs */
+#include "H5Lprivate.h" /* Links */
+#include "H5MMprivate.h" /* Memory management */
+#include "H5Opkg.h" /* Object headers */
+#include "H5Rpkg.h" /* References */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+static herr_t H5O__copy_obj_by_ref(H5O_loc_t *src_oloc, H5O_loc_t *dst_oloc,
+ H5G_loc_t *dst_root_loc, H5O_copy_t *cpy_info);
+static herr_t H5O__copy_expand_ref_object1(H5O_loc_t *src_oloc,
+ const void *buf_src, H5O_loc_t *dst_oloc, H5G_loc_t *dst_root_loc,
+ void *buf_dst, size_t ref_count, H5O_copy_t *cpy_info);
+static herr_t H5O__copy_expand_ref_region1(H5O_loc_t *src_oloc,
+ const void *buf_src, H5O_loc_t *dst_oloc, H5G_loc_t *dst_root_loc,
+ void *buf_dst, size_t ref_count, H5O_copy_t *cpy_info);
+static herr_t H5O__copy_expand_ref_object2(H5O_loc_t *src_oloc, hid_t tid_src,
+ H5T_t *dt_src, const void *buf_src, size_t nbytes_src, H5O_loc_t *dst_oloc,
+ H5G_loc_t *dst_root_loc, void *buf_dst, size_t ref_count,
+ H5O_copy_t *cpy_info);
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+/* Declare extern the free list to manage blocks of type conversion data */
+H5FL_BLK_EXTERN(type_conv);
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O__copy_obj_by_ref
+ *
+ * Purpose: Copy the object pointed to by src_oloc.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O__copy_obj_by_ref(H5O_loc_t *src_oloc, H5O_loc_t *dst_oloc,
+ H5G_loc_t *dst_root_loc, H5O_copy_t *cpy_info)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ HDassert(src_oloc);
+ HDassert(dst_oloc);
+
+ /* Perform the copy, or look up existing copy */
+ if((ret_value = H5O_copy_header_map(src_oloc, dst_oloc, cpy_info, FALSE, NULL, NULL)) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object")
+
+ /* Check if a new valid object is copied to the destination */
+ if(H5F_addr_defined(dst_oloc->addr) && (ret_value > SUCCEED)) {
+ char tmp_obj_name[80];
+ H5G_name_t new_path;
+ H5O_loc_t new_oloc;
+ H5G_loc_t new_loc;
+
+ /* Set up group location for new object */
+ new_loc.oloc = &new_oloc;
+ new_loc.path = &new_path;
+ H5G_loc_reset(&new_loc);
+ new_oloc.file = dst_oloc->file;
+ new_oloc.addr = dst_oloc->addr;
+
+ /* Pick a default name for the new object */
+ HDsnprintf(tmp_obj_name, sizeof(tmp_obj_name), "~obj_pointed_by_%llu", (unsigned long long)dst_oloc->addr);
+
+ /* Create a link to the newly copied object */
+ /* Note: since H5O_copy_header_map actually copied the target object, it
+ * must exist either in cache or on disk, therefore it is is safe to not
+ * pass the obj_type and udata fields returned by H5O_copy_header_map.
+ * This could be changed in the future to slightly improve performance
+ * --NAF */
+ if(H5L_link(dst_root_loc, tmp_obj_name, &new_loc, cpy_info->lcpl_id) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to insert link")
+
+ H5G_loc_free(&new_loc);
+ } /* if (H5F_addr_defined(dst_oloc.addr)) */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O__copy_obj_by_ref() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O__copy_expand_ref_object1
+ *
+ * Purpose: Copy the object pointed by a deprecated object reference.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O__copy_expand_ref_object1(H5O_loc_t *src_oloc, const void *buf_src,
+ H5O_loc_t *dst_oloc, H5G_loc_t *dst_root_loc, void *buf_dst,
+ size_t ref_count, H5O_copy_t *cpy_info)
+{
+ const hobj_ref_t *src_ref = (const hobj_ref_t *)buf_src;
+ hobj_ref_t *dst_ref = (hobj_ref_t *)buf_dst;
+ const unsigned char zeros[H5R_OBJ_REF_BUF_SIZE] = { 0 };
+ size_t buf_size = H5R_OBJ_REF_BUF_SIZE;
+ size_t i; /* Local index variable */
+ size_t token_size = H5F_SIZEOF_ADDR(src_oloc->file);
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Making equivalent references in the destination file */
+ for(i = 0; i < ref_count; i++) {
+ const unsigned char *src_buf = (const unsigned char *)&src_ref[i];
+ unsigned char *dst_buf = (unsigned char *)&dst_ref[i];
+ H5VL_token_t tmp_token = { 0 };
+ uint8_t *p;
+
+ /* If data is not initialized, copy zeros and skip */
+ if(0 == HDmemcmp(src_buf, zeros, buf_size)) {
+ HDmemset(dst_buf, 0, buf_size);
+ continue;
+ }
+
+ /* Set up for the object copy for the reference */
+ if(H5R__decode_token_obj_compat(src_buf, &buf_size, &tmp_token, token_size) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, FAIL, "unable to decode src object address")
+ p = tmp_token;
+ H5F_addr_decode(src_oloc->file, (const uint8_t **)&p, &src_oloc->addr);
+ if(!H5F_addr_defined(src_oloc->addr) || src_oloc->addr == 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "undefined reference pointer")
+ dst_oloc->addr = HADDR_UNDEF;
+
+ /* Attempt to copy object from source to destination file */
+ if(H5O__copy_obj_by_ref(src_oloc, dst_oloc, dst_root_loc, cpy_info) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object")
+
+ /* Set the object reference info for the destination file */
+ p = tmp_token;
+ H5F_addr_encode(dst_oloc->file, &p, dst_oloc->addr);
+ if(H5R__encode_token_obj_compat((const H5VL_token_t *)&tmp_token, token_size, dst_buf, &buf_size) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, FAIL, "unable to encode dst object address")
+ } /* end for */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O__copy_expand_ref_object1() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O__copy_expand_ref_region1
+ *
+ * Purpose: Copy the object pointed by a deprecated region reference.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O__copy_expand_ref_region1(H5O_loc_t *src_oloc, const void *buf_src,
+ H5O_loc_t *dst_oloc, H5G_loc_t *dst_root_loc, void *buf_dst,
+ size_t ref_count, H5O_copy_t *cpy_info)
+{
+ const hdset_reg_ref_t *src_ref = (const hdset_reg_ref_t *)buf_src;
+ hdset_reg_ref_t *dst_ref = (hdset_reg_ref_t *)buf_dst;
+ const unsigned char zeros[H5R_DSET_REG_REF_BUF_SIZE] = { 0 };
+ size_t buf_size = H5R_DSET_REG_REF_BUF_SIZE;
+ size_t i; /* Local index variable */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Making equivalent references in the destination file */
+ for(i = 0; i < ref_count; i++) {
+ const unsigned char *src_buf = (const unsigned char *)&src_ref[i];
+ unsigned char *dst_buf = (unsigned char *)&dst_ref[i];
+ unsigned char *data = NULL;
+ size_t data_size;
+ const uint8_t *p;
+ uint8_t *q;
+
+ /* If data is not initialized, copy zeros and skip */
+ if(0 == HDmemcmp(src_buf, zeros, buf_size)) {
+ HDmemset(dst_buf, 0, buf_size);
+ continue;
+ }
+
+ /* Read from heap */
+ if(H5R__decode_heap(src_oloc->file, src_buf, &buf_size, &data, &data_size) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, FAIL, "unable to decode dataset region information")
+
+ /* Get object address */
+ p = (const uint8_t *)data;
+ H5F_addr_decode(src_oloc->file, &p, &src_oloc->addr);
+ if(!H5F_addr_defined(src_oloc->addr) || src_oloc->addr == 0) {
+ H5MM_free(data);
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "undefined reference pointer")
+ }
+ dst_oloc->addr = HADDR_UNDEF;
+
+ /* Attempt to copy object from source to destination file */
+ if(H5O__copy_obj_by_ref(src_oloc, dst_oloc, dst_root_loc, cpy_info) < 0) {
+ H5MM_free(data);
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object")
+ } /* end if */
+
+ /* Serialize object addr */
+ q = (uint8_t *)data;
+ H5F_addr_encode(dst_oloc->file, &q, dst_oloc->addr);
+
+ /* Write to heap */
+ if(H5R__encode_heap(dst_oloc->file, dst_buf, &buf_size, data, (size_t)data_size) < 0) {
+ H5MM_free(data);
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, FAIL, "unable to encode dataset region information")
+ }
+
+ /* Free the buffer allocated in H5R__decode_heap() */
+ H5MM_free(data);
+ } /* end for */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O__copy_expand_ref_region1() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O__copy_expand_ref_object2
+ *
+ * Purpose: Copy the object pointed by a reference (object, region, attribute).
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O__copy_expand_ref_object2(H5O_loc_t *src_oloc, hid_t tid_src, H5T_t *dt_src,
+ const void *buf_src, size_t nbytes_src, H5O_loc_t *dst_oloc,
+ H5G_loc_t *dst_root_loc, void *buf_dst, size_t ref_count,
+ H5O_copy_t *cpy_info)
+{
+ H5T_t *dt_mem = NULL; /* Memory datatype */
+ H5T_t *dt_dst = NULL; /* Destination datatype */
+ hid_t tid_mem = H5I_INVALID_HID; /* Datatype ID for memory datatype */
+ hid_t tid_dst = H5I_INVALID_HID; /* Datatype ID for memory datatype */
+ H5T_path_t *tpath_src_mem = NULL,
+ *tpath_mem_dst = NULL; /* Datatype conversion paths */
+ size_t i; /* Local index variable */
+ hbool_t reg_tid_src = (tid_src == H5I_INVALID_HID);
+ hid_t dst_loc_id = H5I_INVALID_HID;
+ void *conv_buf = NULL; /* Buffer for converting data */
+ size_t conv_buf_size = 0; /* Buffer size */
+ void *reclaim_buf = NULL; /* Buffer for reclaiming data */
+ H5S_t *buf_space = NULL; /* Dataspace describing buffer */
+ hsize_t buf_dim[1] = {ref_count}; /* Dimension for buffer */
+ size_t token_size = H5F_SIZEOF_ADDR(src_oloc->file);
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Create datatype ID for src datatype. */
+ if((tid_src == H5I_INVALID_HID) && (tid_src = H5I_register(H5I_DATATYPE, dt_src, FALSE)) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTREGISTER, FAIL, "unable to register source file datatype")
+
+ /* create a memory copy of the reference datatype */
+ if(NULL == (dt_mem = H5T_copy(dt_src, H5T_COPY_TRANSIENT)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to copy")
+ if((tid_mem = H5I_register(H5I_DATATYPE, dt_mem, FALSE)) < 0) {
+ (void)H5T_close_real(dt_mem);
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTREGISTER, FAIL, "unable to register memory datatype")
+ } /* end if */
+
+ /* create reference datatype at the destinaton file */
+ if(NULL == (dt_dst = H5T_copy(dt_src, H5T_COPY_TRANSIENT)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to copy")
+ if(H5T_set_loc(dt_dst, dst_oloc->file, H5T_LOC_DISK) < 0) {
+ (void)H5T_close_real(dt_dst);
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "cannot mark datatype on disk")
+ } /* end if */
+ if((tid_dst = H5I_register(H5I_DATATYPE, dt_dst, FALSE)) < 0) {
+ (void)H5T_close_real(dt_dst);
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTREGISTER, FAIL, "unable to register destination file datatype")
+ } /* end if */
+
+ /* Set up the conversion functions */
+ if(NULL == (tpath_src_mem = H5T_path_find(dt_src, dt_mem)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to convert between src and mem datatypes")
+ if(NULL == (tpath_mem_dst = H5T_path_find(dt_mem, dt_dst)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to convert between mem and dst datatypes")
+
+ /* Use extra conversion buffer (TODO we should avoid using an extra buffer once the H5Ocopy code has been reworked) */
+ conv_buf_size = MAX(H5T_get_size(dt_src), H5T_get_size(dt_mem)) * ref_count;
+ if(NULL == (conv_buf = H5FL_BLK_MALLOC(type_conv, conv_buf_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for copy buffer")
+ H5MM_memcpy(conv_buf, buf_src, nbytes_src);
+
+ /* Convert from source file to memory */
+ if(H5T_convert(tpath_src_mem, tid_src, tid_mem, ref_count, (size_t)0, (size_t)0, conv_buf, NULL) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTCONVERT, FAIL, "datatype conversion failed")
+
+ /* Retrieve loc ID */
+ if((dst_loc_id = H5F__get_file_id(dst_oloc->file, FALSE)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+
+ /* Making equivalent references in the destination file */
+ for(i = 0; i < ref_count; i++) {
+ H5R_ref_t *ref_ptr = (H5R_ref_t *)conv_buf;
+ H5R_ref_priv_t *ref = (H5R_ref_priv_t *)&ref_ptr[i];
+ H5VL_token_t tmp_token = { 0 };
+ uint8_t *p;
+
+ /* Get src object address */
+ if(H5R__get_obj_token(ref, &tmp_token, &token_size) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to get object token")
+ p = tmp_token;
+ H5F_addr_decode(src_oloc->file, (const uint8_t **)&p, &src_oloc->addr);
+
+ /* Attempt to copy object from source to destination file */
+ if(H5O__copy_obj_by_ref(src_oloc, dst_oloc, dst_root_loc, cpy_info) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object")
+
+ /* Set dst object address */
+ p = tmp_token;
+ H5F_addr_encode(dst_oloc->file, &p, dst_oloc->addr);
+ if(H5R__set_obj_token(ref, (const H5VL_token_t *)&tmp_token, token_size) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "unable to set object token")
+ if(H5R__set_loc_id(ref, dst_loc_id, TRUE) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "unable to set destination loc id")
+ } /* end for */
+
+ /* Copy into another buffer, to reclaim memory later */
+ if(NULL == (reclaim_buf = H5FL_BLK_MALLOC(type_conv, conv_buf_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for copy buffer")
+ H5MM_memcpy(reclaim_buf, conv_buf, conv_buf_size);
+ if(NULL == (buf_space = H5S_create_simple((unsigned)1, buf_dim, NULL)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTCREATE, FAIL, "can't create simple dataspace")
+
+ /* Convert from memory to destination file */
+ if(H5T_convert(tpath_mem_dst, tid_mem, tid_dst, ref_count, (size_t)0, (size_t)0, conv_buf, NULL) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTCONVERT, FAIL, "datatype conversion failed")
+ H5MM_memcpy(buf_dst, conv_buf, nbytes_src);
+
+ /* Reclaim space from reference data */
+ if(H5T_reclaim(tid_mem, buf_space, reclaim_buf) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "unable to reclaim reference data")
+
+done:
+ if(buf_space && (H5S_close(buf_space) < 0))
+ HDONE_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "Can't close dataspace")
+ /* Don't decrement ID, we want to keep underlying datatype */
+ if(reg_tid_src && (tid_src > 0) && (NULL == H5I_remove(tid_src)))
+ HDONE_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "Can't decrement temporary datatype ID")
+ if((tid_mem > 0) && H5I_dec_ref(tid_mem) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "Can't decrement temporary datatype ID")
+ if((tid_dst > 0) && H5I_dec_ref(tid_dst) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "Can't decrement temporary datatype ID")
+ if(reclaim_buf)
+ reclaim_buf = H5FL_BLK_FREE(type_conv, reclaim_buf);
+ if(conv_buf)
+ conv_buf = H5FL_BLK_FREE(type_conv, conv_buf);
+ if((dst_loc_id != H5I_INVALID_HID) && (H5I_dec_ref(dst_loc_id) < 0))
+ HDONE_ERROR(H5E_OHDR, H5E_CANTDEC, FAIL, "unable to decrement refcount on location id")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O__copy_expand_ref_object2() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_copy_expand_ref
+ *
+ * Purpose: Copy the object pointed by a reference.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5O_copy_expand_ref(H5F_t *file_src, hid_t tid_src, H5T_t *dt_src,
+ void *buf_src, size_t nbytes_src, H5F_t *file_dst, void *buf_dst,
+ H5O_copy_t *cpy_info)
+{
+ H5O_loc_t dst_oloc; /* Copied object object location */
+ H5O_loc_t src_oloc; /* Temporary object location for source object */
+ H5G_loc_t dst_root_loc; /* The location of root group of the destination file */
+ size_t ref_count;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(file_src);
+ HDassert(buf_src);
+ HDassert(file_dst);
+ HDassert(buf_dst);
+ HDassert(nbytes_src);
+ HDassert(cpy_info);
+
+ /* Initialize object locations */
+ H5O_loc_reset(&src_oloc);
+ H5O_loc_reset(&dst_oloc);
+ src_oloc.file = file_src;
+ dst_oloc.file = file_dst;
+
+ /* Set up the root group in the destination file */
+ if(NULL == (dst_root_loc.oloc = H5G_oloc(H5G_rootof(file_dst))))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get object location for root group")
+ if(NULL == (dst_root_loc.path = H5G_nameof(H5G_rootof(file_dst))))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get path for root group")
+
+ /* Determine # of reference elements to copy */
+ ref_count = nbytes_src / H5T_get_size(dt_src);
+
+ /* Copy object references */
+ switch(H5T_get_ref_type(dt_src)) {
+ case H5R_OBJECT1:
+ if(H5O__copy_expand_ref_object1(&src_oloc, buf_src, &dst_oloc, &dst_root_loc, buf_dst, ref_count, cpy_info) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "unable to expand H5R_OBJECT1 reference")
+ break;
+ case H5R_DATASET_REGION1:
+ if(H5O__copy_expand_ref_region1(&src_oloc, buf_src, &dst_oloc, &dst_root_loc, buf_dst, ref_count, cpy_info) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "unable to expand H5R_DATASET_REGION1 reference")
+ break;
+ case H5R_DATASET_REGION2:
+ case H5R_ATTR:
+ case H5R_OBJECT2:
+ if(H5O__copy_expand_ref_object2(&src_oloc, tid_src, dt_src, buf_src, nbytes_src, &dst_oloc, &dst_root_loc, buf_dst, ref_count, cpy_info) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "unable to expand reference")
+ break;
+ case H5R_BADTYPE:
+ case H5R_MAXTYPE:
+ default:
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid reference type")
+ break;
+ } /* end switch */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_copy_expand_ref() */
diff --git a/src/H5Odeprec.c b/src/H5Odeprec.c
index 3441d8b..7aefc67 100644
--- a/src/H5Odeprec.c
+++ b/src/H5Odeprec.c
@@ -34,8 +34,11 @@
#include "H5private.h" /* Generic Functions */
#include "H5CXprivate.h" /* API Contexts */
#include "H5Eprivate.h" /* Error handling */
+#include "H5Iprivate.h" /* IDs */
#include "H5Opkg.h" /* Object headers */
+#include "H5VLnative_private.h" /* Native VOL connector */
+
/****************/
/* Local Macros */
@@ -88,20 +91,27 @@
herr_t
H5Oget_info1(hid_t loc_id, H5O_info_t *oinfo)
{
- H5G_loc_t loc; /* Location of group */
+ H5VL_object_t *vol_obj = NULL; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE2("e", "i*x", loc_id, oinfo);
/* Check args */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!oinfo)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "oinfo parameter cannot be NULL")
+ /* Set location struct fields */
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* Get the location object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
/* Retrieve the object's information */
- if(H5G_loc_info(&loc, ".", oinfo/*out*/, H5O_INFO_ALL) < 0)
+ if(H5VL_object_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_OBJECT_GET_INFO, &loc_params, oinfo, H5O_INFO_ALL) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't get info for object")
done:
@@ -122,15 +132,14 @@ done:
herr_t
H5Oget_info_by_name1(hid_t loc_id, const char *name, H5O_info_t *oinfo, hid_t lapl_id)
{
- H5G_loc_t loc; /* Location of group */
+ H5VL_object_t *vol_obj = NULL; /* object token of loc_id */
+ H5VL_loc_params_t loc_params;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE4("e", "i*s*xi", loc_id, name, oinfo, lapl_id);
/* Check args */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "name parameter cannot be NULL")
if(!*name)
@@ -142,8 +151,18 @@ H5Oget_info_by_name1(hid_t loc_id, const char *name, H5O_info_t *oinfo, hid_t la
if(H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, FALSE) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set access property list info")
+ /* Fill out location struct */
+ loc_params.type = H5VL_OBJECT_BY_NAME;
+ loc_params.loc_data.loc_by_name.name = name;
+ loc_params.loc_data.loc_by_name.lapl_id = lapl_id;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* Get the location object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
/* Retrieve the object's information */
- if(H5G_loc_info(&loc, name, oinfo/*out*/, H5O_INFO_ALL) < 0)
+ if(H5VL_object_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_OBJECT_GET_INFO, &loc_params, oinfo, H5O_INFO_ALL) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't get info for object: '%s'", name)
done:
@@ -169,9 +188,8 @@ herr_t
H5Oget_info_by_idx1(hid_t loc_id, const char *group_name, H5_index_t idx_type,
H5_iter_order_t order, hsize_t n, H5O_info_t *oinfo, hid_t lapl_id)
{
- H5G_loc_t loc; /* Location of group */
- H5G_loc_t obj_loc; /* Location used to open group */
- hbool_t loc_found = FALSE; /* Entry at 'name' found */
+ H5VL_object_t *vol_obj = NULL; /* object token of loc_id */
+ H5VL_loc_params_t loc_params;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -179,8 +197,6 @@ H5Oget_info_by_idx1(hid_t loc_id, const char *group_name, H5_index_t idx_type,
lapl_id);
/* Check args */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!group_name || !*group_name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified")
if(idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N)
@@ -194,15 +210,23 @@ H5Oget_info_by_idx1(hid_t loc_id, const char *group_name, H5_index_t idx_type,
if(H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, FALSE) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set access property list info")
+ loc_params.type = H5VL_OBJECT_BY_IDX;
+ loc_params.loc_data.loc_by_idx.name = group_name;
+ loc_params.loc_data.loc_by_idx.idx_type = idx_type;
+ loc_params.loc_data.loc_by_idx.order = order;
+ loc_params.loc_data.loc_by_idx.n = n;
+ loc_params.loc_data.loc_by_idx.lapl_id = lapl_id;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* Get the location object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
/* Retrieve the object's information */
- if(H5O__get_info_by_idx(&loc, group_name, idx_type, order, n, oinfo, H5O_INFO_ALL) < 0)
+ if(H5VL_object_optional(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5VL_NATIVE_OBJECT_GET_INFO, &loc_params, oinfo, H5O_INFO_ALL) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't get info for object")
done:
- /* Release the object location */
- if(loc_found && H5G_loc_free(&obj_loc) < 0)
- HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "can't free location")
-
FUNC_LEAVE_API(ret_value)
} /* end H5Oget_info_by_idx1() */
@@ -243,15 +267,14 @@ herr_t
H5Ovisit1(hid_t obj_id, H5_index_t idx_type, H5_iter_order_t order,
H5O_iterate_t op, void *op_data)
{
- H5G_loc_t loc;
+ H5VL_object_t *vol_obj = NULL; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
herr_t ret_value; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE5("e", "iIiIox*x", obj_id, idx_type, order, op, op_data);
/* Check args */
- if(H5G_loc(obj_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index type specified")
if(order <= H5_ITER_UNKNOWN || order >= H5_ITER_N)
@@ -259,8 +282,16 @@ H5Ovisit1(hid_t obj_id, H5_index_t idx_type, H5_iter_order_t order,
if(!op)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no callback operator specified")
+ /* Get the location object */
+ if(NULL == (vol_obj = H5VL_vol_object(obj_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Set location parameters */
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(obj_id);
+
/* Visit the objects */
- if((ret_value = H5O__visit(&loc, ".", idx_type, order, op, op_data, H5O_INFO_ALL)) < 0)
+ if((ret_value = H5VL_object_specific(vol_obj, &loc_params, H5VL_OBJECT_VISIT, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, (int)idx_type, (int)order, op, op_data, H5O_INFO_ALL)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "object visitation failed")
done:
@@ -304,7 +335,8 @@ herr_t
H5Ovisit_by_name1(hid_t loc_id, const char *obj_name, H5_index_t idx_type,
H5_iter_order_t order, H5O_iterate_t op, void *op_data, hid_t lapl_id)
{
- H5G_loc_t loc;
+ H5VL_object_t *vol_obj = NULL; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
herr_t ret_value; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -312,8 +344,6 @@ H5Ovisit_by_name1(hid_t loc_id, const char *obj_name, H5_index_t idx_type,
lapl_id);
/* Check args */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!obj_name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "obj_name parameter cannot be NULL")
if(!*obj_name)
@@ -329,8 +359,18 @@ H5Ovisit_by_name1(hid_t loc_id, const char *obj_name, H5_index_t idx_type,
if(H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, FALSE) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set access property list info")
+ /* Get the location object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Set location parameters */
+ loc_params.type = H5VL_OBJECT_BY_NAME;
+ loc_params.loc_data.loc_by_name.name = obj_name;
+ loc_params.loc_data.loc_by_name.lapl_id = lapl_id;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
/* Visit the objects */
- if((ret_value = H5O__visit(&loc, obj_name, idx_type, order, op, op_data, H5O_INFO_ALL)) < 0)
+ if((ret_value = H5VL_object_specific(vol_obj, &loc_params, H5VL_OBJECT_VISIT, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, (int)idx_type, (int)order, op, op_data, H5O_INFO_ALL)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "object visitation failed")
done:
diff --git a/src/H5Odrvinfo.c b/src/H5Odrvinfo.c
index 159c950..eb678e4 100644
--- a/src/H5Odrvinfo.c
+++ b/src/H5Odrvinfo.c
@@ -101,7 +101,7 @@ H5O_drvinfo_decode(H5F_t H5_ATTR_UNUSED *f, H5O_t H5_ATTR_UNUSED *open_oh,
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for driver info message")
/* Retrieve driver name */
- HDmemcpy(mesg->name, p, 8);
+ H5MM_memcpy(mesg->name, p, 8);
mesg->name[8] = '\0';
p += 8;
@@ -116,7 +116,7 @@ H5O_drvinfo_decode(H5F_t H5_ATTR_UNUSED *f, H5O_t H5_ATTR_UNUSED *open_oh,
} /* end if */
/* Copy encoded driver info into buffer */
- HDmemcpy(mesg->buf, p, mesg->len);
+ H5MM_memcpy(mesg->buf, p, mesg->len);
/* Set return value */
ret_value = (void *)mesg;
@@ -152,11 +152,11 @@ H5O_drvinfo_encode(H5F_t H5_ATTR_UNUSED *f, hbool_t H5_ATTR_UNUSED disable_share
/* Store version, driver name, buffer length, & encoded buffer */
*p++ = H5O_DRVINFO_VERSION;
- HDmemcpy(p, mesg->name, 8);
+ H5MM_memcpy(p, mesg->name, 8);
p += 8;
HDassert(mesg->len <= 65535);
UINT16ENCODE(p, mesg->len);
- HDmemcpy(p, mesg->buf, mesg->len);
+ H5MM_memcpy(p, mesg->buf, mesg->len);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O_drvinfo_encode() */
@@ -200,7 +200,7 @@ H5O_drvinfo_copy(const void *_mesg, void *_dest)
dest = (H5O_drvinfo_t *)H5MM_xfree(dest);
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
} /* end if */
- HDmemcpy(dest->buf, mesg->buf, mesg->len);
+ H5MM_memcpy(dest->buf, mesg->buf, mesg->len);
/* Set return value */
ret_value = dest;
diff --git a/src/H5Odtype.c b/src/H5Odtype.c
index 28970d1..805df2b 100644
--- a/src/H5Odtype.c
+++ b/src/H5Odtype.c
@@ -129,7 +129,7 @@ const H5O_msg_class_t H5O_MSG_DTYPE[1] = {{
*-------------------------------------------------------------------------
*/
static htri_t
-H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **pp, H5T_t *dt)
+H5O_dtype_decode_helper(unsigned *ioflags/*in,out*/, const uint8_t **pp, H5T_t *dt)
{
unsigned flags, version;
unsigned i;
@@ -145,7 +145,7 @@ H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **p
/* Version, class & flags */
UINT32DECODE(*pp, flags);
version = (flags>>4) & 0x0f;
- if(version < H5O_DTYPE_VERSION_1 || version > H5O_DTYPE_VERSION_3)
+ if(version < H5O_DTYPE_VERSION_1 || version > H5O_DTYPE_VERSION_LATEST)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTLOAD, FAIL, "bad version number for datatype message")
dt->shared->version = version;
dt->shared->type = (H5T_class_t)(flags & 0x0f);
@@ -250,7 +250,7 @@ H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **p
HDassert(0 == (z & 0x7)); /*must be aligned*/
if(NULL == (dt->shared->u.opaque.tag = (char *)H5MM_malloc(z + 1)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
- HDmemcpy(dt->shared->u.opaque.tag, *pp, z);
+ H5MM_memcpy(dt->shared->u.opaque.tag, *pp, z);
dt->shared->u.opaque.tag[z] = '\0';
*pp += z;
break;
@@ -331,7 +331,7 @@ H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **p
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
/* Decode the field's datatype information */
- if((can_upgrade = H5O_dtype_decode_helper(f, ioflags, pp, temp_type)) < 0) {
+ if((can_upgrade = H5O_dtype_decode_helper(ioflags, pp, temp_type)) < 0) {
for(j = 0; j <= i; j++)
H5MM_xfree(dt->shared->u.compnd.memb[j].name);
H5MM_xfree(dt->shared->u.compnd.memb);
@@ -438,16 +438,28 @@ H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **p
/* Set reference type */
dt->shared->u.atomic.u.r.rtype = (H5R_type_t)(flags & 0x0f);
-
- /* Set extra information for object references, so the hobj_ref_t gets swizzled correctly */
- if(dt->shared->u.atomic.u.r.rtype == H5R_OBJECT) {
- /* Mark location this type as undefined for now. The caller function should
- * decide the location. */
- dt->shared->u.atomic.u.r.loc = H5T_LOC_BADLOC;
-
- /* This type needs conversion */
- dt->shared->force_conv = TRUE;
- } /* end if */
+ if(dt->shared->u.atomic.u.r.rtype <= H5R_BADTYPE
+ || dt->shared->u.atomic.u.r.rtype >= H5R_MAXTYPE)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, "invalid reference type");
+
+ /* Set generic flag */
+ if(dt->shared->u.atomic.u.r.rtype == H5R_OBJECT2
+ || dt->shared->u.atomic.u.r.rtype == H5R_DATASET_REGION2
+ || dt->shared->u.atomic.u.r.rtype == H5R_ATTR) {
+ dt->shared->u.atomic.u.r.opaque = TRUE;
+ dt->shared->u.atomic.u.r.version = (unsigned)((flags >> 4) & 0x0f);
+ if(dt->shared->u.atomic.u.r.version != H5R_ENCODE_VERSION)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, "reference version does not match");
+ } else
+ dt->shared->u.atomic.u.r.opaque = FALSE;
+
+ /* This type needs conversion */
+ dt->shared->force_conv = TRUE;
+
+ /* Mark location of this type as undefined for now. The caller
+ * function should decide the location. */
+ if(H5T_set_loc(dt, NULL, H5T_LOC_BADLOC) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location")
break;
case H5T_ENUM:
@@ -457,7 +469,7 @@ H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **p
dt->shared->u.enumer.nmembs = dt->shared->u.enumer.nalloc = flags & 0xffff;
if(NULL == (dt->shared->parent = H5T__alloc()))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
- if(H5O_dtype_decode_helper(f, ioflags, pp, dt->shared->parent) < 0)
+ if(H5O_dtype_decode_helper(ioflags, pp, dt->shared->parent) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, "unable to decode parent datatype")
/* Check if the parent of this enum has a version greater than the
@@ -483,7 +495,7 @@ H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **p
} /* end for */
/* Values */
- HDmemcpy(dt->shared->u.enumer.value, *pp,
+ H5MM_memcpy(dt->shared->u.enumer.value, *pp,
dt->shared->u.enumer.nmembs * dt->shared->parent->shared->size);
*pp += dt->shared->u.enumer.nmembs * dt->shared->parent->shared->size;
break;
@@ -499,7 +511,7 @@ H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **p
/* Decode base type of VL information */
if(NULL == (dt->shared->parent = H5T__alloc()))
HGOTO_ERROR(H5E_DATATYPE, H5E_NOSPACE, FAIL, "memory allocation failed")
- if(H5O_dtype_decode_helper(f, ioflags, pp, dt->shared->parent) < 0)
+ if(H5O_dtype_decode_helper(ioflags, pp, dt->shared->parent) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, "unable to decode VL parent type")
/* Check if the parent of this vlen has a version greater than the
@@ -511,7 +523,7 @@ H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **p
/* Mark location this type as undefined for now. The caller function should
* decide the location. */
- if(H5T_set_loc(dt, f, H5T_LOC_BADLOC) < 0)
+ if(H5T_set_loc(dt, NULL, H5T_LOC_BADLOC) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location")
break;
@@ -540,7 +552,7 @@ H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **p
/* Decode base type of array */
if(NULL == (dt->shared->parent = H5T__alloc()))
HGOTO_ERROR(H5E_DATATYPE, H5E_NOSPACE, FAIL, "memory allocation failed")
- if(H5O_dtype_decode_helper(f, ioflags, pp, dt->shared->parent) < 0)
+ if(H5O_dtype_decode_helper(ioflags, pp, dt->shared->parent) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, "unable to decode array parent type")
/* Check if the parent of this array has a version greater than the
@@ -596,7 +608,7 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt)
+H5O_dtype_encode_helper(uint8_t **pp, const H5T_t *dt)
{
unsigned flags = 0;
uint8_t *hdr = (uint8_t *)*pp;
@@ -882,7 +894,7 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt)
z = HDstrlen(dt->shared->u.opaque.tag);
aligned = (z + 7) & (H5T_OPAQUE_TAG_MAX - 8);
flags = (unsigned)(flags | aligned);
- HDmemcpy(*pp, dt->shared->u.opaque.tag, MIN(z,aligned));
+ H5MM_memcpy(*pp, dt->shared->u.opaque.tag, MIN(z,aligned));
for(n = MIN(z, aligned); n < aligned; n++)
(*pp)[n] = 0;
*pp += aligned;
@@ -956,7 +968,7 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt)
} /* end if */
/* Subtype */
- if(H5O_dtype_encode_helper(f, pp, dt->shared->u.compnd.memb[i].type) < 0)
+ if(H5O_dtype_encode_helper(pp, dt->shared->u.compnd.memb[i].type) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTENCODE, FAIL, "unable to encode member type")
} /* end for */
}
@@ -964,6 +976,8 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt)
case H5T_REFERENCE:
flags |= (dt->shared->u.atomic.u.r.rtype & 0x0f);
+ if(dt->shared->u.atomic.u.r.opaque)
+ flags = (unsigned)(flags | (((unsigned)dt->shared->u.atomic.u.r.version & 0x0f) << 4));
break;
case H5T_ENUM:
@@ -976,7 +990,7 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt)
flags = dt->shared->u.enumer.nmembs & 0xffff;
/* Parent type */
- if(H5O_dtype_encode_helper(f, pp, dt->shared->parent) < 0)
+ if(H5O_dtype_encode_helper(pp, dt->shared->parent) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTENCODE, FAIL, "unable to encode parent datatype")
/* Names, each a multiple of eight bytes */
@@ -997,7 +1011,7 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt)
} /* end for */
/* Values */
- HDmemcpy(*pp, dt->shared->u.enumer.value, dt->shared->u.enumer.nmembs * dt->shared->parent->shared->size);
+ H5MM_memcpy(*pp, dt->shared->u.enumer.value, dt->shared->u.enumer.nmembs * dt->shared->parent->shared->size);
*pp += dt->shared->u.enumer.nmembs * dt->shared->parent->shared->size;
break;
@@ -1012,7 +1026,7 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt)
} /* end if */
/* Encode base type of VL information */
- if(H5O_dtype_encode_helper(f, pp, dt->shared->parent) < 0)
+ if(H5O_dtype_encode_helper(pp, dt->shared->parent) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTENCODE, FAIL, "unable to encode VL parent type")
break;
@@ -1050,7 +1064,7 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt)
} /* end if */
/* Encode base type of array's information */
- if(H5O_dtype_encode_helper(f, pp, dt->shared->parent) < 0)
+ if(H5O_dtype_encode_helper(pp, dt->shared->parent) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTENCODE, FAIL, "unable to encode VL parent type")
break;
@@ -1091,7 +1105,7 @@ done:
function using malloc() and is returned to the caller.
--------------------------------------------------------------------------*/
static void *
-H5O_dtype_decode(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh, unsigned H5_ATTR_UNUSED mesg_flags,
+H5O_dtype_decode(H5F_t H5_ATTR_UNUSED *f, H5O_t H5_ATTR_UNUSED *open_oh, unsigned H5_ATTR_UNUSED mesg_flags,
unsigned *ioflags/*in,out*/, size_t H5_ATTR_UNUSED p_size, const uint8_t *p)
{
H5T_t *dt = NULL;
@@ -1107,7 +1121,7 @@ H5O_dtype_decode(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh, unsigned H5_ATTR_UNUSE
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* Perform actual decode of message */
- if(H5O_dtype_decode_helper(f, ioflags, &p, dt) < 0)
+ if(H5O_dtype_decode_helper(ioflags, &p, dt) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, NULL, "can't decode type")
/* Set return value */
@@ -1136,7 +1150,7 @@ done:
message in the "raw" disk form.
--------------------------------------------------------------------------*/
static herr_t
-H5O_dtype_encode(H5F_t *f, uint8_t *p, const void *mesg)
+H5O_dtype_encode(H5F_t H5_ATTR_UNUSED *f, uint8_t *p, const void *mesg)
{
const H5T_t *dt = (const H5T_t *) mesg;
herr_t ret_value = SUCCEED; /* Return value */
@@ -1149,7 +1163,7 @@ H5O_dtype_encode(H5F_t *f, uint8_t *p, const void *mesg)
HDassert(dt);
/* encode */
- if(H5O_dtype_encode_helper(f, &p, dt) < 0)
+ if(H5O_dtype_encode_helper(&p, dt) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTENCODE, FAIL, "can't encode type")
done:
@@ -1765,7 +1779,7 @@ H5O__dtype_debug(H5F_t *f, const void *mesg, FILE *stream, int indent,
HDfprintf(stream, "%*s%-*s 0x", indent, "", fwidth,
"Raw bytes of value:");
for(k = 0; k < dt->shared->parent->shared->size; k++)
- HDfprintf(stream, "%02x", dt->shared->u.enumer.value[i*dt->shared->parent->shared->size + k]);
+ HDfprintf(stream, "%02x", (unsigned)*((uint8_t *)dt->shared->u.enumer.value + (i * dt->shared->parent->shared->size) + k));
HDfprintf(stream, "\n");
} /* end for */
} /* end else if */
diff --git a/src/H5Oefl.c b/src/H5Oefl.c
index 6a81a46..b18d819 100644
--- a/src/H5Oefl.c
+++ b/src/H5Oefl.c
@@ -461,7 +461,7 @@ H5O__efl_copy_file(H5F_t H5_ATTR_UNUSED *file_src, void *mesg_src, H5F_t *file_d
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* Copy the "top level" information */
- HDmemcpy(efl_dst, efl_src, sizeof(H5O_efl_t));
+ H5MM_memcpy(efl_dst, efl_src, sizeof(H5O_efl_t));
/* Determine size needed for destination heap */
heap_size = H5HL_ALIGN(1); /* "empty" name */
@@ -488,7 +488,7 @@ H5O__efl_copy_file(H5F_t H5_ATTR_UNUSED *file_src, void *mesg_src, H5F_t *file_d
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* copy content from the source. Need to update later */
- HDmemcpy(efl_dst->slot, efl_src->slot, size);
+ H5MM_memcpy(efl_dst->slot, efl_src->slot, size);
} /* end if */
/* copy the name from the source */
diff --git a/src/H5Ofill.c b/src/H5Ofill.c
index c131c76..0cc58a6 100644
--- a/src/H5Ofill.c
+++ b/src/H5Ofill.c
@@ -14,15 +14,15 @@
/* Programmer: Robb Matzke <matzke@llnl.gov>
* Wednesday, September 30, 1998
*
- * Purpose: The fill message indicates a bit pattern to use for
- * uninitialized data points of a dataset.
+ * Purpose: The fill message indicates a bit pattern to use for
+ * uninitialized data points of a dataset.
*/
#include "H5Omodule.h" /* This source code file is part of the H5O module */
#include "H5private.h" /* Generic Functions */
-#include "H5Dprivate.h" /* Datasets */
+#include "H5Dprivate.h" /* Datasets */
#include "H5Eprivate.h" /* Error handling */
#include "H5FLprivate.h" /* Free Lists */
#include "H5Iprivate.h" /* IDs */
@@ -49,61 +49,61 @@ static herr_t H5O__fill_debug(H5F_t *f, const void *_mesg, FILE *stream,
int indent, int fwidth);
/* Set up & include shared message "interface" info */
-#define H5O_SHARED_TYPE H5O_MSG_FILL
-#define H5O_SHARED_DECODE H5O_fill_shared_decode
-#define H5O_SHARED_DECODE_REAL H5O_fill_old_decode
-#define H5O_SHARED_ENCODE H5O_fill_shared_encode
-#define H5O_SHARED_ENCODE_REAL H5O_fill_old_encode
-#define H5O_SHARED_SIZE H5O_fill_shared_size
-#define H5O_SHARED_SIZE_REAL H5O_fill_old_size
-#define H5O_SHARED_DELETE H5O__fill_shared_delete
+#define H5O_SHARED_TYPE H5O_MSG_FILL
+#define H5O_SHARED_DECODE H5O_fill_shared_decode
+#define H5O_SHARED_DECODE_REAL H5O_fill_old_decode
+#define H5O_SHARED_ENCODE H5O_fill_shared_encode
+#define H5O_SHARED_ENCODE_REAL H5O_fill_old_encode
+#define H5O_SHARED_SIZE H5O_fill_shared_size
+#define H5O_SHARED_SIZE_REAL H5O_fill_old_size
+#define H5O_SHARED_DELETE H5O__fill_shared_delete
#undef H5O_SHARED_DELETE_REAL
-#define H5O_SHARED_LINK H5O__fill_shared_link
+#define H5O_SHARED_LINK H5O__fill_shared_link
#undef H5O_SHARED_LINK_REAL
-#define H5O_SHARED_COPY_FILE H5O__fill_shared_copy_file
+#define H5O_SHARED_COPY_FILE H5O__fill_shared_copy_file
#undef H5O_SHARED_COPY_FILE_REAL
-#define H5O_SHARED_POST_COPY_FILE H5O_fill_shared_post_copy_file
+#define H5O_SHARED_POST_COPY_FILE H5O_fill_shared_post_copy_file
#undef H5O_SHARED_POST_COPY_FILE_REAL
#undef H5O_SHARED_POST_COPY_FILE_UPD
-#define H5O_SHARED_DEBUG H5O_fill_shared_debug
-#define H5O_SHARED_DEBUG_REAL H5O__fill_debug
-#include "H5Oshared.h" /* Shared Object Header Message Callbacks */
+#define H5O_SHARED_DEBUG H5O_fill_shared_debug
+#define H5O_SHARED_DEBUG_REAL H5O__fill_debug
+#include "H5Oshared.h" /* Shared Object Header Message Callbacks */
/* Set up & include shared message "interface" info */
/* (Kludgy 'undef's in order to re-include the H5Oshared.h header) */
#undef H5O_SHARED_TYPE
-#define H5O_SHARED_TYPE H5O_MSG_FILL_NEW
+#define H5O_SHARED_TYPE H5O_MSG_FILL_NEW
#undef H5O_SHARED_DECODE
-#define H5O_SHARED_DECODE H5O_fill_new_shared_decode
+#define H5O_SHARED_DECODE H5O_fill_new_shared_decode
#undef H5O_SHARED_DECODE_REAL
-#define H5O_SHARED_DECODE_REAL H5O_fill_new_decode
+#define H5O_SHARED_DECODE_REAL H5O_fill_new_decode
#undef H5O_SHARED_ENCODE
-#define H5O_SHARED_ENCODE H5O_fill_new_shared_encode
+#define H5O_SHARED_ENCODE H5O_fill_new_shared_encode
#undef H5O_SHARED_ENCODE_REAL
-#define H5O_SHARED_ENCODE_REAL H5O_fill_new_encode
+#define H5O_SHARED_ENCODE_REAL H5O_fill_new_encode
#undef H5O_SHARED_SIZE
-#define H5O_SHARED_SIZE H5O_fill_new_shared_size
+#define H5O_SHARED_SIZE H5O_fill_new_shared_size
#undef H5O_SHARED_SIZE_REAL
-#define H5O_SHARED_SIZE_REAL H5O_fill_new_size
+#define H5O_SHARED_SIZE_REAL H5O_fill_new_size
#undef H5O_SHARED_DELETE
-#define H5O_SHARED_DELETE H5O__fill_new_shared_delete
+#define H5O_SHARED_DELETE H5O__fill_new_shared_delete
#undef H5O_SHARED_DELETE_REAL
#undef H5O_SHARED_LINK
-#define H5O_SHARED_LINK H5O__fill_new_shared_link
+#define H5O_SHARED_LINK H5O__fill_new_shared_link
#undef H5O_SHARED_LINK_REAL
#undef H5O_SHARED_COPY_FILE
-#define H5O_SHARED_COPY_FILE H5O__fill_new_shared_copy_file
+#define H5O_SHARED_COPY_FILE H5O__fill_new_shared_copy_file
#undef H5O_SHARED_COPY_FILE_REAL
#undef H5O_SHARED_POST_COPY_FILE
-#define H5O_SHARED_POST_COPY_FILE H5O_fill_new_shared_post_copy_file
+#define H5O_SHARED_POST_COPY_FILE H5O_fill_new_shared_post_copy_file
#undef H5O_SHARED_POST_COPY_FILE_REAL
#undef H5O_SHARED_POST_COPY_FILE_UPD
#undef H5O_SHARED_DEBUG
-#define H5O_SHARED_DEBUG H5O_fill_new_shared_debug
+#define H5O_SHARED_DEBUG H5O_fill_new_shared_debug
#undef H5O_SHARED_DEBUG_REAL
-#define H5O_SHARED_DEBUG_REAL H5O__fill_debug
+#define H5O_SHARED_DEBUG_REAL H5O__fill_debug
#undef H5Oshared_H
-#include "H5Oshared.h" /* Shared Object Header Message Callbacks */
+#include "H5Oshared.h" /* Shared Object Header Message Callbacks */
/* This message derives from H5O message class, for old fill value before version 1.5 */
const H5O_msg_class_t H5O_MSG_FILL[1] = {{
@@ -150,13 +150,15 @@ const H5O_msg_class_t H5O_MSG_FILL_NEW[1] = {{
H5O_fill_new_shared_post_copy_file, /* post copy native value to file */
NULL, /* get creation index */
NULL, /* set creation index */
- H5O_fill_new_shared_debug /*debug the message */
+ H5O_fill_new_shared_debug /*debug the message */
}};
/* Format version bounds for fill value */
const unsigned H5O_fill_ver_bounds[] = {
H5O_FILL_VERSION_1, /* H5F_LIBVER_EARLIEST */
- H5O_FILL_VERSION_2, /* H5F_LIBVER_V18 */
+ H5O_FILL_VERSION_3, /* H5F_LIBVER_V18 */
+ H5O_FILL_VERSION_3, /* H5F_LIBVER_V110 */
+ H5O_FILL_VERSION_3, /* H5F_LIBVER_V112 */
H5O_FILL_VERSION_LATEST /* H5F_LIBVER_LATEST */
};
@@ -175,15 +177,15 @@ H5FL_DEFINE(H5O_fill_t);
/* Declare extern the free list to manage blocks of type conversion data */
H5FL_BLK_EXTERN(type_conv);
-
+
/*-------------------------------------------------------------------------
- * Function: H5O_fill_new_decode
+ * Function: H5O_fill_new_decode
*
- * Purpose: Decode a new fill value message. The new fill value
+ * Purpose: Decode a new fill value message. The new fill value
* message is fill value plus space allocation time and
* fill value writing time and whether fill value is defined.
*
- * Return: Success: Ptr to new message in native struct.
+ * Return: Success: Ptr to new message in native struct.
* Failure: NULL
*
* Programmer: Raymond Lu
@@ -196,7 +198,7 @@ H5O_fill_new_decode(H5F_t H5_ATTR_UNUSED *f, H5O_t H5_ATTR_UNUSED *open_oh,
unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags,
size_t p_size, const uint8_t *p)
{
- H5O_fill_t *fill = NULL;
+ H5O_fill_t *fill = NULL;
void *ret_value = NULL; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
@@ -232,7 +234,7 @@ H5O_fill_new_decode(H5F_t H5_ATTR_UNUSED *f, H5O_t H5_ATTR_UNUSED *open_oh,
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "destination buffer too small")
if(NULL == (fill->buf = H5MM_malloc((size_t)fill->size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fill value")
- HDmemcpy(fill->buf, p, (size_t)fill->size);
+ H5MM_memcpy(fill->buf, p, (size_t)fill->size);
} /* end if */
} /* end if */
else
@@ -270,7 +272,7 @@ H5O_fill_new_decode(H5F_t H5_ATTR_UNUSED *f, H5O_t H5_ATTR_UNUSED *open_oh,
H5_CHECK_OVERFLOW(fill->size, ssize_t, size_t);
if(NULL == (fill->buf = H5MM_malloc((size_t)fill->size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fill value")
- HDmemcpy(fill->buf, p, (size_t)fill->size);
+ H5MM_memcpy(fill->buf, p, (size_t)fill->size);
/* Set the "defined" flag */
fill->fill_defined = TRUE;
@@ -294,7 +296,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_fill_new_decode() */
-
+
/*-------------------------------------------------------------------------
* Function: H5O_fill_old_decode
*
@@ -313,7 +315,7 @@ H5O_fill_old_decode(H5F_t *f, H5O_t *open_oh,
unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags,
size_t p_size, const uint8_t *p)
{
- H5O_fill_t *fill = NULL; /* Decoded fill value message */
+ H5O_fill_t *fill = NULL; /* Decoded fill value message */
htri_t exists = FALSE;
H5T_t *dt = NULL;
void *ret_value = NULL; /* Return value */
@@ -344,16 +346,16 @@ H5O_fill_old_decode(H5F_t *f, H5O_t *open_oh,
if((exists = H5O_msg_exists_oh(open_oh, H5O_DTYPE_ID)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, NULL, "unable to read object header")
if(exists) {
- if((dt = H5O_msg_read_oh(f, open_oh, H5O_DTYPE_ID, NULL)) < 0)
+ if(NULL == (dt = (H5T_t *)H5O_msg_read_oh(f, open_oh, H5O_DTYPE_ID, NULL)))
HGOTO_ERROR(H5E_SYM, H5E_CANTGET, NULL, "can't read DTYPE message")
/* Verify size */
- if(fill->size != H5T_GET_SIZE(dt))
+ if(fill->size != (ssize_t)H5T_GET_SIZE(dt))
HGOTO_ERROR(H5E_SYM, H5E_CANTGET, NULL, "inconsistent fill value size")
- }
+ } /* end if */
if(NULL == (fill->buf = H5MM_malloc((size_t)fill->size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fill value")
- HDmemcpy(fill->buf, p, (size_t)fill->size);
+ H5MM_memcpy(fill->buf, p, (size_t)fill->size);
fill->fill_defined = TRUE;
} /* end if */
else
@@ -375,15 +377,15 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_fill_old_decode() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O_fill_new_encode
+ * Function: H5O_fill_new_encode
*
- * Purpose: Encode a new fill value message. The new fill value
+ * Purpose: Encode a new fill value message. The new fill value
* message is fill value plus space allocation time and
* fill value writing time and whether fill value is defined.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
* Programmer: Raymond Lu
* Feb 26, 2002
@@ -393,7 +395,7 @@ done:
static herr_t
H5O_fill_new_encode(H5F_t H5_ATTR_UNUSED *f, uint8_t *p, const void *_fill)
{
- const H5O_fill_t *fill = (const H5O_fill_t *)_fill;
+ const H5O_fill_t *fill = (const H5O_fill_t *)_fill;
FUNC_ENTER_NOAPI_NOINIT_NOERR
@@ -420,7 +422,7 @@ H5O_fill_new_encode(H5F_t H5_ATTR_UNUSED *f, uint8_t *p, const void *_fill)
if(fill->size > 0)
if(fill->buf) {
H5_CHECK_OVERFLOW(fill->size, ssize_t, size_t);
- HDmemcpy(p, fill->buf, (size_t)fill->size);
+ H5MM_memcpy(p, fill->buf, (size_t)fill->size);
} /* end if */
} /* end if */
} /* end if */
@@ -459,7 +461,7 @@ H5O_fill_new_encode(H5F_t H5_ATTR_UNUSED *f, uint8_t *p, const void *_fill)
/* Encode the fill value */
HDassert(fill->buf);
H5_CHECK_OVERFLOW(fill->size, ssize_t, size_t);
- HDmemcpy(p, fill->buf, (size_t)fill->size);
+ H5MM_memcpy(p, fill->buf, (size_t)fill->size);
} /* end if */
else {
/* Flags */
@@ -473,7 +475,7 @@ H5O_fill_new_encode(H5F_t H5_ATTR_UNUSED *f, uint8_t *p, const void *_fill)
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O_fill_new_encode() */
-
+
/*-------------------------------------------------------------------------
* Function: H5O_fill_old_encode
*
@@ -499,22 +501,22 @@ H5O_fill_old_encode(H5F_t H5_ATTR_UNUSED *f, uint8_t *p, const void *_fill)
UINT32ENCODE(p, fill->size);
if(fill->buf)
- HDmemcpy(p, fill->buf, (size_t)fill->size);
+ H5MM_memcpy(p, fill->buf, (size_t)fill->size);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O_fill_old_encode() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O_fill_copy
+ * Function: H5O_fill_copy
*
- * Purpose: Copies a message from _MESG to _DEST, allocating _DEST if
- * necessary. The new fill value message is fill value plus
- * space allocation time and fill value writing time and
- * whether fill value is defined.
+ * Purpose: Copies a message from _MESG to _DEST, allocating _DEST if
+ * necessary. The new fill value message is fill value plus
+ * space allocation time and fill value writing time and
+ * whether fill value is defined.
*
- * Return: Success: Ptr to _DEST
- * Failure: NULL
+ * Return: Success: Ptr to _DEST
+ * Failure: NULL
*
* Programmer: Raymond Lu
* Feb 26, 2002
@@ -551,7 +553,7 @@ H5O_fill_copy(const void *_src, void *_dst)
H5_CHECK_OVERFLOW(src->size, ssize_t, size_t);
if(NULL == (dst->buf = H5MM_malloc((size_t)src->size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fill value")
- HDmemcpy(dst->buf, src->buf, (size_t)src->size);
+ H5MM_memcpy(dst->buf, src->buf, (size_t)src->size);
/* Check for needing to convert/copy fill value */
if(src->type) {
@@ -621,18 +623,18 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_fill_copy() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O_fill_new_size
+ * Function: H5O_fill_new_size
*
- * Purpose: Returns the size of the raw message in bytes not counting the
+ * Purpose: Returns the size of the raw message in bytes not counting the
* message type or size fields, but only the data fields. This
* function doesn't take into account alignment. The new fill
* value message is fill value plus space allocation time and
* fill value writing time and whether fill value is defined.
*
- * Return: Success: Message data size in bytes w/o alignment.
- * Failure: 0
+ * Return: Success: Message data size in bytes w/o alignment.
+ * Failure: 0
*
* Programmer: Raymond Lu
* Feb 26, 2002
@@ -652,26 +654,26 @@ H5O_fill_new_size(const H5F_t H5_ATTR_UNUSED *f, const void *_fill)
/* Determine size for different versions */
if(fill->version < H5O_FILL_VERSION_3) {
- ret_value = 1 + /* Version number */
- 1 + /* Space allocation time */
- 1 + /* Fill value write time */
- 1; /* Fill value defined */
+ ret_value = 1 + /* Version number */
+ 1 + /* Space allocation time */
+ 1 + /* Fill value write time */
+ 1; /* Fill value defined */
if(fill->fill_defined)
- ret_value += 4 + /* Fill value size */
- (fill->size > 0 ? (size_t)fill->size : 0); /* Size of fill value */
+ ret_value += 4 + /* Fill value size */
+ (fill->size > 0 ? (size_t)fill->size : 0); /* Size of fill value */
} /* end if */
else {
- ret_value = 1 + /* Version number */
- 1; /* Status flags */
+ ret_value = 1 + /* Version number */
+ 1; /* Status flags */
if(fill->size > 0)
- ret_value += 4 + /* Fill value size */
- (size_t)fill->size; /* Size of fill value */
+ ret_value += 4 + /* Fill value size */
+ (size_t)fill->size; /* Size of fill value */
} /* end else */
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_fill_new_size() */
-
+
/*-------------------------------------------------------------------------
* Function: H5O_fill_old_size
*
@@ -699,15 +701,15 @@ H5O_fill_old_size(const H5F_t H5_ATTR_UNUSED *f, const void *_fill)
FUNC_LEAVE_NOAPI(4 + (size_t)fill->size)
} /* end H5O_fill_old_size() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O_fill_reset_dyn
+ * Function: H5O_fill_reset_dyn
*
- * Purpose: Resets dynamic fill value fields
+ * Purpose: Resets dynamic fill value fields
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* Monday, January 22, 2007
*
*-------------------------------------------------------------------------
@@ -740,7 +742,7 @@ H5O_fill_reset_dyn(H5O_fill_t *fill)
HGOTO_ERROR(H5E_OHDR, H5E_CANTCREATE, FAIL, "can't create scalar dataspace")
/* Reclaim any variable length components of the fill value */
- if(H5D_vlen_reclaim(fill_type_id, fill_space, fill->buf) < 0) {
+ if(H5T_reclaim(fill_type_id, fill_space, fill->buf) < 0) {
H5S_close(fill_space);
HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "unable to reclaim variable-length fill value data")
} /* end if */
@@ -765,15 +767,15 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_fill_reset_dyn() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O__fill_reset
+ * Function: H5O__fill_reset
*
- * Purpose: Resets a message to an initial state.
+ * Purpose: Resets a message to an initial state.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Robb Matzke
+ * Programmer: Robb Matzke
* Thursday, October 1, 1998
*
*-------------------------------------------------------------------------
@@ -781,7 +783,7 @@ done:
static herr_t
H5O__fill_reset(void *_fill)
{
- H5O_fill_t *fill = (H5O_fill_t *)_fill;
+ H5O_fill_t *fill = (H5O_fill_t *)_fill;
FUNC_ENTER_STATIC_NOERR
@@ -798,15 +800,15 @@ H5O__fill_reset(void *_fill)
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O__fill_reset() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O__fill_free
+ * Function: H5O__fill_free
*
- * Purpose: Frees the message
+ * Purpose: Frees the message
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* Thursday, December 5, 2002
*
*-------------------------------------------------------------------------
@@ -823,7 +825,7 @@ H5O__fill_free(void *fill)
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O__fill_free() */
-
+
/*-------------------------------------------------------------------------
* Function: H5O__fill_pre_copy_file
*
@@ -841,7 +843,7 @@ static herr_t
H5O__fill_pre_copy_file(H5F_t H5_ATTR_UNUSED *file_src, const void *mesg_src,
hbool_t H5_ATTR_UNUSED *deleted, const H5O_copy_t *cpy_info, void H5_ATTR_UNUSED *udata)
{
- const H5O_fill_t *fill_src = (const H5O_fill_t *)mesg_src; /* Source fill value */
+ const H5O_fill_t *fill_src = (const H5O_fill_t *)mesg_src; /* Source fill value */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC
@@ -859,15 +861,15 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O__fill_pre_copy_file() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O__fill_debug
+ * Function: H5O__fill_debug
*
- * Purpose: Prints debugging info for the message.
+ * Purpose: Prints debugging info for the message.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Robb Matzke
+ * Programmer: Robb Matzke
* Thursday, October 1, 1998
*
*-------------------------------------------------------------------------
@@ -890,40 +892,40 @@ H5O__fill_debug(H5F_t H5_ATTR_UNUSED *f, const void *_fill, FILE *stream,
HDfprintf(stream, "%*s%-*s ", indent, "", fwidth, "Space Allocation Time:");
switch(fill->alloc_time) {
case H5D_ALLOC_TIME_EARLY:
- fprintf(stream,"Early\n");
+ HDfprintf(stream,"Early\n");
break;
case H5D_ALLOC_TIME_LATE:
- fprintf(stream,"Late\n");
+ HDfprintf(stream,"Late\n");
break;
case H5D_ALLOC_TIME_INCR:
- fprintf(stream,"Incremental\n");
+ HDfprintf(stream,"Incremental\n");
break;
case H5D_ALLOC_TIME_DEFAULT:
case H5D_ALLOC_TIME_ERROR:
default:
- fprintf(stream,"Unknown!\n");
+ HDfprintf(stream,"Unknown!\n");
break;
} /* end switch */
HDfprintf(stream, "%*s%-*s ", indent, "", fwidth, "Fill Time:");
switch(fill->fill_time) {
case H5D_FILL_TIME_ALLOC:
- fprintf(stream,"On Allocation\n");
+ HDfprintf(stream,"On Allocation\n");
break;
case H5D_FILL_TIME_NEVER:
- fprintf(stream,"Never\n");
+ HDfprintf(stream,"Never\n");
break;
case H5D_FILL_TIME_IFSET:
- fprintf(stream,"If Set\n");
+ HDfprintf(stream,"If Set\n");
break;
case H5D_FILL_TIME_ERROR:
default:
- fprintf(stream,"Unknown!\n");
+ HDfprintf(stream,"Unknown!\n");
break;
} /* end switch */
@@ -931,25 +933,25 @@ H5O__fill_debug(H5F_t H5_ATTR_UNUSED *f, const void *_fill, FILE *stream,
H5P_is_fill_value_defined((const H5O_fill_t *)fill, &fill_status);
switch(fill_status) {
case H5D_FILL_VALUE_UNDEFINED:
- fprintf(stream,"Undefined\n");
+ HDfprintf(stream,"Undefined\n");
break;
case H5D_FILL_VALUE_DEFAULT:
- fprintf(stream,"Default\n");
+ HDfprintf(stream,"Default\n");
break;
case H5D_FILL_VALUE_USER_DEFINED:
- fprintf(stream,"User Defined\n");
+ HDfprintf(stream,"User Defined\n");
break;
case H5D_FILL_VALUE_ERROR:
default:
- fprintf(stream,"Unknown!\n");
+ HDfprintf(stream,"Unknown!\n");
break;
} /* end switch */
HDfprintf(stream, "%*s%-*s %Zd\n", indent, "", fwidth,
- "Size:", fill->size);
+ "Size:", fill->size);
HDfprintf(stream, "%*s%-*s ", indent, "", fwidth, "Data type:");
if(fill->type) {
H5T_debug(fill->type, stream);
@@ -961,18 +963,18 @@ H5O__fill_debug(H5F_t H5_ATTR_UNUSED *f, const void *_fill, FILE *stream,
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O__fill_debug() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O_fill_convert
+ * Function: H5O_fill_convert
*
- * Purpose: Convert a fill value from whatever data type it currently has
+ * Purpose: Convert a fill value from whatever data type it currently has
* to the specified dataset type. The `type' field of the fill
* value struct will be set to NULL to indicate that it has the
* same type as the dataset.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Robb Matzke
+ * Programmer: Robb Matzke
* Thursday, October 1, 1998
*
*-------------------------------------------------------------------------
@@ -980,10 +982,10 @@ H5O__fill_debug(H5F_t H5_ATTR_UNUSED *f, const void *_fill, FILE *stream,
herr_t
H5O_fill_convert(H5O_fill_t *fill, H5T_t *dset_type, hbool_t *fill_changed)
{
- H5T_path_t *tpath; /* Type conversion info */
- void *buf = NULL, *bkg = NULL; /* Conversion buffers */
- hid_t src_id = -1, dst_id = -1; /* Datatype identifiers */
- herr_t ret_value = SUCCEED; /* Return value */
+ H5T_path_t *tpath; /* Type conversion info */
+ void *buf = NULL, *bkg = NULL; /* Conversion buffers */
+ hid_t src_id = -1, dst_id = -1; /* Datatype identifiers */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
@@ -1025,7 +1027,7 @@ H5O_fill_convert(H5O_fill_t *fill, H5T_t *dset_type, hbool_t *fill_changed)
else {
if(NULL == (buf = H5MM_malloc(H5T_get_size(dset_type))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion")
- HDmemcpy(buf, fill->buf, H5T_get_size(fill->type));
+ H5MM_memcpy(buf, fill->buf, H5T_get_size(fill->type));
} /* end else */
/* Use CALLOC here to clear the buffer in case later the library thinks there's
@@ -1064,7 +1066,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_fill_convert() */
-
+
/*-------------------------------------------------------------------------
* Function: H5O_fill_set_version
*
diff --git a/src/H5Oflush.c b/src/H5Oflush.c
index 2302d4c..a03cfa1 100644
--- a/src/H5Oflush.c
+++ b/src/H5Oflush.c
@@ -27,6 +27,7 @@
/****************/
#include "H5Omodule.h" /* This source code file is part of the H5O module */
+#define H5T_FRIEND /* Suppress error about including H5Tpkg */
/***********/
/* Headers */
@@ -40,6 +41,7 @@
#include "H5Gprivate.h" /* Groups */
#include "H5Iprivate.h" /* IDs */
#include "H5Opkg.h" /* Objects */
+#include "H5Tpkg.h" /* Datatypes */
/********************/
/* Local Prototypes */
@@ -70,22 +72,27 @@ static herr_t H5O__refresh_metadata_close(hid_t oid, H5O_loc_t oloc,
herr_t
H5Oflush(hid_t obj_id)
{
- H5O_loc_t *oloc; /* Object location */
+ H5VL_object_t *vol_obj = NULL; /* Object token */
+ H5VL_loc_params_t loc_params;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE1("e", "i", obj_id);
/* Check args */
- if(NULL == (oloc = H5O_get_loc(obj_id)))
+ if(NULL == (vol_obj = H5VL_vol_object(obj_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier")
/* Set up collective metadata if appropriate */
if(H5CX_set_loc(obj_id) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "can't set access property list info")
+ /* Set location parameters */
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(obj_id);
+
/* Flush the object */
- if(H5O_flush(oloc, obj_id) < 0)
+ if(H5VL_object_specific(vol_obj, &loc_params, H5VL_OBJECT_FLUSH, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, obj_id) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTFLUSH, FAIL, "unable to flush object")
done:
@@ -116,7 +123,7 @@ H5O_flush(H5O_loc_t *oloc, hid_t obj_id)
FUNC_ENTER_NOAPI(FAIL)
/* Get the object pointer */
- if(NULL == (obj_ptr = H5I_object(obj_id)))
+ if(NULL == (obj_ptr = H5VL_object(obj_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier")
/* Get the object class */
@@ -229,22 +236,27 @@ done:
herr_t
H5Orefresh(hid_t oid)
{
- H5O_loc_t *oloc; /* object location */
- herr_t ret_value = SUCCEED; /* return value */
-
+ H5VL_object_t *vol_obj = NULL; /* Object token */
+ H5VL_loc_params_t loc_params;
+ herr_t ret_value = SUCCEED; /* Return value */
+
FUNC_ENTER_API(FAIL)
H5TRACE1("e", "i", oid);
/* Check args */
- if(NULL == (oloc = H5O_get_loc(oid)))
+ if(NULL == (vol_obj = H5VL_vol_object(oid)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier")
/* Set up collective metadata if appropriate */
if(H5CX_set_loc(oid) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set access property list info")
+ /* Set location parameters */
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(oid);
+
/* Refresh the object */
- if(H5O_refresh_metadata(oid, *oloc) < 0)
+ if(H5VL_object_specific(vol_obj, &loc_params, H5VL_OBJECT_REFRESH, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, oid) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to refresh object")
done:
@@ -275,6 +287,7 @@ done:
herr_t
H5O_refresh_metadata(hid_t oid, H5O_loc_t oloc)
{
+ H5VL_object_t *vol_obj = NULL; /* VOL object associated with the ID */
hbool_t objs_incr = FALSE; /* Whether the object count in the file was incremented */
herr_t ret_value = SUCCEED; /* Return value */
@@ -285,6 +298,8 @@ H5O_refresh_metadata(hid_t oid, H5O_loc_t oloc)
H5G_loc_t obj_loc;
H5O_loc_t obj_oloc;
H5G_name_t obj_path;
+ H5O_shared_t cached_H5O_shared;
+ H5VL_t *connector = NULL;
/* Create empty object location */
obj_loc.oloc = &obj_oloc;
@@ -297,13 +312,40 @@ H5O_refresh_metadata(hid_t oid, H5O_loc_t oloc)
H5F_incr_nopen_objs(oloc.file);
objs_incr = TRUE;
+ /* Save important datatype state */
+ if(H5I_get_type(oid) == H5I_DATATYPE)
+ if(H5T_save_refresh_state(oid, &cached_H5O_shared) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, FAIL, "unable to save datatype state")
+
+ /* Get the VOL object from the ID and cache a pointer to the connector.
+ * The vol_obj will disappear when the underlying object is closed, so
+ * we can't use that directly.
+ */
+ if(NULL == (vol_obj = H5VL_vol_object(oid)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier")
+ connector = vol_obj->connector;
+
+ /* Bump the number of references on the VOL connector.
+ * If you don't do this, VDS refreshes can accidentally close the connector.
+ */
+ connector->nrefs++;
+
/* Close object & evict its metadata */
if((H5O__refresh_metadata_close(oid, oloc, &obj_loc)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to refresh object")
/* Re-open the object, re-fetching its metadata */
- if((H5O_refresh_metadata_reopen(oid, &obj_loc, FALSE)) < 0)
+ if((H5O_refresh_metadata_reopen(oid, &obj_loc, connector, FALSE)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to refresh object")
+
+ /* Restore the number of references on the VOL connector */
+ connector->nrefs--;
+
+ /* Restore important datatype state */
+ if(H5I_get_type(oid) == H5I_DATATYPE)
+ if(H5T_restore_refresh_state(oid, &cached_H5O_shared) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, FAIL, "unable to restore datatype state")
+
} /* end if */
done:
@@ -350,7 +392,7 @@ H5O__refresh_metadata_close(hid_t oid, H5O_loc_t oloc, H5G_loc_t *obj_loc)
H5G_loc_copy(obj_loc, &tmp_loc, H5_COPY_DEEP);
} /* end if */
- /* Get object's type */
+ /* Handle close for multiple dataset opens */
if(H5I_get_type(oid) == H5I_DATASET)
if(H5D_mult_refresh_close(oid) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "unable to prepare refresh for dataset")
@@ -400,7 +442,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5O_refresh_metadata_reopen(hid_t oid, H5G_loc_t *obj_loc, hbool_t start_swmr)
+H5O_refresh_metadata_reopen(hid_t oid, H5G_loc_t *obj_loc, H5VL_t *vol_connector, hbool_t start_swmr)
{
void *object = NULL; /* Object for this operation */
H5I_type_t type; /* Type of object for the ID */
@@ -410,6 +452,7 @@ H5O_refresh_metadata_reopen(hid_t oid, H5G_loc_t *obj_loc, hbool_t start_swmr)
/* Sanity check */
HDassert(obj_loc);
+ HDassert(vol_connector);
/* Get object's type */
type = H5I_get_type(oid);
@@ -418,13 +461,13 @@ H5O_refresh_metadata_reopen(hid_t oid, H5G_loc_t *obj_loc, hbool_t start_swmr)
case H5I_GROUP:
/* Re-open the group */
if(NULL == (object = H5G_open(obj_loc)))
- HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group")
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, FAIL, "unable to open group")
break;
case H5I_DATATYPE:
/* Re-open the named datatype */
if(NULL == (object = H5T_open(obj_loc)))
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, FAIL, "unable to open named datatype")
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, FAIL, "unable to open named datatype")
break;
case H5I_DATASET:
@@ -433,30 +476,34 @@ H5O_refresh_metadata_reopen(hid_t oid, H5G_loc_t *obj_loc, hbool_t start_swmr)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "unable to open dataset")
if(!start_swmr) /* No need to handle multiple opens when H5Fstart_swmr_write() */
if(H5D_mult_refresh_reopen((H5D_t *)object) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "unable to finish refresh for dataset")
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, FAIL, "unable to finish refresh for dataset")
break;
+ case H5I_MAP:
+ HGOTO_ERROR(H5E_OHDR, H5E_BADTYPE, FAIL, "maps not supported in native VOL connector")
+
case H5I_UNINIT:
case H5I_BADID:
case H5I_FILE:
case H5I_DATASPACE:
case H5I_ATTR:
- case H5I_REFERENCE:
case H5I_VFL:
+ case H5I_VOL:
case H5I_GENPROP_CLS:
case H5I_GENPROP_LST:
case H5I_ERROR_CLASS:
case H5I_ERROR_MSG:
case H5I_ERROR_STACK:
+ case H5I_SPACE_SEL_ITER:
case H5I_NTYPES:
default:
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a valid file object ID (dataset, group, or datatype)")
+ HGOTO_ERROR(H5E_OHDR, H5E_BADTYPE, FAIL, "not a valid file object ID (dataset, group, or datatype)")
break;
} /* end switch */
/* Re-register ID for the object */
- if((H5I_register_with_id(type, object, TRUE, oid)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to re-register object ID after refresh")
+ if((H5VL_register_using_existing_id(type, object, vol_connector, TRUE, oid)) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTREGISTER, FAIL, "unable to re-register object ID after refresh")
done:
FUNC_LEAVE_NOAPI(ret_value);
diff --git a/src/H5Ofsinfo.c b/src/H5Ofsinfo.c
index bb15f62..e5e6741 100644
--- a/src/H5Ofsinfo.c
+++ b/src/H5Ofsinfo.c
@@ -15,7 +15,7 @@
*
* Created: H5Ofsinfo.c
* Feb 2009
- * Vailin Choi
+ * Vailin Choi
*
* Purpose: File space info message.
*
@@ -25,11 +25,11 @@
#include "H5Omodule.h" /* This source code file is part of the H5O module */
-#include "H5private.h" /* Generic Functions */
-#include "H5Eprivate.h" /* Error handling */
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
#include "H5Fpkg.h" /* File access */
-#include "H5FLprivate.h" /* Free lists */
-#include "H5Opkg.h" /* Object headers */
+#include "H5FLprivate.h" /* Free lists */
+#include "H5Opkg.h" /* Object headers */
/* PRIVATE PROTOTYPES */
static void *H5O_fsinfo_decode(H5F_t *f, H5O_t *open_oh, unsigned mesg_flags,
@@ -43,36 +43,43 @@ static herr_t H5O__fsinfo_debug(H5F_t *f, const void *_mesg, FILE * stream,
/* This message derives from H5O message class */
const H5O_msg_class_t H5O_MSG_FSINFO[1] = {{
- H5O_FSINFO_ID, /* message id number */
- "fsinfo", /* message name for debugging */
- sizeof(H5O_fsinfo_t), /* native message size */
- 0, /* messages are sharable? */
- H5O_fsinfo_decode, /* decode message */
- H5O_fsinfo_encode, /* encode message */
- H5O_fsinfo_copy, /* copy the native value */
- H5O_fsinfo_size, /* size of free-space manager info message */
- NULL, /* default reset method */
- H5O__fsinfo_free, /* free method */
- NULL, /* file delete method */
- NULL, /* link method */
- NULL, /* set share method */
- NULL, /* can share method */
- NULL, /* pre copy native value to file */
- NULL, /* copy native value to file */
- NULL, /* post copy native value to file */
- NULL, /* get creation index */
- NULL, /* set creation index */
- H5O__fsinfo_debug /* debug the message */
+ H5O_FSINFO_ID, /* message id number */
+ "fsinfo", /* message name for debugging */
+ sizeof(H5O_fsinfo_t), /* native message size */
+ 0, /* messages are sharable? */
+ H5O_fsinfo_decode, /* decode message */
+ H5O_fsinfo_encode, /* encode message */
+ H5O_fsinfo_copy, /* copy the native value */
+ H5O_fsinfo_size, /* size of free-space manager info message */
+ NULL, /* default reset method */
+ H5O__fsinfo_free, /* free method */
+ NULL, /* file delete method */
+ NULL, /* link method */
+ NULL, /* set share method */
+ NULL, /* can share method */
+ NULL, /* pre copy native value to file */
+ NULL, /* copy native value to file */
+ NULL, /* post copy native value to file */
+ NULL, /* get creation index */
+ NULL, /* set creation index */
+ H5O__fsinfo_debug /* debug the message */
}};
-/* Current version of free-space manager info information */
-#define H5O_FSINFO_VERSION_0 0
-#define H5O_FSINFO_VERSION_1 1
+/* Format version bounds for fsinfo message */
+/* This message exists starting library release v1.10 */
+static const unsigned H5O_fsinfo_ver_bounds[] = {
+ H5O_INVALID_VERSION, /* H5F_LIBVER_EARLIEST */
+ H5O_INVALID_VERSION, /* H5F_LIBVER_V18 */
+ H5O_FSINFO_VERSION_1, /* H5F_LIBVER_V110 */
+ H5O_FSINFO_VERSION_1, /* H5F_LIBVER_V112 */
+ H5O_FSINFO_VERSION_LATEST /* H5F_LIBVER_LATEST */
+};
+#define N_FSINFO_VERSION_BOUNDS H5F_LIBVER_NBOUNDS
/* Declare a free list to manage the H5O_fsinfo_t struct */
H5FL_DEFINE_STATIC(H5O_fsinfo_t);
-
+
/*-------------------------------------------------------------------------
* Function: H5O_fsinfo_decode
*
@@ -103,7 +110,7 @@ H5O_fsinfo_decode(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh,
/* Allocate space for message */
if(NULL == (fsinfo = H5FL_CALLOC(H5O_fsinfo_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
for(ptype = H5F_MEM_PAGE_SUPER; ptype < H5F_MEM_PAGE_NTYPES; H5_INC_ENUM(H5F_mem_page_t, ptype))
fsinfo->fs_addr[ptype - 1] = HADDR_UNDEF;
@@ -157,11 +164,13 @@ H5O_fsinfo_decode(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh,
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid file space strategy")
} /* end switch */
+ fsinfo->version = H5O_FSINFO_VERSION_1;
fsinfo->mapped = TRUE;
-
+
} else {
- HDassert(vers == H5O_FSINFO_VERSION_1);
+ HDassert(vers >= H5O_FSINFO_VERSION_1);
+ fsinfo->version = vers;
fsinfo->strategy = (H5F_fspace_strategy_t)*p++; /* File space strategy */
fsinfo->persist = *p++; /* Free-space persist or not */
H5F_DECODE_LENGTH(f, p, fsinfo->threshold); /* Free-space section threshold */
@@ -189,7 +198,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_fsinfo_decode() */
-
+
/*-------------------------------------------------------------------------
* Function: H5O_fsinfo_encode
*
@@ -205,7 +214,7 @@ static herr_t
H5O_fsinfo_encode(H5F_t *f, hbool_t H5_ATTR_UNUSED disable_shared, uint8_t *p, const void *_mesg)
{
const H5O_fsinfo_t *fsinfo = (const H5O_fsinfo_t *)_mesg;
- H5F_mem_page_t ptype; /* Memory type for iteration */
+ H5F_mem_page_t ptype; /* Memory type for iteration */
FUNC_ENTER_NOAPI_NOINIT_NOERR
@@ -214,13 +223,13 @@ H5O_fsinfo_encode(H5F_t *f, hbool_t H5_ATTR_UNUSED disable_shared, uint8_t *p, c
HDassert(p);
HDassert(fsinfo);
- *p++ = H5O_FSINFO_VERSION_1; /* message version */
- *p++ = fsinfo->strategy; /* File space strategy */
- *p++ = (unsigned char)fsinfo->persist; /* Free-space persist or not */
+ *p++ = (uint8_t)fsinfo->version; /* message version */
+ *p++ = fsinfo->strategy; /* File space strategy */
+ *p++ = (unsigned char)fsinfo->persist; /* Free-space persist or not */
H5F_ENCODE_LENGTH(f, p, fsinfo->threshold); /* Free-space section size threshold */
- H5F_ENCODE_LENGTH(f, p, fsinfo->page_size); /* File space page size */
- UINT16ENCODE(p, fsinfo->pgend_meta_thres); /* Page end metadata threshold */
+ H5F_ENCODE_LENGTH(f, p, fsinfo->page_size); /* File space page size */
+ UINT16ENCODE(p, fsinfo->pgend_meta_thres); /* Page end metadata threshold */
H5F_addr_encode(f, &p, fsinfo->eoa_pre_fsm_fsalloc); /* EOA before free-space header and section info */
/* Store addresses of free-space managers, if persisting */
@@ -233,7 +242,7 @@ H5O_fsinfo_encode(H5F_t *f, hbool_t H5_ATTR_UNUSED disable_shared, uint8_t *p, c
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O_fsinfo_encode() */
-
+
/*-------------------------------------------------------------------------
* Function: H5O_fsinfo_copy
*
@@ -259,7 +268,7 @@ H5O_fsinfo_copy(const void *_mesg, void *_dest)
/* check args */
HDassert(fsinfo);
if(!dest && NULL == (dest = H5FL_CALLOC(H5O_fsinfo_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* copy */
*dest = *fsinfo;
@@ -271,7 +280,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_fsinfo_copy() */
-
+
/*-------------------------------------------------------------------------
* Function: H5O_fsinfo_size
*
@@ -295,11 +304,11 @@ H5O_fsinfo_size(const H5F_t *f, hbool_t H5_ATTR_UNUSED disable_shared, const voi
FUNC_ENTER_NOAPI_NOINIT_NOERR
ret_value = 3 /* Version, strategy & persist */
- + (size_t)H5F_SIZEOF_SIZE(f) /* Free-space section threshold */
- + (size_t)H5F_SIZEOF_SIZE(f) /* File space page size */
- + 2 /* Page end meta threshold */
- + (size_t)H5F_SIZEOF_ADDR(f);
-
+ + (size_t)H5F_SIZEOF_SIZE(f) /* Free-space section threshold */
+ + (size_t)H5F_SIZEOF_SIZE(f) /* File space page size */
+ + 2 /* Page end meta threshold */
+ + (size_t)H5F_SIZEOF_ADDR(f);
+
/* Free-space manager addresses */
if(fsinfo->persist)
ret_value += (H5F_MEM_PAGE_NTYPES - 1) * (size_t)H5F_SIZEOF_ADDR(f);
@@ -307,7 +316,7 @@ H5O_fsinfo_size(const H5F_t *f, hbool_t H5_ATTR_UNUSED disable_shared, const voi
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_fsinfo_size() */
-
+
/*-------------------------------------------------------------------------
* Function: H5O__fsinfo_free
*
@@ -331,7 +340,80 @@ H5O__fsinfo_free(void *mesg)
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O__fsinfo_free() */
-
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_fsinfo_set_version
+ *
+ * Purpose: Set the version to encode the fsinfo message with.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Vailin Choi; June 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5O_fsinfo_set_version(H5F_libver_t low, H5F_libver_t high, H5O_fsinfo_t *fsinfo)
+{
+ unsigned version; /* Message version */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check */
+ HDcompile_assert(N_FSINFO_VERSION_BOUNDS == H5F_LIBVER_NBOUNDS);
+ HDassert(fsinfo);
+
+ version = H5O_FSINFO_VERSION_1;
+
+ /* Upgrade to the version indicated by the file's low bound if higher */
+ if(H5O_fsinfo_ver_bounds[low] != H5O_INVALID_VERSION)
+ version = MAX(version, H5O_fsinfo_ver_bounds[low]);
+
+ /* Version bounds check */
+ if(H5O_fsinfo_ver_bounds[high] == H5O_INVALID_VERSION || version > H5O_fsinfo_ver_bounds[high])
+ HGOTO_ERROR(H5E_OHDR, H5E_BADRANGE, FAIL, "File space info message's version out of bounds")
+
+ /* Set the message version */
+ fsinfo->version = version;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_fsinfo_set_version() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_fsinfo_check_version
+ *
+ * Purpose: Validate the fsinfo message version
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Dana Robinson
+ * Summer 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5O_fsinfo_check_version(H5F_libver_t high, H5O_fsinfo_t *fsinfo)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check */
+ HDcompile_assert(N_FSINFO_VERSION_BOUNDS == H5F_LIBVER_NBOUNDS);
+ HDassert(fsinfo);
+
+ /* Check the version */
+ if(H5O_fsinfo_ver_bounds[high] == H5O_INVALID_VERSION || fsinfo->version > H5O_fsinfo_ver_bounds[high])
+ HGOTO_ERROR(H5E_OHDR, H5E_BADRANGE, FAIL, "File space info message's version out of bounds")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_fsinfo_check_version() */
+
+
/*-------------------------------------------------------------------------
* Function: H5O__fsinfo_debug
*
@@ -347,7 +429,7 @@ static herr_t
H5O__fsinfo_debug(H5F_t H5_ATTR_UNUSED *f, const void *_mesg, FILE * stream,
int indent, int fwidth)
{
- const H5O_fsinfo_t *fsinfo = (const H5O_fsinfo_t *) _mesg;
+ const H5O_fsinfo_t *fsinfo = (const H5O_fsinfo_t *) _mesg;
H5F_mem_page_t ptype; /* Free-space types for iteration */
FUNC_ENTER_STATIC_NOERR
diff --git a/src/H5Oint.c b/src/H5Oint.c
index 44809e1..ecf347c 100644
--- a/src/H5Oint.c
+++ b/src/H5Oint.c
@@ -38,10 +38,9 @@
#include "H5Iprivate.h" /* IDs */
#include "H5Lprivate.h" /* Links */
#include "H5MFprivate.h" /* File memory management */
-#ifdef H5O_ENABLE_BOGUS
#include "H5MMprivate.h" /* Memory management */
-#endif /* H5O_ENABLE_BOGUS */
#include "H5Opkg.h" /* Object headers */
+#include "H5VLprivate.h" /* Virtual Object Layer */
/****************/
@@ -56,7 +55,7 @@
/* User data for recursive traversal over objects from a group */
typedef struct {
hid_t obj_id; /* The ID for the starting group */
- H5G_loc_t *start_loc; /* Location of starting group */
+ H5G_loc_t *start_loc; /* Location of starting group */
H5SL_t *visited; /* Skip list for tracking visited nodes */
H5O_iterate_t op; /* Application callback */
void *op_data; /* Application's op data */
@@ -82,7 +81,6 @@ static herr_t H5O__visit_cb(hid_t group, const char *name, const H5L_info_t *lin
void *_udata);
static const H5O_obj_class_t *H5O__obj_class_real(const H5O_t *oh);
-
/*********************/
/* Package Variables */
/*********************/
@@ -96,47 +94,44 @@ hbool_t H5_PKG_INIT_VAR = FALSE;
* message.
*/
const H5O_msg_class_t *const H5O_msg_class_g[] = {
- H5O_MSG_NULL, /*0x0000 Null */
- H5O_MSG_SDSPACE, /*0x0001 Dataspace */
- H5O_MSG_LINFO, /*0x0002 Link information */
- H5O_MSG_DTYPE, /*0x0003 Datatype */
- H5O_MSG_FILL, /*0x0004 Old data storage -- fill value */
- H5O_MSG_FILL_NEW, /*0x0005 New data storage -- fill value */
- H5O_MSG_LINK, /*0x0006 Link */
- H5O_MSG_EFL, /*0x0007 Data storage -- external data files */
- H5O_MSG_LAYOUT, /*0x0008 Data Layout */
+ H5O_MSG_NULL, /*0x0000 Null */
+ H5O_MSG_SDSPACE, /*0x0001 Dataspace */
+ H5O_MSG_LINFO, /*0x0002 Link information */
+ H5O_MSG_DTYPE, /*0x0003 Datatype */
+ H5O_MSG_FILL, /*0x0004 Old data storage -- fill value */
+ H5O_MSG_FILL_NEW, /*0x0005 New data storage -- fill value */
+ H5O_MSG_LINK, /*0x0006 Link */
+ H5O_MSG_EFL, /*0x0007 Data storage -- external data files */
+ H5O_MSG_LAYOUT, /*0x0008 Data Layout */
#ifdef H5O_ENABLE_BOGUS
- H5O_MSG_BOGUS_VALID, /*0x0009 "Bogus valid" (for testing) */
+ H5O_MSG_BOGUS_VALID, /*0x0009 "Bogus valid" (for testing) */
#else /* H5O_ENABLE_BOGUS */
- NULL, /*0x0009 "Bogus valid" (for testing) */
+ NULL, /*0x0009 "Bogus valid" (for testing) */
#endif /* H5O_ENABLE_BOGUS */
- H5O_MSG_GINFO, /*0x000A Group information */
- H5O_MSG_PLINE, /*0x000B Data storage -- filter pipeline */
- H5O_MSG_ATTR, /*0x000C Attribute */
- H5O_MSG_NAME, /*0x000D Object name */
- H5O_MSG_MTIME, /*0x000E Object modification date and time */
- H5O_MSG_SHMESG, /*0x000F File-wide shared message table */
- H5O_MSG_CONT, /*0x0010 Object header continuation */
- H5O_MSG_STAB, /*0x0011 Symbol table */
- H5O_MSG_MTIME_NEW, /*0x0012 New Object modification date and time */
- H5O_MSG_BTREEK, /*0x0013 Non-default v1 B-tree 'K' values */
- H5O_MSG_DRVINFO, /*0x0014 Driver info settings */
- H5O_MSG_AINFO, /*0x0015 Attribute information */
- H5O_MSG_REFCOUNT, /*0x0016 Object's ref. count */
- H5O_MSG_FSINFO, /*0x0017 Free-space manager info */
+ H5O_MSG_GINFO, /*0x000A Group information */
+ H5O_MSG_PLINE, /*0x000B Data storage -- filter pipeline */
+ H5O_MSG_ATTR, /*0x000C Attribute */
+ H5O_MSG_NAME, /*0x000D Object name */
+ H5O_MSG_MTIME, /*0x000E Object modification date and time */
+ H5O_MSG_SHMESG, /*0x000F File-wide shared message table */
+ H5O_MSG_CONT, /*0x0010 Object header continuation */
+ H5O_MSG_STAB, /*0x0011 Symbol table */
+ H5O_MSG_MTIME_NEW, /*0x0012 New Object modification date and time */
+ H5O_MSG_BTREEK, /*0x0013 Non-default v1 B-tree 'K' values */
+ H5O_MSG_DRVINFO, /*0x0014 Driver info settings */
+ H5O_MSG_AINFO, /*0x0015 Attribute information */
+ H5O_MSG_REFCOUNT, /*0x0016 Object's ref. count */
+ H5O_MSG_FSINFO, /*0x0017 Free-space manager info */
H5O_MSG_MDCI, /*0x0018 Metadata cache image */
- H5O_MSG_UNKNOWN, /*0x0019 Placeholder for unknown message */
-#ifdef H5O_ENABLE_BOGUS
- H5O_MSG_BOGUS_INVALID, /*0x001A "Bogus invalid" (for testing) */
-#else /* H5O_ENABLE_BOGUS */
- NULL, /*0x001A "Bogus invalid" (for testing) */
-#endif /* H5O_ENABLE_BOGUS */
+ H5O_MSG_UNKNOWN /*0x0019 Placeholder for unknown message */
};
/* Format version bounds for object header */
const unsigned H5O_obj_ver_bounds[] = {
H5O_VERSION_1, /* H5F_LIBVER_EARLIEST */
H5O_VERSION_2, /* H5F_LIBVER_V18 */
+ H5O_VERSION_2, /* H5F_LIBVER_V110 */
+ H5O_VERSION_2, /* H5F_LIBVER_V112 */
H5O_VERSION_LATEST /* H5F_LIBVER_LATEST */
};
@@ -178,20 +173,20 @@ H5FL_EXTERN(H5_obj_t);
* datatype message is a datatype but only some of them are datasets.
*/
static const H5O_obj_class_t *const H5O_obj_class_g[] = {
- H5O_OBJ_DATATYPE, /* Datatype object (H5O_TYPE_NAMED_DATATYPE - 2) */
- H5O_OBJ_DATASET, /* Dataset object (H5O_TYPE_DATASET - 1) */
- H5O_OBJ_GROUP, /* Group object (H5O_TYPE_GROUP - 0) */
+ H5O_OBJ_DATATYPE, /* Datatype object (H5O_TYPE_NAMED_DATATYPE - 2) */
+ H5O_OBJ_DATASET, /* Dataset object (H5O_TYPE_DATASET - 1) */
+ H5O_OBJ_GROUP, /* Group object (H5O_TYPE_GROUP - 0) */
};
-
+
/*-------------------------------------------------------------------------
- * Function: H5O__init_package
+ * Function: H5O__init_package
*
- * Purpose: Initialize information specific to H5O interface.
+ * Purpose: Initialize information specific to H5O interface.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* Thursday, January 18, 2007
*
*-------------------------------------------------------------------------
@@ -210,7 +205,7 @@ H5O__init_package(void)
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O__init_package() */
-
+
/*-------------------------------------------------------------------------
* Function: H5O_set_version
*
@@ -257,118 +252,202 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_set_version() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O_create
+ * Function: H5O_create
*
- * Purpose: Creates a new object header. Allocates space for it and
+ * Purpose: Creates a new object header. Allocates space for it and
* then calls an initialization function. The object header
* is opened for write access and should eventually be
* closed by calling H5O_close().
*
- * Return: Success: Non-negative, the ENT argument contains
- * information about the object header,
- * including its address.
+ * Return: Success: Non-negative, the ENT argument contains
+ * information about the object header,
+ * including its address.
*
- * Failure: Negative
+ * Failure: Negative
*
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Aug 5 1997
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Aug 5 1997
+ *
+ * Changes: 2018 August 17
+ * Jacob Smith
+ * Refactor out the operations into two separate steps --
+ * preparation and application -- to facilitate overriding the
+ * library-default size allocated for the object header. This
+ * function is retained as a wrapper, to minimize changes to
+ * unaffected calling functions.
*
*-------------------------------------------------------------------------
*/
herr_t
-H5O_create(H5F_t *f, size_t size_hint, size_t initial_rc, hid_t ocpl_id,
- H5O_loc_t *loc/*out*/)
+H5O_create(H5F_t *f, size_t size_hint, size_t initial_rc, hid_t ocpl_id, H5O_loc_t *loc /*out*/)
{
- H5P_genplist_t *oc_plist; /* Object creation property list */
- H5O_t *oh = NULL; /* Object header created */
- haddr_t oh_addr; /* Address of initial object header */
- size_t oh_size; /* Size of initial object header */
- uint8_t oh_flags; /* Object header's initial status flags */
- unsigned insert_flags = H5AC__NO_FLAGS_SET; /* Flags for inserting object header into cache */
- hbool_t store_msg_crt_idx; /* Whether to always store message creation indices for this file */
- herr_t ret_value = SUCCEED; /* return value */
+ H5O_t *oh = NULL;
+ herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
- /* check args */
HDassert(f);
HDassert(loc);
HDassert(TRUE == H5P_isa_class(ocpl_id, H5P_OBJECT_CREATE));
+ /* create object header in freelist
+ * header version is set internally
+ */
+ oh = H5O__create_ohdr(f, ocpl_id);
+ if(NULL == oh)
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "Can't instantiate object header")
+
+ /* apply object header information to file
+ */
+ if(H5O__apply_ohdr(f, oh, ocpl_id, size_hint, initial_rc, loc) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "Can't apply object header to file")
+
+done:
+ if((FAIL == ret_value) && (NULL != oh) && (H5O__free(oh) < 0))
+ HDONE_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "can't delete object header")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_create() */
+
+
+/*-----------------------------------------------------------------------------
+ * Function: H5O__create_ohdr
+ *
+ * Purpose: Create the object header, set version and flags.
+ *
+ * Return: Success: Pointer to the newly-crated header object.
+ * Failure: NULL
+ *
+ * Programmer: Jacob Smith
+ * 2018 August 17
+ *
+ *-----------------------------------------------------------------------------
+ */
+H5O_t *
+H5O__create_ohdr(H5F_t *f, hid_t ocpl_id)
+{
+ H5P_genplist_t *oc_plist;
+ H5O_t *oh = NULL; /* Object header in Freelist */
+ uint8_t oh_flags; /* Initial status flags */
+ H5O_t *ret_value = NULL;
+
+ FUNC_ENTER_NOAPI(NULL)
+
+ HDassert(f);
+ HDassert(TRUE == H5P_isa_class(ocpl_id, H5P_OBJECT_CREATE));
+
/* Check for invalid access request */
if(0 == (H5F_INTENT(f) & H5F_ACC_RDWR))
- HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "no write intent on file")
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "no write intent on file")
- /* Make certain we allocate at least a reasonable size for the object header */
- size_hint = H5O_ALIGN_F(f, MAX(H5O_MIN_SIZE, size_hint));
+ oh = H5FL_CALLOC(H5O_t);
+ if(NULL == oh)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- /* Get the property list */
- if(NULL == (oc_plist = (H5P_genplist_t *)H5I_object(ocpl_id)))
- HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a property list")
+ oc_plist = (H5P_genplist_t *)H5I_object(ocpl_id);
+ if(NULL == oc_plist)
+ HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, NULL, "not a property list")
/* Get any object header status flags set by properties */
if(H5P_get(oc_plist, H5O_CRT_OHDR_FLAGS_NAME, &oh_flags) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get object header flags")
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get object header flags")
- /* Allocate the object header and zero out header fields */
- if(NULL == (oh = H5FL_CALLOC(H5O_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ if(H5O_set_version(f, oh, oh_flags, H5F_STORE_MSG_CRT_IDX(f)) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, NULL, "can't set version of object header")
- /* Initialize file-specific information for object header */
- store_msg_crt_idx = H5F_STORE_MSG_CRT_IDX(f);
+ oh->flags = oh_flags;
- if(H5O_set_version(f, oh, oh_flags, store_msg_crt_idx) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set version of objecdt header")
+ ret_value = oh;
+
+done:
+ if((NULL == ret_value) && (NULL != oh) && (H5O__free(oh) < 0))
+ HDONE_ERROR(H5E_OHDR, H5E_CANTFREE, NULL, "can't delete object header")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5O__create_ohdr() */
+
+
+/*-----------------------------------------------------------------------------
+ * Function: H5O__apply_ohdr
+ *
+ * Purpose: Initialize and set the object header in the file.
+ * Record some information at `loc_out`.
+ *
+ * Return: Success: SUCCEED (0) (non-negative value)
+ * Failure: FAIL (-1) (negative value)
+ *
+ * Programmer: Jacob Smith
+ * 2018 August 17
+ *
+ *-----------------------------------------------------------------------------
+ */
+herr_t
+H5O__apply_ohdr(H5F_t *f, H5O_t *oh, hid_t ocpl_id, size_t size_hint, size_t initial_rc, H5O_loc_t *loc_out)
+{
+ haddr_t oh_addr;
+ size_t oh_size;
+ H5P_genplist_t *oc_plist = NULL;
+ unsigned insert_flags = H5AC__NO_FLAGS_SET;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ HDassert(f);
+ HDassert(loc_out);
+ HDassert(oh);
+ HDassert(TRUE == H5P_isa_class(ocpl_id, H5P_OBJECT_CREATE));
+
+ /* Allocate at least a reasonable size for the object header */
+ size_hint = H5O_ALIGN_F(f, MAX(H5O_MIN_SIZE, size_hint));
oh->sizeof_size = H5F_SIZEOF_SIZE(f);
oh->sizeof_addr = H5F_SIZEOF_ADDR(f);
- oh->swmr_write = !!(H5F_INTENT(f) & H5F_ACC_SWMR_WRITE);
+ oh->swmr_write = !!(H5F_INTENT(f) & H5F_ACC_SWMR_WRITE); /* funky cast */
+
#ifdef H5O_ENABLE_BAD_MESG_COUNT
/* Check whether the "bad message count" property is set */
- if(H5P_exist_plist(oc_plist, H5O_BAD_MESG_COUNT_NAME) > 0) {
- /* Retrieve bad message count flag */
+ if(0 < H5P_exist_plist(oc_plist, H5O_BAD_MESG_COUNT_NAME))
+ /* Get bad message count flag -- from property list */
if(H5P_get(oc_plist, H5O_BAD_MESG_COUNT_NAME, &oh->store_bad_mesg_count) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't get bad message count flag")
- }
#endif /* H5O_ENABLE_BAD_MESG_COUNT */
/* Create object header proxy if doing SWMR writes */
if(oh->swmr_write) {
- /* Create virtual entry, for use as proxy */
- if(NULL == (oh->proxy = H5AC_proxy_entry_create()))
+ oh->proxy = H5AC_proxy_entry_create();
+ if(NULL == oh->proxy)
HGOTO_ERROR(H5E_OHDR, H5E_CANTCREATE, FAIL, "can't create object header proxy")
- }
- else
+ } else {
oh->proxy = NULL;
+ }
- /* Set initial status flags */
- oh->flags = oh_flags;
+ oc_plist = (H5P_genplist_t *)H5I_object(ocpl_id);
+ if(NULL == oc_plist)
+ HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a property list")
/* Initialize version-specific fields */
if(oh->version > H5O_VERSION_1) {
- /* Initialize all time fields with current time, if we are storing them */
+ /* Initialize all time fields */
if(oh->flags & H5O_HDR_STORE_TIMES)
oh->atime = oh->mtime = oh->ctime = oh->btime = H5_now();
else
oh->atime = oh->mtime = oh->ctime = oh->btime = 0;
- /* Make certain attribute creation order tracking is enabled if
- * attributes can be shared in this file.
- */
- if(store_msg_crt_idx)
+ if(H5F_STORE_MSG_CRT_IDX(f))
+ /* flag to record message creation indices */
oh->flags |= H5O_HDR_ATTR_CRT_ORDER_TRACKED;
- /* Retrieve attribute storage phase change values from property list */
+ /* Get attribute storage phase change values -- from property list */
if(H5P_get(oc_plist, H5O_CRT_ATTR_MAX_COMPACT_NAME, &oh->max_compact) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get max. # of compact attributes")
if(H5P_get(oc_plist, H5O_CRT_ATTR_MIN_DENSE_NAME, &oh->min_dense) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get min. # of dense attributes")
/* Check for non-default attribute storage phase change values */
- if(oh->max_compact != H5O_CRT_ATTR_MAX_COMPACT_DEF || oh->min_dense != H5O_CRT_ATTR_MIN_DENSE_DEF)
+ if(H5O_CRT_ATTR_MAX_COMPACT_DEF != oh->max_compact || H5O_CRT_ATTR_MIN_DENSE_DEF != oh->min_dense )
oh->flags |= H5O_HDR_ATTR_STORE_PHASE_CHANGE;
/* Determine correct value for chunk #0 size bits */
@@ -382,23 +461,25 @@ H5O_create(H5F_t *f, size_t size_hint, size_t initial_rc, hid_t ocpl_id,
oh->flags |= H5O_HDR_CHUNK0_4;
else if(size_hint > 255)
oh->flags |= H5O_HDR_CHUNK0_2;
- } /* end if */
- else {
+ } else {
/* Reset unused time fields */
oh->atime = oh->mtime = oh->ctime = oh->btime = 0;
- } /* end else */
+ } /* end if/else header version >1 */
/* Compute total size of initial object header */
/* (i.e. object header prefix and first chunk) */
oh_size = (size_t)H5O_SIZEOF_HDR(oh) + size_hint;
/* Allocate disk space for header and first chunk */
- if(HADDR_UNDEF == (oh_addr = H5MF_alloc(f, H5FD_MEM_OHDR, (hsize_t)oh_size)))
+ oh_addr = H5MF_alloc(f, H5FD_MEM_OHDR, (hsize_t)oh_size);
+ if(HADDR_UNDEF == oh_addr)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for object header")
/* Create the chunk list */
- oh->nchunks = oh->alloc_nchunks = 1;
- if(NULL == (oh->chunk = H5FL_SEQ_MALLOC(H5O_chunk_t, (size_t)oh->alloc_nchunks)))
+ oh->nchunks = 1;
+ oh->alloc_nchunks = 1;
+ oh->chunk = H5FL_SEQ_MALLOC(H5O_chunk_t, (size_t)oh->alloc_nchunks);
+ if(NULL == oh->chunk)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
/* Initialize the first chunk */
@@ -408,25 +489,27 @@ H5O_create(H5F_t *f, size_t size_hint, size_t initial_rc, hid_t ocpl_id,
/* Allocate enough space for the first chunk */
/* (including space for serializing the object header prefix */
- if(NULL == (oh->chunk[0].image = H5FL_BLK_CALLOC(chunk_image, oh_size)))
+ oh->chunk[0].image = H5FL_BLK_CALLOC(chunk_image, oh_size);
+ if(NULL == oh->chunk[0].image)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
oh->chunk[0].chunk_proxy = NULL;
/* Put magic # for object header in first chunk */
- if(oh->version > H5O_VERSION_1)
- HDmemcpy(oh->chunk[0].image, H5O_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ if(H5O_VERSION_1 < oh->version)
+ H5MM_memcpy(oh->chunk[0].image, H5O_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
/* Create the message list */
oh->nmesgs = 1;
oh->alloc_nmesgs = H5O_NMESGS;
- if(NULL == (oh->mesg = H5FL_SEQ_CALLOC(H5O_mesg_t, oh->alloc_nmesgs)))
+ oh->mesg = H5FL_SEQ_CALLOC(H5O_mesg_t, oh->alloc_nmesgs);
+ if(NULL == oh->mesg)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
- /* Initialize the initial "null" message, covering the entire first chunk */
+ /* Initialize the initial "null" message; covers the entire first chunk */
oh->mesg[0].type = H5O_MSG_NULL;
oh->mesg[0].dirty = TRUE;
oh->mesg[0].native = NULL;
- oh->mesg[0].raw = oh->chunk[0].image + (H5O_SIZEOF_HDR(oh) - H5O_SIZEOF_CHKSUM_OH(oh)) + H5O_SIZEOF_MSGHDR_OH(oh);
+ oh->mesg[0].raw = oh->chunk[0].image + H5O_SIZEOF_HDR(oh) - H5O_SIZEOF_CHKSUM_OH(oh) + H5O_SIZEOF_MSGHDR_OH(oh);
oh->mesg[0].raw_size = size_hint - (size_t)H5O_SIZEOF_MSGHDR_OH(oh);
oh->mesg[0].chunkno = 0;
@@ -451,32 +534,27 @@ H5O_create(H5F_t *f, size_t size_hint, size_t initial_rc, hid_t ocpl_id,
H5_END_TAG
/* Set up object location */
- loc->file = f;
- loc->addr = oh_addr;
+ loc_out->file = f;
+ loc_out->addr = oh_addr;
- /* Open it */
- if(H5O_open(loc) < 0)
+ if(H5O_open(loc_out) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, FAIL, "unable to open object header")
done:
- if(ret_value < 0 && oh)
- if(H5O__free(oh) < 0)
- HDONE_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to destroy object header data")
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* H5O__apply_ohdr() */
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5O_create() */
-
/*-------------------------------------------------------------------------
- * Function: H5O_open
+ * Function: H5O_open
*
- * Purpose: Opens an object header which is described by the symbol table
- * entry OBJ_ENT.
+ * Purpose: Opens an object header which is described by the symbol table
+ * entry OBJ_ENT.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Robb Matzke
- * Monday, January 5, 1998
+ * Programmer: Robb Matzke
+ * Monday, January 5, 1998
*
* Modification:
* Raymond Lu
@@ -503,7 +581,7 @@ H5O_open(H5O_loc_t *loc)
/* Turn off the variable for holding file or increment open-lock counters */
if(loc->holding_file)
- loc->holding_file = FALSE;
+ loc->holding_file = FALSE;
else
H5F_INCR_NOPEN_OBJS(loc->file);
@@ -511,30 +589,30 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_open() */
-
+
/*-------------------------------------------------------------------------
* Function: H5O_open_name
*
- * Purpose: Opens an object within an HDF5 file.
+ * Purpose: Opens an object by name
*
- * Return: Success: Open object identifier
- * Failure: H5I_INVALID_HID
+ * Return: Success: Pointer to object data
+ * Failure: NULL
*
- * Programmer: Quincey Koziol
- * March 5 2007
+ * Programmer: Quincey Koziol
+ * March 5 2007
*
*-------------------------------------------------------------------------
*/
-hid_t
-H5O_open_name(const H5G_loc_t *loc, const char *name, hbool_t app_ref)
+void *
+H5O_open_name(const H5G_loc_t *loc, const char *name, H5I_type_t *opened_type)
{
H5G_loc_t obj_loc; /* Location used to open group */
- H5G_name_t obj_path; /* Opened object group hier. path */
- H5O_loc_t obj_oloc; /* Opened object object location */
+ H5G_name_t obj_path; /* Opened object group hier. path */
+ H5O_loc_t obj_oloc; /* Opened object object location */
hbool_t loc_found = FALSE; /* Entry at 'name' found */
- hid_t ret_value = H5I_INVALID_HID;
+ void *ret_value = NULL; /* Return value */
- FUNC_ENTER_NOAPI(H5I_INVALID_HID)
+ FUNC_ENTER_NOAPI(NULL)
/* Check args */
HDassert(loc);
@@ -547,46 +625,46 @@ H5O_open_name(const H5G_loc_t *loc, const char *name, hbool_t app_ref)
/* Find the object's location */
if(H5G_loc_find(loc, name, &obj_loc/*out*/) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, H5I_INVALID_HID, "object not found")
+ HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, NULL, "object not found")
loc_found = TRUE;
/* Open the object */
- if((ret_value = H5O_open_by_loc(&obj_loc, app_ref)) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open object")
+ if(NULL == (ret_value = H5O_open_by_loc(&obj_loc, opened_type)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, NULL, "unable to open object")
done:
- if(ret_value < 0 && loc_found)
- if(H5G_loc_free(&obj_loc) < 0)
- HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, H5I_INVALID_HID, "can't free location")
+ if(NULL == ret_value)
+ if(loc_found && H5G_loc_free(&obj_loc) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, NULL, "can't free location")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_open_name() */
-
+
/*-------------------------------------------------------------------------
* Function: H5O_open_by_idx
*
* Purpose: Internal routine to open an object by index within group
*
- * Return: Success: Open object identifier
- * Failure: H5I_INVALID_HID
+ * Return: Success: Pointer to object data
+ * Failure: NULL
*
- * Programmer: Quincey Koziol
- * December 28, 2017
+ * Programmer: Quincey Koziol
+ * December 28, 2017
*
*-------------------------------------------------------------------------
*/
-hid_t
+void *
H5O_open_by_idx(const H5G_loc_t *loc, const char *name, H5_index_t idx_type,
- H5_iter_order_t order, hsize_t n)
+ H5_iter_order_t order, hsize_t n, H5I_type_t *opened_type)
{
H5G_loc_t obj_loc; /* Location used to open group */
- H5G_name_t obj_path; /* Opened object group hier. path */
- H5O_loc_t obj_oloc; /* Opened object object location */
+ H5G_name_t obj_path; /* Opened object group hier. path */
+ H5O_loc_t obj_oloc; /* Opened object object location */
hbool_t loc_found = FALSE; /* Entry at 'name' found */
- hid_t ret_value = H5I_INVALID_HID; /* Return value */
+ void *ret_value = NULL; /* Return value */
- FUNC_ENTER_NOAPI(H5I_INVALID_HID)
+ FUNC_ENTER_NOAPI(NULL)
/* Check arguments */
HDassert(loc);
@@ -598,45 +676,45 @@ H5O_open_by_idx(const H5G_loc_t *loc, const char *name, H5_index_t idx_type,
/* Find the object's location, according to the order in the index */
if(H5G_loc_find_by_idx(loc, name, idx_type, order, n, &obj_loc/*out*/) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, H5I_INVALID_HID, "group not found")
+ HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, NULL, "group not found")
loc_found = TRUE;
/* Open the object */
- if((ret_value = H5O_open_by_loc(&obj_loc, TRUE)) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open object")
+ if(NULL == (ret_value = H5O_open_by_loc(&obj_loc, opened_type)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, NULL, "unable to open object")
done:
/* Release the object location if we failed after copying it */
- if(ret_value < 0 && loc_found)
- if(H5G_loc_free(&obj_loc) < 0)
- HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, H5I_INVALID_HID, "can't free location")
+ if(NULL == ret_value)
+ if(loc_found && H5G_loc_free(&obj_loc) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, NULL, "can't free location")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_open_by_idx() */
-
+
/*-------------------------------------------------------------------------
* Function: H5O_open_by_addr
*
* Purpose: Internal routine to open an object by its address
*
- * Return: Success: Open object identifier
- * Failure: H5I_INVALID_HID
+ * Return: Success: Pointer to object data
+ * Failure: NULL
*
- * Programmer: Quincey Koziol
- * December 28, 2017
+ * Programmer: Quincey Koziol
+ * December 28, 2017
*
*-------------------------------------------------------------------------
*/
-hid_t
-H5O_open_by_addr(const H5G_loc_t *loc, haddr_t addr)
+void *
+H5O_open_by_addr(const H5G_loc_t *loc, haddr_t addr, H5I_type_t *opened_type)
{
H5G_loc_t obj_loc; /* Location used to open group */
- H5G_name_t obj_path; /* Opened object group hier. path */
- H5O_loc_t obj_oloc; /* Opened object object location */
- hid_t ret_value = H5I_INVALID_HID; /* Return value */
+ H5G_name_t obj_path; /* Opened object group hier. path */
+ H5O_loc_t obj_oloc; /* Opened object object location */
+ void *ret_value = NULL; /* Return value */
- FUNC_ENTER_NOAPI(H5I_INVALID_HID)
+ FUNC_ENTER_NOAPI(NULL)
/* Check arguments */
HDassert(loc);
@@ -650,60 +728,60 @@ H5O_open_by_addr(const H5G_loc_t *loc, haddr_t addr)
H5G_name_reset(obj_loc.path); /* objects opened through this routine don't have a path name */
/* Open the object */
- if((ret_value = H5O_open_by_loc(&obj_loc, TRUE)) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open object")
+ if(NULL == (ret_value = H5O_open_by_loc(&obj_loc, opened_type)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, NULL, "unable to open object")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_open_by_addr() */
-
+
/*-------------------------------------------------------------------------
* Function: H5O_open_by_loc
*
- * Purpose: Opens an object and returns an ID given its group loction.
+ * Purpose: Opens an object
*
- * Return: Success: Open object identifier
- * Failure: H5I_INVALID_HID
+ * Return: Success: Pointer to object data
+ * Failure: NULL
*
- * Programmer: James Laird
- * July 25 2006
+ * Programmer: James Laird
+ * July 25 2006
*
*-------------------------------------------------------------------------
*/
-hid_t
-H5O_open_by_loc(const H5G_loc_t *obj_loc, hbool_t app_ref)
+void *
+H5O_open_by_loc(const H5G_loc_t *obj_loc, H5I_type_t *opened_type)
{
const H5O_obj_class_t *obj_class; /* Class of object for location */
- hid_t ret_value = H5I_INVALID_HID; /* Return value */
+ void *ret_value = NULL; /* Return value */
- FUNC_ENTER_NOAPI(H5I_INVALID_HID)
+ FUNC_ENTER_NOAPI(NULL)
HDassert(obj_loc);
/* Get the object class for this location */
if(NULL == (obj_class = H5O__obj_class(obj_loc->oloc)))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, H5I_INVALID_HID, "unable to determine object class")
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "unable to determine object class")
/* Call the object class's 'open' routine */
HDassert(obj_class->open);
- if((ret_value = obj_class->open(obj_loc, app_ref)) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open object")
+ if(NULL == (ret_value = obj_class->open(obj_loc, opened_type)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, NULL, "unable to open object")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_open_by_loc() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O_close
+ * Function: H5O_close
*
- * Purpose: Closes an object header that was previously open.
+ * Purpose: Closes an object header that was previously open.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Robb Matzke
- * Monday, January 5, 1998
+ * Programmer: Robb Matzke
+ * Monday, January 5, 1998
*
*-------------------------------------------------------------------------
*/
@@ -733,7 +811,7 @@ H5O_close(H5O_loc_t *loc, hbool_t *file_closed /*out*/)
#ifdef H5O_DEBUG
if(H5DEBUG(O)) {
- if(H5F_FILE_ID(loc->file)< 0 && 1 == H5F_NREFS(loc->file))
+ if(FALSE == H5F_ID_EXISTS(loc->file) && 1 == H5F_NREFS(loc->file))
HDfprintf(H5DEBUG(O), "< %a auto %lu remaining\n", loc->addr, (unsigned long)H5F_NOPEN_OBJS(loc->file));
else
HDfprintf(H5DEBUG(O), "< %a\n", loc->addr);
@@ -757,7 +835,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_close() */
-
+
/*-------------------------------------------------------------------------
* Function: H5O__link_oh
*
@@ -768,9 +846,9 @@ done:
*
* Failure: -1
*
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Aug 5 1997
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Aug 5 1997
*
*-------------------------------------------------------------------------
*/
@@ -778,7 +856,7 @@ int
H5O__link_oh(H5F_t *f, int adjust, H5O_t *oh, hbool_t *deleted)
{
haddr_t addr = H5O_OH_GET_ADDR(oh); /* Object header address */
- int ret_value = -1; /* Return value */
+ int ret_value = -1; /* Return value */
FUNC_ENTER_PACKAGE
@@ -872,29 +950,29 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O__link_oh() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O_link
+ * Function: H5O_link
*
- * Purpose: Adjust the link count for an object header by adding
- * ADJUST to the link count.
+ * Purpose: Adjust the link count for an object header by adding
+ * ADJUST to the link count.
*
- * Return: Success: New link count
+ * Return: Success: New link count
*
- * Failure: Negative
+ * Failure: Negative
*
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Aug 5 1997
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Aug 5 1997
*
*-------------------------------------------------------------------------
*/
int
H5O_link(const H5O_loc_t *loc, int adjust)
{
- H5O_t *oh = NULL;
+ H5O_t *oh = NULL;
hbool_t deleted = FALSE; /* Whether the object was deleted */
- int ret_value = -1; /* Return value */
+ int ret_value = -1; /* Return value */
FUNC_ENTER_NOAPI_TAG(loc->addr, FAIL)
@@ -920,21 +998,21 @@ done:
FUNC_LEAVE_NOAPI_TAG(ret_value)
} /* end H5O_link() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O_protect
+ * Function: H5O_protect
*
- * Purpose: Wrapper around H5AC_protect for use during a H5O_protect->
+ * Purpose: Wrapper around H5AC_protect for use during a H5O_protect->
* H5O_msg_append->...->H5O_msg_append->H5O_unprotect sequence of calls
* during an object's creation.
*
- * Return: Success: Pointer to the object header structure for the
+ * Return: Success: Pointer to the object header structure for the
* object.
- * Failure: NULL
+ * Failure: NULL
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Dec 31 2002
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Dec 31 2002
*
*-------------------------------------------------------------------------
*/
@@ -1106,21 +1184,21 @@ done:
FUNC_LEAVE_NOAPI_TAG(ret_value)
} /* end H5O_protect() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O_pin
+ * Function: H5O_pin
*
- * Purpose: Pin an object header down for use during a sequence of message
+ * Purpose: Pin an object header down for use during a sequence of message
* operations, which prevents the object header from being
* evicted from the cache.
*
- * Return: Success: Pointer to the object header structure for the
+ * Return: Success: Pointer to the object header structure for the
* object.
- * Failure: NULL
+ * Failure: NULL
*
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Jul 13 2008
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Jul 13 2008
*
*-------------------------------------------------------------------------
*/
@@ -1155,19 +1233,19 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_pin() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O_unpin
+ * Function: H5O_unpin
*
- * Purpose: Unpin an object header, allowing it to be evicted from the
+ * Purpose: Unpin an object header, allowing it to be evicted from the
* metadata cache.
*
- * Return: Success: Non-negative
- * Failure: Negative
+ * Return: Success: Non-negative
+ * Failure: Negative
*
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Jul 13 2008
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Jul 13 2008
*
*-------------------------------------------------------------------------
*/
@@ -1190,20 +1268,20 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_unpin() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O_unprotect
+ * Function: H5O_unprotect
*
- * Purpose: Wrapper around H5AC_unprotect for use during a H5O_protect->
+ * Purpose: Wrapper around H5AC_unprotect for use during a H5O_protect->
* H5O_msg_append->...->H5O_msg_append->H5O_unprotect sequence of calls
* during an object's creation.
*
- * Return: Success: Non-negative
- * Failure: Negative
+ * Return: Success: Non-negative
+ * Failure: Negative
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Dec 31 2002
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Dec 31 2002
*
*-------------------------------------------------------------------------
*/
@@ -1247,17 +1325,17 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_unprotect() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O_touch_oh
+ * Function: H5O_touch_oh
*
- * Purpose: If FORCE is non-zero then create a modification time message
- * unless one already exists. Then update any existing
- * modification time message with the current time.
+ * Purpose: If FORCE is non-zero then create a modification time message
+ * unless one already exists. Then update any existing
+ * modification time message with the current time.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Robb Matzke
+ * Programmer: Robb Matzke
* Monday, July 27, 1998
*
*-------------------------------------------------------------------------
@@ -1267,7 +1345,7 @@ H5O_touch_oh(H5F_t *f, H5O_t *oh, hbool_t force)
{
H5O_chunk_proxy_t *chk_proxy = NULL; /* Chunk that message is in */
hbool_t chk_dirtied = FALSE; /* Flag for unprotecting chunk */
- time_t now; /* Current time */
+ time_t now; /* Current time */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
@@ -1282,7 +1360,7 @@ H5O_touch_oh(H5F_t *f, H5O_t *oh, hbool_t force)
/* Check version, to determine how to store time information */
if(oh->version == H5O_VERSION_1) {
- size_t idx; /* Index of modification time message to update */
+ size_t idx; /* Index of modification time message to update */
/* Look for existing message */
for(idx = 0; idx < oh->nmesgs; idx++)
@@ -1342,18 +1420,18 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_touch_oh() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O_touch
+ * Function: H5O_touch
*
- * Purpose: Touch an object by setting the modification time to the
- * current time and marking the object as dirty. Unless FORCE
- * is non-zero, nothing happens if there is no MTIME message in
- * the object header.
+ * Purpose: Touch an object by setting the modification time to the
+ * current time and marking the object as dirty. Unless FORCE
+ * is non-zero, nothing happens if there is no MTIME message in
+ * the object header.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Robb Matzke
+ * Programmer: Robb Matzke
* Monday, July 27, 1998
*
*-------------------------------------------------------------------------
@@ -1361,8 +1439,8 @@ done:
herr_t
H5O_touch(const H5O_loc_t *loc, hbool_t force)
{
- H5O_t *oh = NULL; /* Object header to modify */
- unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting object header */
+ H5O_t *oh = NULL; /* Object header to modify */
+ unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting object header */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
@@ -1389,15 +1467,15 @@ done:
} /* end H5O_touch() */
#ifdef H5O_ENABLE_BOGUS
-
+
/*-------------------------------------------------------------------------
- * Function: H5O_bogus_oh
+ * Function: H5O_bogus_oh
*
- * Purpose: Create a "bogus" message unless one already exists.
+ * Purpose: Create a "bogus" message unless one already exists.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* <koziol@ncsa.uiuc.edu>
* Tuesday, January 21, 2003
*
@@ -1406,8 +1484,8 @@ done:
herr_t
H5O_bogus_oh(H5F_t *f, H5O_t *oh, unsigned bogus_id, unsigned mesg_flags)
{
- size_t idx; /* Local index variable */
- H5O_msg_class_t *type; /* Message class type */
+ size_t idx; /* Local index variable */
+ H5O_msg_class_t *type; /* Message class type */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
@@ -1458,20 +1536,20 @@ done:
} /* end H5O_bogus_oh() */
#endif /* H5O_ENABLE_BOGUS */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O_delete
+ * Function: H5O_delete
*
- * Purpose: Delete an object header from a file. This frees the file
+ * Purpose: Delete an object header from a file. This frees the file
* space used for the object header (and it's continuation blocks)
* and also walks through each header message and asks it to
* remove all the pieces of the file referenced by the header.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Mar 19 2003
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Mar 19 2003
*
*-------------------------------------------------------------------------
*/
@@ -1520,21 +1598,21 @@ done:
FUNC_LEAVE_NOAPI_TAG(ret_value)
} /* end H5O_delete() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O__delete_oh
+ * Function: H5O__delete_oh
*
- * Purpose: Internal function to:
+ * Purpose: Internal function to:
* Delete an object header from a file. This frees the file
* space used for the object header (and it's continuation blocks)
* and also walks through each header message and asks it to
* remove all the pieces of the file referenced by the header.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Mar 19 2003
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Mar 19 2003
*
*-------------------------------------------------------------------------
*/
@@ -1542,7 +1620,7 @@ static herr_t
H5O__delete_oh(H5F_t *f, H5O_t *oh)
{
H5O_mesg_t *curr_msg; /* Pointer to current message being operated on */
- unsigned u;
+ unsigned u;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC
@@ -1564,16 +1642,16 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O__delete_oh() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O_obj_type
+ * Function: H5O_obj_type
*
- * Purpose: Retrieves the type of object pointed to by `loc'.
+ * Purpose: Retrieves the type of object pointed to by `loc'.
*
- * Return: Success: Non-negative
- * Failure: Negative
+ * Return: Success: Non-negative
+ * Failure: Negative
*
- * Programmer: Robb Matzke
+ * Programmer: Robb Matzke
* Wednesday, November 4, 1998
*
*-------------------------------------------------------------------------
@@ -1581,7 +1659,7 @@ done:
herr_t
H5O_obj_type(const H5O_loc_t *loc, H5O_type_t *obj_type)
{
- H5O_t *oh = NULL; /* Object header for location */
+ H5O_t *oh = NULL; /* Object header for location */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_TAG(loc->addr, FAIL)
@@ -1596,21 +1674,21 @@ H5O_obj_type(const H5O_loc_t *loc, H5O_type_t *obj_type)
done:
if(oh && H5O_unprotect(loc, oh, H5AC__NO_FLAGS_SET) < 0)
- HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
+ HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
FUNC_LEAVE_NOAPI_TAG(ret_value)
} /* end H5O_obj_type() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O__obj_type_real
+ * Function: H5O__obj_type_real
*
- * Purpose: Returns the type of object pointed to by `oh'.
+ * Purpose: Returns the type of object pointed to by `oh'.
*
- * Return: Success: Non-negative
- * Failure: Negative
+ * Return: Success: Non-negative
+ * Failure: Negative
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* Monday, November 21, 2005
*
*-------------------------------------------------------------------------
@@ -1642,7 +1720,7 @@ H5O__obj_type_real(const H5O_t *oh, H5O_type_t *obj_type)
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O__obj_type_real() */
-
+
/*-------------------------------------------------------------------------
* Function: H5O__obj_class
*
@@ -1651,7 +1729,7 @@ H5O__obj_type_real(const H5O_t *oh, H5O_type_t *obj_type)
* Return: Success: An object class
* Failure: NULL
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* Monday, November 6, 2006
*
*-------------------------------------------------------------------------
@@ -1659,7 +1737,7 @@ H5O__obj_type_real(const H5O_t *oh, H5O_type_t *obj_type)
const H5O_obj_class_t *
H5O__obj_class(const H5O_loc_t *loc)
{
- H5O_t *oh = NULL; /* Object header for location */
+ H5O_t *oh = NULL; /* Object header for location */
const H5O_obj_class_t *ret_value = NULL; /* Return value */
FUNC_ENTER_PACKAGE_TAG(loc->addr)
@@ -1679,16 +1757,16 @@ done:
FUNC_LEAVE_NOAPI_TAG(ret_value)
} /* end H5O__obj_class() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O__obj_class_real
+ * Function: H5O__obj_class_real
*
- * Purpose: Returns the class of object pointed to by `oh'.
+ * Purpose: Returns the class of object pointed to by `oh'.
*
- * Return: Success: An object class
- * Failure: NULL
+ * Return: Success: An object class
+ * Failure: NULL
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* Monday, November 21, 2005
*
*-------------------------------------------------------------------------
@@ -1696,7 +1774,7 @@ done:
static const H5O_obj_class_t *
H5O__obj_class_real(const H5O_t *oh)
{
- size_t i; /* Local index variable */
+ size_t i; /* Local index variable */
const H5O_obj_class_t *ret_value = NULL; /* Return value */
FUNC_ENTER_STATIC
@@ -1707,7 +1785,7 @@ H5O__obj_class_real(const H5O_t *oh)
/* Test whether entry qualifies as a particular type of object */
/* (Note: loop is in reverse order, to test specific objects first) */
for(i = NELMTS(H5O_obj_class_g); i > 0; --i) {
- htri_t isa; /* Is entry a particular type? */
+ htri_t isa; /* Is entry a particular type? */
if((isa = (H5O_obj_class_g[i - 1]->isa)(oh)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to determine object type")
@@ -1722,17 +1800,17 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O__obj_class_real() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O_get_loc
+ * Function: H5O_get_loc
*
- * Purpose: Gets the object location for an object given its ID.
+ * Purpose: Gets the object location for an object given its ID.
*
- * Return: Success: Pointer to H5O_loc_t
- * Failure: NULL
+ * Return: Success: Pointer to H5O_loc_t
+ * Failure: NULL
*
- * Programmer: James Laird
- * July 25 2006
+ * Programmer: James Laird
+ * July 25 2006
*
*-------------------------------------------------------------------------
*/
@@ -1759,18 +1837,22 @@ H5O_get_loc(hid_t object_id)
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "unable to get object location from datatype ID")
break;
+ case H5I_MAP:
+ HGOTO_ERROR(H5E_OHDR, H5E_BADTYPE, NULL, "maps not supported in native VOL connector")
+
case H5I_UNINIT:
case H5I_BADID:
case H5I_FILE:
case H5I_DATASPACE:
case H5I_ATTR:
- case H5I_REFERENCE:
case H5I_VFL:
+ case H5I_VOL:
case H5I_GENPROP_CLS:
case H5I_GENPROP_LST:
case H5I_ERROR_CLASS:
case H5I_ERROR_MSG:
case H5I_ERROR_STACK:
+ case H5I_SPACE_SEL_ITER:
case H5I_NTYPES:
default:
HGOTO_ERROR(H5E_OHDR, H5E_BADTYPE, NULL, "invalid object type")
@@ -1780,16 +1862,16 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_get_loc() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O_loc_reset
+ * Function: H5O_loc_reset
*
- * Purpose: Reset a object location to an empty state
+ * Purpose: Reset a object location to an empty state
*
- * Return: Success: Non-negative
- * Failure: Negative
+ * Return: Success: Non-negative
+ * Failure: Negative
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* Monday, September 19, 2005
*
*-------------------------------------------------------------------------
@@ -1809,16 +1891,16 @@ H5O_loc_reset(H5O_loc_t *loc)
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O_loc_reset() */
-
+
/*-------------------------------------------------------------------------
* Function: H5O_loc_copy
*
* Purpose: Copy object location information
*
- * Return: Success: Non-negative
- * Failure: Negative
+ * Return: Success: Non-negative
+ * Failure: Negative
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
* Monday, September 19, 2005
*
@@ -1843,7 +1925,7 @@ H5O_loc_copy(H5O_loc_t *dst, H5O_loc_t *src, H5_copy_depth_t depth)
HDassert(depth == H5_COPY_SHALLOW || depth == H5_COPY_DEEP);
/* Copy the top level information */
- HDmemcpy(dst, src, sizeof(H5O_loc_t));
+ H5MM_memcpy(dst, src, sizeof(H5O_loc_t));
/* Deep copy the names */
if(depth == H5_COPY_DEEP) {
@@ -1860,17 +1942,17 @@ H5O_loc_copy(H5O_loc_t *dst, H5O_loc_t *src, H5_copy_depth_t depth)
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O_loc_copy() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O_loc_hold_file
+ * Function: H5O_loc_hold_file
*
- * Purpose: Have this object header hold a file open until it is
+ * Purpose: Have this object header hold a file open until it is
* released.
*
- * Return: Success: Non-negative
- * Failure: Negative
+ * Return: Success: Non-negative
+ * Failure: Negative
*
- * Programmer: James Laird
+ * Programmer: James Laird
* Wednesday, August 16, 2006
*
*-------------------------------------------------------------------------
@@ -1893,18 +1975,18 @@ H5O_loc_hold_file(H5O_loc_t *loc)
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O_loc_hold_file() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O_loc_free
+ * Function: H5O_loc_free
*
- * Purpose: Release resources used by this object header location.
+ * Purpose: Release resources used by this object header location.
* Not to be confused with H5O_close; this is used on
* locations that don't correspond to open objects.
*
- * Return: Success: Non-negative
- * Failure: Negative
+ * Return: Success: Non-negative
+ * Failure: Negative
*
- * Programmer: James Laird
+ * Programmer: James Laird
* Wednesday, August 16, 2006
*
*-------------------------------------------------------------------------
@@ -1933,17 +2015,17 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_loc_free() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O_get_hdr_info
+ * Function: H5O_get_hdr_info
*
- * Purpose: Retrieve the object header information for an object
+ * Purpose: Retrieve the object header information for an object
*
- * Return: Success: Non-negative
- * Failure: Negative
+ * Return: Success: Non-negative
+ * Failure: Negative
*
- * Programmer: Quincey Koziol
- * September 22 2009
+ * Programmer: Quincey Koziol
+ * September 22 2009
*
*-------------------------------------------------------------------------
*/
@@ -1972,22 +2054,22 @@ H5O_get_hdr_info(const H5O_loc_t *loc, H5O_hdr_info_t *hdr)
done:
if(oh && H5O_unprotect(loc, oh, H5AC__NO_FLAGS_SET) < 0)
- HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header")
+ HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_get_hdr_info() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O__get_hdr_info_real
+ * Function: H5O__get_hdr_info_real
*
- * Purpose: Internal routine to retrieve the object header information for an object
+ * Purpose: Internal routine to retrieve the object header information for an object
*
- * Return: Success: Non-negative
- * Failure: Negative
+ * Return: Success: Non-negative
+ * Failure: Negative
*
- * Programmer: Quincey Koziol
- * September 22 2009
+ * Programmer: Quincey Koziol
+ * September 22 2009
*
*-------------------------------------------------------------------------
*/
@@ -1995,7 +2077,7 @@ static herr_t
H5O__get_hdr_info_real(const H5O_t *oh, H5O_hdr_info_t *hdr)
{
const H5O_mesg_t *curr_msg; /* Pointer to current message being operated on */
- const H5O_chunk_t *curr_chunk; /* Pointer to current message being operated on */
+ const H5O_chunk_t *curr_chunk; /* Pointer to current message being operated on */
unsigned u; /* Local index variable */
FUNC_ENTER_STATIC_NOERR
@@ -2058,16 +2140,16 @@ H5O__get_hdr_info_real(const H5O_t *oh, H5O_hdr_info_t *hdr)
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O__get_hdr_info_real() */
-
+
/*-------------------------------------------------------------------------
* Function: H5O_get_info
*
* Purpose: Retrieve the information for an object
*
* Note: Add a parameter "fields" to indicate selection of object info.
- *
- * Return: Success: Non-negative
- * Failure: Negative
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
*
* Programmer: Quincey Koziol
* November 21 2006
@@ -2111,7 +2193,7 @@ H5O_get_info(const H5O_loc_t *loc, H5O_info_t *oinfo, unsigned fields)
/* Set the object's reference count */
oinfo->rc = oh->nlink;
- }
+ } /* end if */
/* Get time information, if requested */
if(fields & H5O_INFO_TIME) {
@@ -2188,7 +2270,7 @@ done:
FUNC_LEAVE_NOAPI_TAG(ret_value)
} /* end H5O_get_info() */
-
+
/*-------------------------------------------------------------------------
* Function: H5O__get_info_by_idx
*
@@ -2198,8 +2280,8 @@ done:
*
* Note: Add a parameter "fields" to indicate selection of object info.
*
- * Return: Success: Non-negative
- * Failure: Negative
+ * Return: Success: Non-negative
+ * Failure: Negative
*
* Programmer: Quincey Koziol
* December 28, 2017
@@ -2211,10 +2293,10 @@ H5O__get_info_by_idx(const H5G_loc_t *loc, const char *group_name, H5_index_t id
H5_iter_order_t order, hsize_t n, H5O_info_t *oinfo, unsigned fields)
{
H5G_loc_t obj_loc; /* Location used to open group */
- H5G_name_t obj_path; /* Opened object group hier. path */
- H5O_loc_t obj_oloc; /* Opened object object location */
+ H5G_name_t obj_path; /* Opened object group hier. path */
+ H5O_loc_t obj_oloc; /* Opened object object location */
hbool_t loc_found = FALSE; /* Entry at 'name' found */
- herr_t ret_value = SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
@@ -2245,17 +2327,17 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O__get_info_by_idx() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O_get_create_plist
+ * Function: H5O_get_create_plist
*
- * Purpose: Retrieve the object creation properties for an object
+ * Purpose: Retrieve the object creation properties for an object
*
- * Return: Success: Non-negative
- * Failure: Negative
+ * Return: Success: Non-negative
+ * Failure: Negative
*
- * Programmer: Quincey Koziol
- * November 28 2006
+ * Programmer: Quincey Koziol
+ * November 28 2006
*
*-------------------------------------------------------------------------
*/
@@ -2300,17 +2382,17 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_get_create_plist() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O_get_nlinks
+ * Function: H5O_get_nlinks
*
- * Purpose: Retrieve the number of link messages read in from the file
+ * Purpose: Retrieve the number of link messages read in from the file
*
- * Return: Success: Non-negative
- * Failure: Negative
+ * Return: Success: Non-negative
+ * Failure: Negative
*
- * Programmer: Quincey Koziol
- * March 11 2007
+ * Programmer: Quincey Koziol
+ * March 11 2007
*
*-------------------------------------------------------------------------
*/
@@ -2340,17 +2422,17 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_get_nlinks() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O_obj_create
+ * Function: H5O_obj_create
*
- * Purpose: Creates an object, in an abstract manner.
+ * Purpose: Creates an object, in an abstract manner.
*
- * Return: Success: Pointer to object opened
- * Failure: NULL
+ * Return: Success: Pointer to object opened
+ * Failure: NULL
*
- * Programmer: Quincey Koziol
- * April 9 2007
+ * Programmer: Quincey Koziol
+ * April 9 2007
*
*-------------------------------------------------------------------------
*/
@@ -2371,7 +2453,7 @@ H5O_obj_create(H5F_t *f, H5O_type_t obj_type, void *crt_info, H5G_loc_t *obj_loc
/* Iterate through the object classes */
for(u = 0; u < NELMTS(H5O_obj_class_g); u++) {
/* Check for correct type of object to create */
- if(H5O_obj_class_g[u]->type == obj_type) {
+ if(H5O_obj_class_g[u]->type == obj_type) {
/* Call the object class's 'create' routine */
HDassert(H5O_obj_class_g[u]->create);
if(NULL == (ret_value = H5O_obj_class_g[u]->create(f, crt_info, obj_loc)))
@@ -2387,21 +2469,21 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_obj_create() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O_get_oh_addr
+ * Function: H5O_get_oh_addr
*
- * Purpose: Retrieve the address of the object header
+ * Purpose: Retrieve the address of the object header
*
- * Note: This routine participates in the "Inlining C struct access"
- * pattern, don't call it directly, use the appropriate macro
- * defined in H5Oprivate.h.
+ * Note: This routine participates in the "Inlining C struct access"
+ * pattern, don't call it directly, use the appropriate macro
+ * defined in H5Oprivate.h.
*
- * Return: Success: Valid haddr_t
- * Failure: HADDR_UNDEF
+ * Return: Success: Valid haddr_t
+ * Failure: HADDR_UNDEF
*
- * Programmer: Quincey Koziol
- * March 15 2007
+ * Programmer: Quincey Koziol
+ * March 15 2007
*
*-------------------------------------------------------------------------
*/
@@ -2417,17 +2499,74 @@ H5O_get_oh_addr(const H5O_t *oh)
FUNC_LEAVE_NOAPI(oh->chunk[0].addr)
} /* end H5O_get_oh_addr() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O_get_rc_and_type
+ * Function: H5O_get_oh_flags
*
- * Purpose: Retrieve an object's reference count and type
+ * Programmer: Jacob Smith
+ * 2018 August 17
*
- * Return: Success: Non-negative
- * Failure: Negative
+ *-------------------------------------------------------------------------
+ */
+uint8_t
+H5O_get_oh_flags(const H5O_t *oh)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+ HDassert(oh);
+ FUNC_LEAVE_NOAPI(oh->flags); /* flags can be 0 */
+} /* H5O_get_oh_flags() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_get_oh_mtime
+ *
+ * Purpose: Retrieve an object's modification time. Assumes that the
+ * caller has verified that accessing this variable is appropriate
+ * to the header in question.
+ *
+ * Programmer: Jacob Smith
+ * 2018 August 17
+ *
+ *-------------------------------------------------------------------------
+ */
+time_t
+H5O_get_oh_mtime(const H5O_t *oh)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+ HDassert(oh);
+ HDassert(oh->mtime);
+ FUNC_LEAVE_NOAPI(oh->mtime);
+} /* H5O_get_oh_mtime() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_get_oh_version
+ *
+ * Programmer: Jacob Smith
+ * 2018 August 17
+ *
+ *-------------------------------------------------------------------------
+ */
+uint8_t
+H5O_get_oh_version(const H5O_t *oh)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+ HDassert(oh);
+ HDassert(oh->version);
+ FUNC_LEAVE_NOAPI(oh->version);
+} /* H5O_get_oh_version() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_get_rc_and_type
+ *
+ * Purpose: Retrieve an object's reference count and type
*
- * Programmer: Quincey Koziol
- * November 4 2007
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * November 4 2007
*
*-------------------------------------------------------------------------
*/
@@ -2462,7 +2601,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_get_rc_and_type() */
-
+
/*-------------------------------------------------------------------------
* Function: H5O__free_visit_visited
*
@@ -2471,7 +2610,7 @@ done:
* Return: Non-negative on success, negative on failure
*
* Programmer: Quincey Koziol
- * Nov 25, 2007
+ * Nov 25, 2007
*
*-------------------------------------------------------------------------
*/
@@ -2485,17 +2624,17 @@ H5O__free_visit_visited(void *item, void H5_ATTR_UNUSED *key, void H5_ATTR_UNUSE
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O__free_visit_visited() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O__visit_cb
+ * Function: H5O__visit_cb
*
* Purpose: Callback function for recursively visiting objects from a group
*
- * Return: Success: Non-negative
- * Failure: Negative
+ * Return: Success: Non-negative
+ * Failure: Negative
*
- * Programmer: Quincey Koziol
- * Nov 25, 2007
+ * Programmer: Quincey Koziol
+ * Nov 25, 2007
*
*-------------------------------------------------------------------------
*/
@@ -2505,8 +2644,8 @@ H5O__visit_cb(hid_t H5_ATTR_UNUSED group, const char *name, const H5L_info_t *li
{
H5O_iter_visit_ud_t *udata = (H5O_iter_visit_ud_t *)_udata; /* User data for callback */
H5G_loc_t obj_loc; /* Location of object */
- H5G_name_t obj_path; /* Object's group hier. path */
- H5O_loc_t obj_oloc; /* Object's object location */
+ H5G_name_t obj_path; /* Object's group hier. path */
+ H5O_loc_t obj_oloc; /* Object's object location */
hbool_t obj_found = FALSE; /* Object at 'name' found */
herr_t ret_value = H5_ITER_CONT; /* Return value */
@@ -2577,7 +2716,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O__visit_cb() */
-
+
/*-------------------------------------------------------------------------
* Function: H5O__visit
*
@@ -2607,7 +2746,7 @@ done:
* library, or the negative value returned by one
* of the operators.
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* November 24 2007
*
*-------------------------------------------------------------------------
@@ -2622,6 +2761,8 @@ H5O__visit(H5G_loc_t *loc, const char *obj_name, H5_index_t idx_type,
H5O_loc_t obj_oloc; /* Opened object object location */
hbool_t loc_found = FALSE; /* Entry at 'name' found */
H5O_info_t oinfo; /* Object info struct */
+ void *obj = NULL; /* Object */
+ H5I_type_t opened_type; /* ID type of object */
hid_t obj_id = H5I_INVALID_HID; /* ID of object */
herr_t ret_value = FAIL; /* Return value */
@@ -2649,9 +2790,13 @@ H5O__visit(H5G_loc_t *loc, const char *obj_name, H5_index_t idx_type,
/* Open the object */
/* (Takes ownership of the obj_loc information) */
- if((obj_id = H5O_open_by_loc(&obj_loc, TRUE)) < 0)
+ if(NULL == (obj = H5O_open_by_loc(&obj_loc, &opened_type)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, FAIL, "unable to open object")
+ /* Get an ID for the visited object */
+ if((obj_id = H5VL_wrap_register(opened_type, obj, TRUE)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register visited object")
+
/* Make callback for starting object */
if((ret_value = op(obj_id, ".", &oinfo, op_data)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "can't visit objects")
@@ -2662,7 +2807,8 @@ H5O__visit(H5G_loc_t *loc, const char *obj_name, H5_index_t idx_type,
/* Check for object being a group */
if(oinfo.type == H5O_TYPE_GROUP) {
- H5G_loc_t start_loc; /* Location of starting group */
+ H5G_loc_t start_loc; /* Location of starting group */
+ H5G_loc_t vis_loc; /* Location of visited group */
/* Get the location of the starting group */
if(H5G_loc(obj_id, &start_loc) < 0)
@@ -2697,12 +2843,17 @@ H5O__visit(H5G_loc_t *loc, const char *obj_name, H5_index_t idx_type,
HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't insert object node into visited list")
}
+ /* Get the location of the visited group */
+ if(H5G_loc(obj_id, &vis_loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
+
/* Call internal group visitation routine */
- if((ret_value = H5G_visit(&start_loc, ".", idx_type, order, H5O__visit_cb, &udata)) < 0)
+ if((ret_value = H5G_visit(&vis_loc, ".", idx_type, order, H5O__visit_cb, &udata)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "object visitation failed")
} /* end if */
done:
+/* XXX (VOL MERGE): Probably also want to consider closing obj here on failures */
if(obj_id != H5I_INVALID_HID) {
if(H5I_dec_app_ref(obj_id) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "unable to close object")
@@ -2716,17 +2867,17 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O__visit() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O__inc_rc
+ * Function: H5O__inc_rc
*
- * Purpose: Increments the reference count on an object header
+ * Purpose: Increments the reference count on an object header
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Jul 13 2008
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Jul 13 2008
*
*-------------------------------------------------------------------------
*/
@@ -2752,17 +2903,17 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O__inc_rc() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O__dec_rc
+ * Function: H5O__dec_rc
*
- * Purpose: Decrements the reference count on an object header
+ * Purpose: Decrements the reference count on an object header
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Jul 13 2008
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Jul 13 2008
*
*-------------------------------------------------------------------------
*/
@@ -2788,7 +2939,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O__dec_rc() */
-
+
/*-------------------------------------------------------------------------
* Function: H5O_dec_rc_by_loc
*
@@ -2831,16 +2982,16 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_dec_rc_by_loc() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O_get_proxy
+ * Function: H5O_get_proxy
*
- * Purpose: Retrieve the proxy for the object header.
+ * Purpose: Retrieve the proxy for the object header.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Quincey Koziol
- * July 24 2016
+ * Programmer: Quincey Koziol
+ * July 24 2016
*
*-------------------------------------------------------------------------
*/
@@ -2855,24 +3006,24 @@ H5O_get_proxy(const H5O_t *oh)
FUNC_LEAVE_NOAPI(oh->proxy)
} /* end H5O_get_proxy() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O__free
+ * Function: H5O__free
*
- * Purpose: Destroys an object header.
+ * Purpose: Destroys an object header.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Jan 15 2003
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Jan 15 2003
*
*-------------------------------------------------------------------------
*/
herr_t
H5O__free(H5O_t *oh)
{
- unsigned u; /* Local index variable */
+ unsigned u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
diff --git a/src/H5Olayout.c b/src/H5Olayout.c
index 5f16837..138f219 100644
--- a/src/H5Olayout.c
+++ b/src/H5Olayout.c
@@ -189,7 +189,7 @@ H5O__layout_decode(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh,
if(mesg->storage.u.compact.size > 0) {
if(NULL == (mesg->storage.u.compact.buf = H5MM_malloc(mesg->storage.u.compact.size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for compact data buffer")
- HDmemcpy(mesg->storage.u.compact.buf, p, mesg->storage.u.compact.size);
+ H5MM_memcpy(mesg->storage.u.compact.buf, p, mesg->storage.u.compact.size);
p += mesg->storage.u.compact.size;
} /* end if */
} /* end if */
@@ -210,7 +210,7 @@ H5O__layout_decode(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh,
HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, NULL, "memory allocation failed for compact data buffer")
/* Compact data */
- HDmemcpy(mesg->storage.u.compact.buf, p, mesg->storage.u.compact.size);
+ H5MM_memcpy(mesg->storage.u.compact.buf, p, mesg->storage.u.compact.size);
p += mesg->storage.u.compact.size;
} /* end if */
@@ -243,9 +243,15 @@ H5O__layout_decode(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh,
H5F_addr_decode(f, &p, &(mesg->storage.u.chunk.idx_addr));
/* Chunk dimensions */
- for(u = 0; u < mesg->u.chunk.ndims; u++)
+ for(u = 0; u < mesg->u.chunk.ndims; u++) {
UINT32DECODE(p, mesg->u.chunk.dim[u]);
+ /* Just in case that something goes very wrong, such as file corruption. */
+ if(mesg->u.chunk.dim[u] == 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, NULL, "chunk dimension must be positive: mesg->u.chunk.dim[%u] = %u",
+ u, mesg->u.chunk.dim[u])
+ } /* end for */
+
/* Compute chunk size */
for(u = 1, mesg->u.chunk.size = mesg->u.chunk.dim[0]; u < mesg->u.chunk.ndims; u++)
mesg->u.chunk.size *= mesg->u.chunk.dim[u];
@@ -419,14 +425,14 @@ H5O__layout_decode(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh,
tmp_size = HDstrlen((const char *)heap_block_p) + 1;
if(NULL == (mesg->storage.u.virt.list[i].source_file_name = (char *)H5MM_malloc(tmp_size)))
HGOTO_ERROR(H5E_OHDR, H5E_RESOURCE, NULL, "unable to allocate memory for source file name")
- (void)HDmemcpy(mesg->storage.u.virt.list[i].source_file_name, heap_block_p, tmp_size);
+ (void)H5MM_memcpy(mesg->storage.u.virt.list[i].source_file_name, heap_block_p, tmp_size);
heap_block_p += tmp_size;
/* Source dataset name */
tmp_size = HDstrlen((const char *)heap_block_p) + 1;
if(NULL == (mesg->storage.u.virt.list[i].source_dset_name = (char *)H5MM_malloc(tmp_size)))
HGOTO_ERROR(H5E_OHDR, H5E_RESOURCE, NULL, "unable to allocate memory for source dataset name")
- (void)HDmemcpy(mesg->storage.u.virt.list[i].source_dset_name, heap_block_p, tmp_size);
+ (void)H5MM_memcpy(mesg->storage.u.virt.list[i].source_dset_name, heap_block_p, tmp_size);
heap_block_p += tmp_size;
/* Source selection */
@@ -575,7 +581,7 @@ H5O__layout_encode(H5F_t *f, hbool_t H5_ATTR_UNUSED disable_shared, uint8_t *p,
/* Raw data */
if(mesg->storage.u.compact.size > 0) {
if(mesg->storage.u.compact.buf)
- HDmemcpy(p, mesg->storage.u.compact.buf, mesg->storage.u.compact.size);
+ H5MM_memcpy(p, mesg->storage.u.compact.buf, mesg->storage.u.compact.size);
else
HDmemset(p, 0, mesg->storage.u.compact.size);
p += mesg->storage.u.compact.size;
@@ -736,7 +742,7 @@ H5O__layout_copy(const void *_mesg, void *_dest)
HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, NULL, "unable to allocate memory for compact dataset")
/* Copy over the raw data */
- HDmemcpy(dest->storage.u.compact.buf, mesg->storage.u.compact.buf, dest->storage.u.compact.size);
+ H5MM_memcpy(dest->storage.u.compact.buf, mesg->storage.u.compact.buf, dest->storage.u.compact.size);
} /* end if */
else
HDassert(dest->storage.u.compact.buf == NULL);
@@ -1033,7 +1039,8 @@ H5O__layout_copy_file(H5F_t *file_src, void *mesg_src, H5F_t *file_dst,
layout_dst->storage.u.contig.size = H5S_extent_nelem(udata->src_space_extent) *
H5T_get_size(udata->src_dtype);
- if(H5D__contig_is_space_alloc(&layout_src->storage)) {
+ if(H5D__contig_is_space_alloc(&layout_src->storage)
+ || (cpy_info->shared_fo && H5D__contig_is_data_cached((const H5D_shared_t *)cpy_info->shared_fo))) {
/* copy contiguous raw data */
if(H5D__contig_copy(file_src, &layout_src->storage.u.contig, file_dst, &layout_dst->storage.u.contig, udata->src_dtype, cpy_info) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "unable to copy contiguous storage")
@@ -1042,7 +1049,8 @@ H5O__layout_copy_file(H5F_t *file_src, void *mesg_src, H5F_t *file_dst,
break;
case H5D_CHUNKED:
- if(H5D__chunk_is_space_alloc(&layout_src->storage)) {
+ if(H5D__chunk_is_space_alloc(&layout_src->storage)
+ || (cpy_info->shared_fo && H5D__chunk_is_data_cached((const H5D_shared_t *)cpy_info->shared_fo))) {
/* Create chunked layout */
if(H5D__chunk_copy(file_src, &layout_src->storage.u.chunk, &layout_src->u.chunk, file_dst, &layout_dst->storage.u.chunk, udata->src_space_extent, udata->src_dtype, udata->common.src_pline, cpy_info) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "unable to copy chunked storage")
diff --git a/src/H5Olink.c b/src/H5Olink.c
index 6447936..4bd952b 100644
--- a/src/H5Olink.c
+++ b/src/H5Olink.c
@@ -202,7 +202,7 @@ H5O__link_decode(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh,
/* Get the link's name */
if(NULL == (lnk->name = (char *)H5MM_malloc(len + 1)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- HDmemcpy(lnk->name, p, len);
+ H5MM_memcpy(lnk->name, p, len);
lnk->name[len] = '\0';
p += len;
@@ -220,7 +220,7 @@ H5O__link_decode(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh,
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "invalid link length")
if(NULL == (lnk->u.soft.name = (char *)H5MM_malloc((size_t)len + 1)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- HDmemcpy(lnk->u.soft.name, p, len);
+ H5MM_memcpy(lnk->u.soft.name, p, len);
lnk->u.soft.name[len] = '\0';
p += len;
break;
@@ -240,7 +240,7 @@ H5O__link_decode(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh,
{
if(NULL == (lnk->u.ud.udata = H5MM_malloc((size_t)len)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- HDmemcpy(lnk->u.ud.udata, p, len);
+ H5MM_memcpy(lnk->u.ud.udata, p, len);
p += len;
}
else
@@ -349,7 +349,7 @@ H5O_link_encode(H5F_t *f, hbool_t H5_ATTR_UNUSED disable_shared, uint8_t *p, con
} /* end switch */
/* Store the link's name */
- HDmemcpy(p, lnk->name, (size_t)len);
+ H5MM_memcpy(p, lnk->name, (size_t)len);
p += len;
/* Store the appropriate information for each type of link */
@@ -364,7 +364,7 @@ H5O_link_encode(H5F_t *f, hbool_t H5_ATTR_UNUSED disable_shared, uint8_t *p, con
len = (uint16_t)HDstrlen(lnk->u.soft.name);
HDassert(len > 0);
UINT16ENCODE(p, len)
- HDmemcpy(p, lnk->u.soft.name, (size_t)len);
+ H5MM_memcpy(p, lnk->u.soft.name, (size_t)len);
p += len;
break;
@@ -380,7 +380,7 @@ H5O_link_encode(H5F_t *f, hbool_t H5_ATTR_UNUSED disable_shared, uint8_t *p, con
UINT16ENCODE(p, len)
if(len > 0)
{
- HDmemcpy(p, lnk->u.ud.udata, (size_t)len);
+ H5MM_memcpy(p, lnk->u.ud.udata, (size_t)len);
p+=len;
}
break;
@@ -437,7 +437,7 @@ H5O_link_copy(const void *_mesg, void *_dest)
if(lnk->u.ud.size > 0) {
if(NULL == (dest->u.ud.udata = H5MM_malloc(lnk->u.ud.size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- HDmemcpy(dest->u.ud.udata, lnk->u.ud.udata, lnk->u.ud.size);
+ H5MM_memcpy(dest->u.ud.udata, lnk->u.ud.udata, lnk->u.ud.size);
} /* end if */
} /* end if */
@@ -612,6 +612,7 @@ herr_t
H5O_link_delete(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh, void *_mesg)
{
H5O_link_t *lnk = (H5O_link_t *)_mesg;
+ hid_t file_id = -1; /* ID for the file the link is located in (passed to user callback) */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
@@ -645,25 +646,21 @@ H5O_link_delete(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh, void *_mesg)
/* Check for delete callback */
if(link_class->del_func) {
- hid_t file_id; /* ID for the file the link is located in (passed to user callback) */
-
/* Get a file ID for the file the link is in */
- if((file_id = H5F_get_id(f, FALSE)) < 0)
+ if((file_id = H5F_get_id(f)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to get file ID")
/* Call user-defined link's 'delete' callback */
- if((link_class->del_func)(lnk->name, file_id, lnk->u.ud.udata, lnk->u.ud.size) < 0) {
- H5I_dec_ref(file_id);
+ if((link_class->del_func)(lnk->name, file_id, lnk->u.ud.udata, lnk->u.ud.size) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CALLBACK, FAIL, "link deletion callback returned failure")
- } /* end if */
-
- /* Release the file ID */
- if(H5I_dec_ref(file_id) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTCLOSEFILE, FAIL, "can't close file")
} /* end if */
} /* end if */
done:
+ /* Release the file ID */
+ if(file_id > 0 && H5I_dec_ref(file_id) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTCLOSEFILE, FAIL, "can't close file")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_link_delete() */
diff --git a/src/H5Omessage.c b/src/H5Omessage.c
index d6e3dce..18f3706 100644
--- a/src/H5Omessage.c
+++ b/src/H5Omessage.c
@@ -1598,16 +1598,23 @@ H5O_msg_is_shared(unsigned type_id, const void *mesg)
FUNC_ENTER_NOAPI_NOINIT_NOERR
/* Check args */
- HDassert(type_id < NELMTS(H5O_msg_class_g));
- type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
- HDassert(type);
- HDassert(mesg);
-
- /* If messages in a class aren't sharable, then obviously this message isn't shared! :-) */
- if(type->share_flags & H5O_SHARE_IS_SHARABLE)
- ret_value = H5O_IS_STORED_SHARED(((const H5O_shared_t *)mesg)->type);
- else
+#ifdef H5O_ENABLE_BOGUS
+ if(type_id >= NELMTS(H5O_msg_class_g))
ret_value = FALSE;
+ else
+#endif /* H5O_ENABLE_BOGUS */
+ {
+ HDassert(type_id < NELMTS(H5O_msg_class_g));
+ type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
+ HDassert(type);
+ HDassert(mesg);
+
+ /* If messages in a class aren't sharable, then obviously this message isn't shared! :-) */
+ if(type->share_flags & H5O_SHARE_IS_SHARABLE)
+ ret_value = H5O_IS_STORED_SHARED(((const H5O_shared_t *)mesg)->type);
+ else
+ ret_value = FALSE;
+ } /* end block/else */
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_msg_is_shared() */
diff --git a/src/H5Omtime.c b/src/H5Omtime.c
index 172f9ab..fbf7613 100644
--- a/src/H5Omtime.c
+++ b/src/H5Omtime.c
@@ -289,7 +289,7 @@ H5O_mtime_encode(H5F_t H5_ATTR_UNUSED *f, hbool_t H5_ATTR_UNUSED disable_shared,
/* encode */
tm = HDgmtime(mesg);
- sprintf((char*)p, "%04d%02d%02d%02d%02d%02d",
+ HDsprintf((char*)p, "%04d%02d%02d%02d%02d%02d",
1900+tm->tm_year, 1+tm->tm_mon, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
diff --git a/src/H5Oname.c b/src/H5Oname.c
index a710944..1f20f10 100644
--- a/src/H5Oname.c
+++ b/src/H5Oname.c
@@ -297,7 +297,7 @@ H5O__name_debug(H5F_t H5_ATTR_UNUSED *f, const void *_mesg, FILE *stream,
HDassert(indent >= 0);
HDassert(fwidth >= 0);
- fprintf(stream, "%*s%-*s `%s'\n", indent, "", fwidth,
+ HDfprintf(stream, "%*s%-*s `%s'\n", indent, "", fwidth,
"Name:",
mesg->s);
diff --git a/src/H5Opkg.h b/src/H5Opkg.h
index ea654d2..4afa452 100644
--- a/src/H5Opkg.h
+++ b/src/H5Opkg.h
@@ -29,7 +29,7 @@
#define H5O_NMESGS 8 /*initial number of messages */
#define H5O_NCHUNKS 2 /*initial number of chunks */
#define H5O_MIN_SIZE 22 /* Min. obj header data size (must be big enough for a message prefix and a continuation message) */
-#define H5O_MSG_TYPES 27 /* # of types of messages */
+#define H5O_MSG_TYPES 26 /* # of types of messages */
#define H5O_MAX_CRT_ORDER_IDX 65535 /* Max. creation order index value */
/* Versions of object header structure */
@@ -134,9 +134,9 @@
) : 0)) \
)
#define H5O_SIZEOF_MSGHDR_OH(O) \
- H5O_SIZEOF_MSGHDR_VERS((O)->version, (O)->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED)
+ (unsigned)H5O_SIZEOF_MSGHDR_VERS((O)->version, (O)->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED)
#define H5O_SIZEOF_MSGHDR_F(F, C) \
- H5O_SIZEOF_MSGHDR_VERS(MAX((H5F_STORE_MSG_CRT_IDX(F) ? H5O_VERSION_LATEST : H5O_VERSION_1), (uint8_t)H5O_obj_ver_bounds[H5F_LOW_BOUND(F)]), (C))
+ (unsigned)H5O_SIZEOF_MSGHDR_VERS(MAX((H5F_STORE_MSG_CRT_IDX(F) ? H5O_VERSION_LATEST : H5O_VERSION_1), (uint8_t)H5O_obj_ver_bounds[H5F_LOW_BOUND(F)]), (C))
/*
* Size of chunk "header" for each chunk
@@ -339,7 +339,7 @@ typedef struct H5O_obj_class_t {
void *(*get_copy_file_udata)(void); /*retrieve user data for 'copy file' operation */
void (*free_copy_file_udata)(void *); /*free user data for 'copy file' operation */
htri_t (*isa)(const H5O_t *); /*if a header matches an object class */
- hid_t (*open)(const H5G_loc_t *, hbool_t ); /*open an object of this class */
+ void *(*open)(const H5G_loc_t *, H5I_type_t *); /*open an object of this class */
void *(*create)(H5F_t *, void *, H5G_loc_t *); /*create an object of this class */
H5O_loc_t *(*get_oloc)(hid_t ); /*get the object header location for an object */
herr_t (*bh_info)(const H5O_loc_t *loc, H5O_t *oh, H5_ih_info_t *bh_info); /*get the index & heap info for an object */
@@ -414,7 +414,6 @@ typedef struct H5O_chk_cache_ud_t {
H5O_common_cache_ud_t common; /* Common object header cache callback info */
} H5O_chk_cache_ud_t;
-
/* Header message ID to class mapping */
H5_DLLVAR const H5O_msg_class_t *const H5O_msg_class_g[H5O_MSG_TYPES];
diff --git a/src/H5Opline.c b/src/H5Opline.c
index 1fae1b8..a956725 100644
--- a/src/H5Opline.c
+++ b/src/H5Opline.c
@@ -12,23 +12,23 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
- * Programmer: Robb Matzke <matzke@llnl.gov>
- * Wednesday, April 15, 1998
+ * Programmer: Robb Matzke <matzke@llnl.gov>
+ * Wednesday, April 15, 1998
*
- * Purpose: Data filter pipeline message.
+ * Purpose: Data filter pipeline message.
*/
#include "H5Omodule.h" /* This source code file is part of the H5O module */
-#define H5Z_FRIEND /*suppress error about including H5Zpkg */
+#define H5Z_FRIEND /*suppress error about including H5Zpkg */
-#include "H5private.h" /* Generic Functions */
-#include "H5Dprivate.h" /* Datasets */
-#include "H5Eprivate.h" /* Error handling */
-#include "H5FLprivate.h" /* Free Lists */
-#include "H5MMprivate.h" /* Memory management */
-#include "H5Opkg.h" /* Object headers */
-#include "H5Zpkg.h" /* Data filters */
+#include "H5private.h" /* Generic Functions */
+#include "H5Dprivate.h" /* Datasets */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5FLprivate.h" /* Free Lists */
+#include "H5MMprivate.h" /* Memory management */
+#include "H5Opkg.h" /* Object headers */
+#include "H5Zpkg.h" /* Data filters */
/* PRIVATE PROTOTYPES */
@@ -45,70 +45,72 @@ static herr_t H5O__pline_debug(H5F_t *f, const void *_mesg, FILE * stream,
int indent, int fwidth);
/* Set up & include shared message "interface" info */
-#define H5O_SHARED_TYPE H5O_MSG_PLINE
-#define H5O_SHARED_DECODE H5O_pline_shared_decode
-#define H5O_SHARED_DECODE_REAL H5O__pline_decode
-#define H5O_SHARED_ENCODE H5O_pline_shared_encode
-#define H5O_SHARED_ENCODE_REAL H5O_pline_encode
-#define H5O_SHARED_SIZE H5O_pline_shared_size
-#define H5O_SHARED_SIZE_REAL H5O_pline_size
-#define H5O_SHARED_DELETE H5O__pline_shared_delete
+#define H5O_SHARED_TYPE H5O_MSG_PLINE
+#define H5O_SHARED_DECODE H5O_pline_shared_decode
+#define H5O_SHARED_DECODE_REAL H5O__pline_decode
+#define H5O_SHARED_ENCODE H5O_pline_shared_encode
+#define H5O_SHARED_ENCODE_REAL H5O_pline_encode
+#define H5O_SHARED_SIZE H5O_pline_shared_size
+#define H5O_SHARED_SIZE_REAL H5O_pline_size
+#define H5O_SHARED_DELETE H5O__pline_shared_delete
#undef H5O_SHARED_DELETE_REAL
-#define H5O_SHARED_LINK H5O__pline_shared_link
+#define H5O_SHARED_LINK H5O__pline_shared_link
#undef H5O_SHARED_LINK_REAL
-#define H5O_SHARED_COPY_FILE H5O__pline_shared_copy_file
+#define H5O_SHARED_COPY_FILE H5O__pline_shared_copy_file
#undef H5O_SHARED_COPY_FILE_REAL
-#define H5O_SHARED_POST_COPY_FILE H5O_pline_shared_post_copy_file
+#define H5O_SHARED_POST_COPY_FILE H5O_pline_shared_post_copy_file
#undef H5O_SHARED_POST_COPY_FILE_REAL
#undef H5O_SHARED_POST_COPY_FILE_UPD
-#define H5O_SHARED_DEBUG H5O_pline_shared_debug
-#define H5O_SHARED_DEBUG_REAL H5O__pline_debug
-#include "H5Oshared.h" /* Shared Object Header Message Callbacks */
+#define H5O_SHARED_DEBUG H5O_pline_shared_debug
+#define H5O_SHARED_DEBUG_REAL H5O__pline_debug
+#include "H5Oshared.h" /* Shared Object Header Message Callbacks */
/* This message derives from H5O message class */
const H5O_msg_class_t H5O_MSG_PLINE[1] = {{
- H5O_PLINE_ID, /* message id number */
- "filter pipeline", /* message name for debugging */
- sizeof(H5O_pline_t), /* native message size */
- H5O_SHARE_IS_SHARABLE|H5O_SHARE_IN_OHDR, /* messages are sharable? */
- H5O_pline_shared_decode, /* decode message */
- H5O_pline_shared_encode, /* encode message */
- H5O_pline_copy, /* copy the native value */
- H5O_pline_shared_size, /* size of raw message */
- H5O__pline_reset, /* reset method */
- H5O__pline_free, /* free method */
- H5O__pline_shared_delete, /* file delete method */
- H5O__pline_shared_link, /* link method */
- NULL, /* set share method */
- NULL, /*can share method */
- H5O_pline_pre_copy_file, /* pre copy native value to file */
- H5O__pline_shared_copy_file, /* copy native value to file */
- H5O_pline_shared_post_copy_file, /* post copy native value to file */
- NULL, /* get creation index */
- NULL, /* set creation index */
- H5O_pline_shared_debug /* debug the message */
+ H5O_PLINE_ID, /* message id number */
+ "filter pipeline", /* message name for debugging */
+ sizeof(H5O_pline_t), /* native message size */
+ H5O_SHARE_IS_SHARABLE|H5O_SHARE_IN_OHDR, /* messages are sharable? */
+ H5O_pline_shared_decode, /* decode message */
+ H5O_pline_shared_encode, /* encode message */
+ H5O_pline_copy, /* copy the native value */
+ H5O_pline_shared_size, /* size of raw message */
+ H5O__pline_reset, /* reset method */
+ H5O__pline_free, /* free method */
+ H5O__pline_shared_delete, /* file delete method */
+ H5O__pline_shared_link, /* link method */
+ NULL, /* set share method */
+ NULL, /*can share method */
+ H5O_pline_pre_copy_file, /* pre copy native value to file */
+ H5O__pline_shared_copy_file, /* copy native value to file */
+ H5O_pline_shared_post_copy_file, /* post copy native value to file */
+ NULL, /* get creation index */
+ NULL, /* set creation index */
+ H5O_pline_shared_debug /* debug the message */
}};
/* Format version bounds for filter pipleline */
const unsigned H5O_pline_ver_bounds[] = {
H5O_PLINE_VERSION_1, /* H5F_LIBVER_EARLIEST */
H5O_PLINE_VERSION_2, /* H5F_LIBVER_V18 */
+ H5O_PLINE_VERSION_2, /* H5F_LIBVER_V110 */
+ H5O_PLINE_VERSION_2, /* H5F_LIBVER_V112 */
H5O_PLINE_VERSION_LATEST /* H5F_LIBVER_LATEST */
};
/* Declare a free list to manage the H5O_pline_t struct */
H5FL_DEFINE(H5O_pline_t);
-
+
/*-------------------------------------------------------------------------
- * Function: H5O__pline_decode
+ * Function: H5O__pline_decode
*
- * Purpose: Decodes a filter pipeline message.
+ * Purpose: Decodes a filter pipeline message.
*
- * Return: Success: Ptr to the native message.
- * Failure: NULL
+ * Return: Success: Ptr to the native message.
+ * Failure: NULL
*
- * Programmer: Robb Matzke
+ * Programmer: Robb Matzke
* Wednesday, April 15, 1998
*
*-------------------------------------------------------------------------
@@ -118,12 +120,12 @@ H5O__pline_decode(H5F_t H5_ATTR_UNUSED *f, H5O_t H5_ATTR_UNUSED *open_oh,
unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags,
size_t p_size, const uint8_t *p)
{
- H5O_pline_t *pline = NULL; /* Pipeline message */
+ H5O_pline_t *pline = NULL; /* Pipeline message */
H5Z_filter_info_t *filter; /* Filter to decode */
- size_t name_length; /* Length of filter name */
- size_t i; /* Local index variable */
+ size_t name_length; /* Length of filter name */
+ size_t i; /* Local index variable */
const uint8_t *p_end = p + p_size - 1; /* End of the p buffer */
- void *ret_value = NULL; /* Return value */
+ void *ret_value = NULL; /* Return value */
FUNC_ENTER_STATIC
@@ -203,7 +205,7 @@ H5O__pline_decode(H5F_t H5_ATTR_UNUSED *f, H5O_t H5_ATTR_UNUSED *open_oh,
/* Filter parameters */
if(filter->cd_nelmts) {
- size_t j; /* Local index variable */
+ size_t j; /* Local index variable */
/* Allocate space for the client data elements, or use the internal buffer */
if(filter->cd_nelmts > H5Z_COMMON_CD_VALUES) {
@@ -242,15 +244,15 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O__pline_decode() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O_pline_encode
+ * Function: H5O_pline_encode
*
- * Purpose: Encodes message MESG into buffer P.
+ * Purpose: Encodes message MESG into buffer P.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Robb Matzke
+ * Programmer: Robb Matzke
* Wednesday, April 15, 1998
*
*-------------------------------------------------------------------------
@@ -258,9 +260,9 @@ done:
static herr_t
H5O_pline_encode(H5F_t H5_ATTR_UNUSED *f, uint8_t *p/*out*/, const void *mesg)
{
- const H5O_pline_t *pline = (const H5O_pline_t*)mesg; /* Pipeline message to encode */
+ const H5O_pline_t *pline = (const H5O_pline_t*)mesg; /* Pipeline message to encode */
const H5Z_filter_info_t *filter; /* Filter to encode */
- size_t i, j; /* Local index variables */
+ size_t i, j; /* Local index variables */
FUNC_ENTER_NOAPI_NOINIT_NOERR
@@ -272,21 +274,21 @@ H5O_pline_encode(H5F_t H5_ATTR_UNUSED *f, uint8_t *p/*out*/, const void *mesg)
*p++ = (uint8_t)pline->version;
*p++ = (uint8_t)(pline->nused);
if(pline->version == H5O_PLINE_VERSION_1) {
- *p++ = 0; /*reserved 1*/
- *p++ = 0; /*reserved 2*/
- *p++ = 0; /*reserved 3*/
- *p++ = 0; /*reserved 4*/
- *p++ = 0; /*reserved 5*/
- *p++ = 0; /*reserved 6*/
+ *p++ = 0; /*reserved 1*/
+ *p++ = 0; /*reserved 2*/
+ *p++ = 0; /*reserved 3*/
+ *p++ = 0; /*reserved 4*/
+ *p++ = 0; /*reserved 5*/
+ *p++ = 0; /*reserved 6*/
} /* end if */
/* Encode filters */
for(i = 0, filter = &pline->filter[0]; i < pline->nused; i++, filter++) {
- const char *name; /* Filter name */
- size_t name_length; /* Length of filter name */
+ const char *name; /* Filter name */
+ size_t name_length; /* Length of filter name */
/* Filter ID */
- UINT16ENCODE(p, filter->id);
+ UINT16ENCODE(p, filter->id);
/* Skip writing the name length & name if the filter is an internal filter */
if(pline->version > H5O_PLINE_VERSION_1 && filter->id < H5Z_FILTER_RESERVED) {
@@ -294,7 +296,7 @@ H5O_pline_encode(H5F_t H5_ATTR_UNUSED *f, uint8_t *p/*out*/, const void *mesg)
name = NULL;
} /* end if */
else {
- H5Z_class2_t *cls; /* Filter class */
+ H5Z_class2_t *cls; /* Filter class */
/*
* Get the filter name. If the pipeline message has a name in it then
@@ -310,26 +312,26 @@ H5O_pline_encode(H5F_t H5_ATTR_UNUSED *f, uint8_t *p/*out*/, const void *mesg)
} /* end else */
/* Filter flags */
- UINT16ENCODE(p, filter->flags);
+ UINT16ENCODE(p, filter->flags);
/* # of filter parameters */
- UINT16ENCODE(p, filter->cd_nelmts);
+ UINT16ENCODE(p, filter->cd_nelmts);
/* Encode name, if there is one to encode */
- if(name_length > 0) {
+ if(name_length > 0) {
/* Store name, with null terminator */
- HDmemcpy(p, name, name_length);
- p += name_length;
+ H5MM_memcpy(p, name, name_length);
+ p += name_length;
/* Pad out name to alignment, in older versions */
if(pline->version == H5O_PLINE_VERSION_1)
while(name_length++ % 8)
*p++ = 0;
- } /* end if */
+ } /* end if */
/* Filter parameters */
- for(j = 0; j < filter->cd_nelmts; j++)
- UINT32ENCODE(p, filter->cd_values[j]);
+ for(j = 0; j < filter->cd_nelmts; j++)
+ UINT32ENCODE(p, filter->cd_values[j]);
/* Align the parameters for older versions of the format */
if(pline->version == H5O_PLINE_VERSION_1)
@@ -340,19 +342,19 @@ H5O_pline_encode(H5F_t H5_ATTR_UNUSED *f, uint8_t *p/*out*/, const void *mesg)
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O_pline_encode() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O_pline_copy
+ * Function: H5O_pline_copy
*
- * Purpose: Copies a filter pipeline message from SRC to DST allocating
- * DST if necessary. If DST is already allocated then we assume
- * that it isn't initialized.
+ * Purpose: Copies a filter pipeline message from SRC to DST allocating
+ * DST if necessary. If DST is already allocated then we assume
+ * that it isn't initialized.
*
- * Return: Success: Ptr to DST or allocated result.
+ * Return: Success: Ptr to DST or allocated result.
*
- * Failure: NULL
+ * Failure: NULL
*
- * Programmer: Robb Matzke
+ * Programmer: Robb Matzke
* Wednesday, April 15, 1998
*
*-------------------------------------------------------------------------
@@ -360,16 +362,16 @@ H5O_pline_encode(H5F_t H5_ATTR_UNUSED *f, uint8_t *p/*out*/, const void *mesg)
static void *
H5O_pline_copy(const void *_src, void *_dst/*out*/)
{
- const H5O_pline_t *src = (const H5O_pline_t *)_src; /* Source pipeline message */
- H5O_pline_t *dst = (H5O_pline_t *)_dst; /* Destination pipeline message */
- size_t i; /* Local index variable */
- H5O_pline_t *ret_value = NULL; /* Return value */
+ const H5O_pline_t *src = (const H5O_pline_t *)_src; /* Source pipeline message */
+ H5O_pline_t *dst = (H5O_pline_t *)_dst; /* Destination pipeline message */
+ size_t i; /* Local index variable */
+ H5O_pline_t *ret_value = NULL; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
/* Allocate pipeline message, if not provided */
if(!dst && NULL == (dst = H5FL_MALLOC(H5O_pline_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* Shallow copy basic fields */
*dst = *src;
@@ -378,8 +380,8 @@ H5O_pline_copy(const void *_src, void *_dst/*out*/)
dst->nalloc = dst->nused;
if(dst->nalloc) {
/* Allocate array to hold filters */
- if(NULL == (dst->filter = (H5Z_filter_info_t *)H5MM_calloc(dst->nalloc * sizeof(dst->filter[0]))))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ if(NULL == (dst->filter = (H5Z_filter_info_t *)H5MM_calloc(dst->nalloc * sizeof(dst->filter[0]))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* Deep-copy filters */
for(i = 0; i < src->nused; i++) {
@@ -409,7 +411,7 @@ H5O_pline_copy(const void *_src, void *_dst/*out*/)
if(NULL == (dst->filter[i].cd_values = (unsigned *)H5MM_malloc(src->filter[i].cd_nelmts* sizeof(unsigned))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- HDmemcpy(dst->filter[i].cd_values, src->filter[i].cd_values,
+ H5MM_memcpy(dst->filter[i].cd_values, src->filter[i].cd_values,
src->filter[i].cd_nelmts * sizeof(unsigned));
} /* end if */
else
@@ -418,7 +420,7 @@ H5O_pline_copy(const void *_src, void *_dst/*out*/)
} /* end for */
} /* end if */
else
- dst->filter = NULL;
+ dst->filter = NULL;
/* Set return value */
ret_value = dst;
@@ -426,24 +428,24 @@ H5O_pline_copy(const void *_src, void *_dst/*out*/)
done:
if(!ret_value && dst) {
H5O__pline_reset(dst);
- if(!_dst)
+ if(!_dst)
H5O__pline_free(dst);
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_pline_copy() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O_pline_size
+ * Function: H5O_pline_size
*
- * Purpose: Determines the size of a raw filter pipeline message.
+ * Purpose: Determines the size of a raw filter pipeline message.
*
- * Return: Success: Size of message.
+ * Return: Success: Size of message.
*
- * Failure: zero
+ * Failure: zero
*
- * Programmer: Robb Matzke
+ * Programmer: Robb Matzke
* Wednesday, April 15, 1998
*
*-------------------------------------------------------------------------
@@ -451,27 +453,27 @@ done:
static size_t
H5O_pline_size(const H5F_t H5_ATTR_UNUSED *f, const void *mesg)
{
- const H5O_pline_t *pline = (const H5O_pline_t*)mesg; /* Pipeline message */
+ const H5O_pline_t *pline = (const H5O_pline_t*)mesg; /* Pipeline message */
size_t i; /* Local index variable */
size_t ret_value = 0; /* Return value */
FUNC_ENTER_NOAPI_NOINIT_NOERR
/* Message header */
- ret_value = 1 + /*version */
- 1 + /*number of filters */
- (pline->version == H5O_PLINE_VERSION_1 ? 6 : 0); /*reserved */
+ ret_value = (size_t)(1 + /*version */
+ 1 + /*number of filters */
+ (pline->version == H5O_PLINE_VERSION_1 ? 6 : 0)); /*reserved */
/* Calculate size of each filter in pipeline */
for(i = 0; i < pline->nused; i++) {
- size_t name_len; /* Length of filter name */
+ size_t name_len; /* Length of filter name */
const char *name; /* Filter name */
/* Don't write the name length & name if the filter is an internal filter */
if(pline->version > H5O_PLINE_VERSION_1 && pline->filter[i].id < H5Z_FILTER_RESERVED)
name_len = 0;
else {
- H5Z_class2_t *cls; /* Filter class */
+ H5Z_class2_t *cls; /* Filter class */
/* Get the name of the filter, same as done with H5O_pline_encode() */
if(NULL == (name = pline->filter[i].name) && (cls = H5Z_find(pline->filter[i].id)))
@@ -479,13 +481,13 @@ H5O_pline_size(const H5F_t H5_ATTR_UNUSED *f, const void *mesg)
name_len = name ? HDstrlen(name) + 1 : 0;
} /* end else */
- ret_value += 2 + /*filter identification number */
- (size_t)((pline->version == H5O_PLINE_VERSION_1 || pline->filter[i].id >= H5Z_FILTER_RESERVED) ? 2 : 0) + /*name length */
- 2 + /*flags */
- 2 + /*number of client data values */
- (pline->version == H5O_PLINE_VERSION_1 ? (size_t)H5O_ALIGN_OLD(name_len) : name_len); /*length of the filter name */
+ ret_value += 2 + /*filter identification number */
+ (size_t)((pline->version == H5O_PLINE_VERSION_1 || pline->filter[i].id >= H5Z_FILTER_RESERVED) ? 2 : 0) + /*name length */
+ 2 + /*flags */
+ 2 + /*number of client data values */
+ (pline->version == H5O_PLINE_VERSION_1 ? (size_t)H5O_ALIGN_OLD(name_len) : name_len); /*length of the filter name */
- ret_value += pline->filter[i].cd_nelmts * 4;
+ ret_value += pline->filter[i].cd_nelmts * 4;
if(pline->version == H5O_PLINE_VERSION_1)
if(pline->filter[i].cd_nelmts % 2)
ret_value += 4;
@@ -494,16 +496,16 @@ H5O_pline_size(const H5F_t H5_ATTR_UNUSED *f, const void *mesg)
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_pline_size() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O__pline_reset
+ * Function: H5O__pline_reset
*
- * Purpose: Resets a filter pipeline message by clearing all filters.
- * The MESG buffer is not freed.
+ * Purpose: Resets a filter pipeline message by clearing all filters.
+ * The MESG buffer is not freed.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Robb Matzke
+ * Programmer: Robb Matzke
* Wednesday, April 15, 1998
*
*-------------------------------------------------------------------------
@@ -511,8 +513,8 @@ H5O_pline_size(const H5F_t H5_ATTR_UNUSED *f, const void *mesg)
static herr_t
H5O__pline_reset(void *mesg)
{
- H5O_pline_t *pline = (H5O_pline_t*)mesg; /* Pipeline message */
- size_t i; /* Local index variable */
+ H5O_pline_t *pline = (H5O_pline_t*)mesg; /* Pipeline message */
+ size_t i; /* Local index variable */
FUNC_ENTER_STATIC_NOERR
@@ -550,15 +552,15 @@ H5O__pline_reset(void *mesg)
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O__pline_reset() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O__pline_free
+ * Function: H5O__pline_free
*
- * Purpose: Frees the message
+ * Purpose: Frees the message
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* Saturday, March 11, 2000
*
*-------------------------------------------------------------------------
@@ -575,7 +577,7 @@ H5O__pline_free(void *mesg)
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O__pline_free() */
-
+
/*-------------------------------------------------------------------------
* Function: H5O_pline_pre_copy_file
*
@@ -623,17 +625,17 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_pline_pre_copy_file() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5O__pline_debug
+ * Function: H5O__pline_debug
*
- * Purpose: Prints debugging information for filter pipeline message MESG
- * on output stream STREAM. Each line is indented INDENT
- * characters and the field name takes up FWIDTH characters.
+ * Purpose: Prints debugging information for filter pipeline message MESG
+ * on output stream STREAM. Each line is indented INDENT
+ * characters and the field name takes up FWIDTH characters.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Robb Matzke
+ * Programmer: Robb Matzke
* Wednesday, April 15, 1998
*
*-------------------------------------------------------------------------
@@ -642,8 +644,8 @@ static herr_t
H5O__pline_debug(H5F_t H5_ATTR_UNUSED *f, const void *mesg, FILE *stream,
int indent, int fwidth)
{
- const H5O_pline_t *pline = (const H5O_pline_t *)mesg;
- size_t i, j;
+ const H5O_pline_t *pline = (const H5O_pline_t *)mesg;
+ size_t i, j;
FUNC_ENTER_STATIC_NOERR
@@ -655,48 +657,48 @@ H5O__pline_debug(H5F_t H5_ATTR_UNUSED *f, const void *mesg, FILE *stream,
HDassert(fwidth >= 0);
HDfprintf(stream, "%*s%-*s %Zu/%Zu\n", indent, "", fwidth,
- "Number of filters:",
- pline->nused,
- pline->nalloc);
+ "Number of filters:",
+ pline->nused,
+ pline->nalloc);
/* Loop over all the filters */
for(i = 0; i < pline->nused; i++) {
- char name[32];
-
- HDsnprintf(name, sizeof(name), "Filter at position %u", (unsigned)i);
- HDfprintf(stream, "%*s%-*s\n", indent, "", fwidth, name);
- HDfprintf(stream, "%*s%-*s 0x%04x\n", indent + 3, "", MAX(0, fwidth - 3),
- "Filter identification:",
- (unsigned)(pline->filter[i].id));
- if(pline->filter[i].name)
- HDfprintf(stream, "%*s%-*s \"%s\"\n", indent + 3, "", MAX(0, fwidth - 3),
- "Filter name:",
- pline->filter[i].name);
- else
- HDfprintf(stream, "%*s%-*s NONE\n", indent + 3, "", MAX(0, fwidth - 3),
- "Filter name:");
- HDfprintf(stream, "%*s%-*s 0x%04x\n", indent + 3, "", MAX(0, fwidth - 3),
- "Flags:",
- pline->filter[i].flags);
- HDfprintf(stream, "%*s%-*s %Zu\n", indent + 3, "", MAX(0, fwidth - 3),
- "Num CD values:",
- pline->filter[i].cd_nelmts);
+ char name[32];
+
+ HDsnprintf(name, sizeof(name), "Filter at position %u", (unsigned)i);
+ HDfprintf(stream, "%*s%-*s\n", indent, "", fwidth, name);
+ HDfprintf(stream, "%*s%-*s 0x%04x\n", indent + 3, "", MAX(0, fwidth - 3),
+ "Filter identification:",
+ (unsigned)(pline->filter[i].id));
+ if(pline->filter[i].name)
+ HDfprintf(stream, "%*s%-*s \"%s\"\n", indent + 3, "", MAX(0, fwidth - 3),
+ "Filter name:",
+ pline->filter[i].name);
+ else
+ HDfprintf(stream, "%*s%-*s NONE\n", indent + 3, "", MAX(0, fwidth - 3),
+ "Filter name:");
+ HDfprintf(stream, "%*s%-*s 0x%04x\n", indent + 3, "", MAX(0, fwidth - 3),
+ "Flags:",
+ pline->filter[i].flags);
+ HDfprintf(stream, "%*s%-*s %Zu\n", indent + 3, "", MAX(0, fwidth - 3),
+ "Num CD values:",
+ pline->filter[i].cd_nelmts);
/* Filter parameters */
- for(j = 0; j < pline->filter[i].cd_nelmts; j++) {
- char field_name[32];
-
- HDsnprintf(field_name, sizeof(field_name), "CD value %lu", (unsigned long)j);
- HDfprintf(stream, "%*s%-*s %u\n", indent + 6, "", MAX(0, fwidth - 6),
- field_name,
- pline->filter[i].cd_values[j]);
- } /* end for */
+ for(j = 0; j < pline->filter[i].cd_nelmts; j++) {
+ char field_name[32];
+
+ HDsnprintf(field_name, sizeof(field_name), "CD value %lu", (unsigned long)j);
+ HDfprintf(stream, "%*s%-*s %u\n", indent + 6, "", MAX(0, fwidth - 6),
+ field_name,
+ pline->filter[i].cd_values[j]);
+ } /* end for */
} /* end for */
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O__pline_debug() */
-
+
/*-------------------------------------------------------------------------
* Function: H5O_pline_set_version
*
diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h
index 4a401b5..54e8ec8 100644
--- a/src/H5Oprivate.h
+++ b/src/H5Oprivate.h
@@ -43,6 +43,7 @@ typedef struct H5O_fill_t H5O_fill_t;
#include "H5HGprivate.h" /* Global Heaps */
#include "H5SLprivate.h" /* Skip lists */
#include "H5Tprivate.h" /* Datatype functions */
+#include "H5VLprivate.h"
#include "H5Zprivate.h" /* I/O pipeline filters */
/* Forward references of package typedefs */
@@ -120,8 +121,14 @@ typedef struct H5O_mesg_t H5O_mesg_t;
/* If the module using this macro is allowed access to the private variables, access them directly */
#ifdef H5O_MODULE
#define H5O_OH_GET_ADDR(O) ((O)->chunk[0].addr)
+#define H5O_OH_GET_VERSION(O) ((O)->version)
+#define H5O_OH_GET_FLAGS(O) ((O)->flags)
+#define H5O_OH_GET_MTIME(O) ((O)->mtime)
#else /* H5O_MODULE */
#define H5O_OH_GET_ADDR(O) (H5O_get_oh_addr(O))
+#define H5O_OH_GET_VERSION(O) (H5O_get_oh_version(O))
+#define H5O_OH_GET_FLAGS(O) (H5O_get_oh_flags(O))
+#define H5O_OH_GET_MTIME(O) (H5O_get_oh_mtime(O))
#endif /* H5O_MODULE */
/* Set the fields in a shared message structure */
@@ -220,11 +227,11 @@ typedef struct H5O_copy_t {
* Note: Must increment H5O_MSG_TYPES in H5Opkg.h and update H5O_msg_class_g
* in H5O.c when creating a new message type. Also bump the value of
* H5O_BOGUS_INVALID_ID, below, to be one greater than the value of
- * H5O_UNKNOWN_ID.
+ * H5O_UNKNOWN_ID, and re-run gen_bogus.c.
*
* (this should never exist in a file)
*/
-#define H5O_BOGUS_INVALID_ID 0x001A /* "Bogus invalid" Message. */
+#define H5O_BOGUS_INVALID_ID 0x001a /* "Bogus invalid" Message. */
/* Shared object message types.
* Shared objects can be committed, in which case the shared message contains
@@ -644,6 +651,7 @@ typedef struct H5O_layout_t {
*/
#define H5O_BOGUS_VALUE 0xdeadbeef
typedef struct H5O_bogus_t {
+ H5O_shared_t sh_loc; /* Shared message info (must be first) */
unsigned u; /* Hold the bogus info */
} H5O_bogus_t;
#endif /* H5O_ENABLE_BOGUS */
@@ -796,6 +804,17 @@ typedef uint32_t H5O_refcount_t; /* Contains # of links to object, if >1
*/
typedef unsigned H5O_unknown_t; /* Original message type ID */
+/* To indicate an invalid version for a message that does not exist yet for the release */
+/* Message version is 1 byte so the value can be 0 to 255 */
+#define H5O_INVALID_VERSION 256
+
+/* The initial version of the fsinfo message: deprecated */
+/* This version is mapped to version 1 from release 1.10.1 onwards */
+#define H5O_FSINFO_VERSION_0 0
+
+/* The latest version for fsinfo message */
+#define H5O_FSINFO_VERSION_1 1
+#define H5O_FSINFO_VERSION_LATEST H5O_FSINFO_VERSION_1
/*
* File space info Message.
* Contains file space management info and
@@ -803,6 +822,7 @@ typedef unsigned H5O_unknown_t; /* Original message type ID */
* (Data structure in memory)
*/
typedef struct H5O_fsinfo_t {
+ unsigned version; /* Version number */
H5F_fspace_strategy_t strategy; /* File space strategy */
hbool_t persist; /* Persisting free-space or not */
hsize_t threshold; /* Free-space section threshold */
@@ -850,7 +870,6 @@ typedef struct {
} u;
} H5O_mesg_operator_t;
-
/* Typedef for abstract object creation */
typedef struct {
H5O_type_t obj_type; /* Type of object to create */
@@ -865,11 +884,14 @@ struct H5P_genplist_t;
H5_DLL herr_t H5O_init(void);
H5_DLL herr_t H5O_create(H5F_t *f, size_t size_hint, size_t initial_rc,
hid_t ocpl_id, H5O_loc_t *loc/*out*/);
+H5_DLL H5O_t *H5O__create_ohdr(H5F_t *f, hid_t ocpl_id);
+H5_DLL herr_t H5O__apply_ohdr(H5F_t *f, H5O_t *oh, hid_t ocpl_id,
+ size_t size_hint, size_t initial_rc, H5O_loc_t *loc_out);
H5_DLL herr_t H5O_open(H5O_loc_t *loc);
-H5_DLL hid_t H5O_open_by_idx(const H5G_loc_t *loc, const char *name,
- H5_index_t idx_type, H5_iter_order_t order, hsize_t n);
-H5_DLL hid_t H5O_open_by_addr(const H5G_loc_t *loc, haddr_t addr);
-H5_DLL hid_t H5O_open_by_loc(const H5G_loc_t *obj_loc, hbool_t app_ref);
+H5_DLL void *H5O_open_by_idx(const H5G_loc_t *loc, const char *name,
+ H5_index_t idx_type, H5_iter_order_t order, hsize_t n, H5I_type_t *opened_type/*out*/);
+H5_DLL void *H5O_open_by_addr(const H5G_loc_t *loc, haddr_t addr, H5I_type_t *opened_type/*out*/);
+H5_DLL void *H5O_open_by_loc(const H5G_loc_t *obj_loc, H5I_type_t *opened_type/*out*/);
H5_DLL herr_t H5O_close(H5O_loc_t *loc, hbool_t *file_closed/*out*/);
H5_DLL int H5O_link(const H5O_loc_t *loc, int adjust);
H5_DLL H5O_t *H5O_protect(const H5O_loc_t *loc, unsigned prot_flags, hbool_t pin_all_chunks);
@@ -887,10 +909,13 @@ H5_DLL herr_t H5O_get_hdr_info(const H5O_loc_t *oloc, H5O_hdr_info_t *hdr);
H5_DLL herr_t H5O_get_info(const H5O_loc_t *oloc, H5O_info_t *oinfo, unsigned fields);
H5_DLL herr_t H5O_obj_type(const H5O_loc_t *loc, H5O_type_t *obj_type);
H5_DLL herr_t H5O_get_create_plist(const H5O_loc_t *loc, struct H5P_genplist_t *oc_plist);
-H5_DLL hid_t H5O_open_name(const H5G_loc_t *loc, const char *name, hbool_t app_ref);
+H5_DLL void *H5O_open_name(const H5G_loc_t *loc, const char *name, H5I_type_t *opened_type/*out*/);
H5_DLL herr_t H5O_get_nlinks(const H5O_loc_t *loc, hsize_t *nlinks);
H5_DLL void *H5O_obj_create(H5F_t *f, H5O_type_t obj_type, void *crt_info, H5G_loc_t *obj_loc);
H5_DLL haddr_t H5O_get_oh_addr(const H5O_t *oh);
+H5_DLL uint8_t H5O_get_oh_flags(const H5O_t *oh);
+H5_DLL time_t H5O_get_oh_mtime(const H5O_t *oh);
+H5_DLL uint8_t H5O_get_oh_version(const H5O_t *oh);
H5_DLL herr_t H5O_get_rc_and_type(const H5O_loc_t *oloc, unsigned *rc, H5O_type_t *otype);
H5_DLL H5AC_proxy_entry_t *H5O_get_proxy(const H5O_t *oh);
@@ -945,14 +970,19 @@ H5_DLL herr_t H5O_msg_get_flags(const H5O_loc_t *loc, unsigned type_id, uint8_t
H5_DLL herr_t H5O_flush(H5O_loc_t *oloc, hid_t obj_id);
H5_DLL herr_t H5O_flush_common(H5O_loc_t *oloc, hid_t obj_id);
H5_DLL herr_t H5O_refresh_metadata(hid_t oid, H5O_loc_t oloc);
-H5_DLL herr_t H5O_refresh_metadata_reopen(hid_t oid, H5G_loc_t *obj_loc, hbool_t start_swmr);
+H5_DLL herr_t H5O_refresh_metadata_reopen(hid_t oid, H5G_loc_t *obj_loc, H5VL_t *vol_driver, hbool_t start_swmr);
+
+/* Cache corking functions */
+H5_DLL herr_t H5O_disable_mdc_flushes(H5O_loc_t *oloc);
+H5_DLL herr_t H5O_enable_mdc_flushes(H5O_loc_t *oloc);
+H5_DLL herr_t H5O_are_mdc_flushes_disabled(H5O_loc_t *oloc, hbool_t *are_disabled);
/* Object copying routines */
H5_DLL herr_t H5O_copy_header_map(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
H5O_copy_t *cpy_info, hbool_t inc_depth,
H5O_type_t *obj_type, void **udata);
-H5_DLL herr_t H5O_copy_expand_ref(H5F_t *file_src, void *_src_ref,
- H5F_t *file_dst, void *_dst_ref, size_t ref_count, H5R_type_t ref_type,
+H5_DLL herr_t H5O_copy_expand_ref(H5F_t *file_src, hid_t tid_src, H5T_t *dt_src,
+ void *buf_src, size_t nbytes_src, H5F_t *file_dst, void *buf_dst,
H5O_copy_t *cpy_info);
H5_DLL herr_t H5O_copy(const H5G_loc_t *src_loc, const char *src_name,
H5G_loc_t *dst_loc, const char *dst_name, hid_t ocpypl_id, hid_t lcpl_id);
@@ -972,6 +1002,10 @@ H5_DLL H5O_loc_t *H5O_get_loc(hid_t id);
/* EFL operators */
H5_DLL hsize_t H5O_efl_total_size(H5O_efl_t *efl);
+/* File space info routines */
+H5_DLL herr_t H5O_fsinfo_set_version(H5F_libver_t low, H5F_libver_t high, H5O_fsinfo_t *fsinfo);
+H5_DLL herr_t H5O_fsinfo_check_version(H5F_libver_t high, H5O_fsinfo_t *fsinfo);
+
/* Fill value operators */
H5_DLL herr_t H5O_fill_reset_dyn(H5O_fill_t *fill);
H5_DLL herr_t H5O_fill_convert(H5O_fill_t *fill, H5T_t *type, hbool_t *fill_changed);
diff --git a/src/H5Opublic.h b/src/H5Opublic.h
index da2910d..234f4f0 100644
--- a/src/H5Opublic.h
+++ b/src/H5Opublic.h
@@ -94,6 +94,7 @@ typedef enum H5O_type_t {
H5O_TYPE_GROUP, /* Object is a group */
H5O_TYPE_DATASET, /* Object is a dataset */
H5O_TYPE_NAMED_DATATYPE, /* Object is a named data type */
+ H5O_TYPE_MAP, /* Object is a map */
H5O_TYPE_NTYPES /* Number of different object types (must be last!) */
} H5O_type_t;
@@ -150,18 +151,19 @@ typedef enum H5O_mcdt_search_ret_t {
/* Callback to invoke when completing the search for a matching committed datatype from the committed dtype list */
typedef H5O_mcdt_search_ret_t (*H5O_mcdt_search_cb_t)(void *op_data);
+
/********************/
/* Public Variables */
/********************/
+/*********************/
+/* Public Prototypes */
+/*********************/
#ifdef __cplusplus
extern "C" {
#endif
-/*********************/
-/* Public Prototypes */
-/*********************/
H5_DLL hid_t H5Oopen(hid_t loc_id, const char *name, hid_t lapl_id);
H5_DLL hid_t H5Oopen_by_addr(hid_t loc_id, haddr_t addr);
H5_DLL hid_t H5Oopen_by_idx(hid_t loc_id, const char *group_name,
diff --git a/src/H5Osdspace.c b/src/H5Osdspace.c
index 74fa72e..b4f00ea 100644
--- a/src/H5Osdspace.c
+++ b/src/H5Osdspace.c
@@ -189,7 +189,7 @@ H5O__sdspace_decode(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh,
done:
if(!ret_value && sdim) {
- H5S_extent_release(sdim);
+ H5S__extent_release(sdim);
sdim = H5FL_FREE(H5S_extent_t, sdim);
} /* end if */
@@ -310,7 +310,7 @@ H5O_sdspace_copy(const void *_mesg, void *_dest)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* Copy extent information */
- if(H5S_extent_copy_real(dest, mesg, TRUE) < 0)
+ if(H5S__extent_copy_real(dest, mesg, TRUE) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, NULL, "can't copy extent")
/* Set return value */
@@ -355,11 +355,11 @@ H5O_sdspace_size(const H5F_t *f, const void *_mesg)
FUNC_ENTER_NOAPI_NOINIT_NOERR
/* Basic information for all dataspace messages */
- ret_value = 1 + /* Version */
+ ret_value = (size_t)(1 + /* Version */
1 + /* Rank */
1 + /* Flags */
1 + /* Dataspace type/reserved */
- ((space->version > H5O_SDSPACE_VERSION_1) ? 0 : 4); /* Eliminated/reserved */
+ ((space->version > H5O_SDSPACE_VERSION_1) ? 0 : 4)); /* Eliminated/reserved */
/* Add in the dimension sizes */
ret_value += space->rank * H5F_SIZEOF_SIZE(f);
@@ -391,7 +391,7 @@ H5O__sdspace_reset(void *_mesg)
FUNC_ENTER_STATIC_NOERR
- H5S_extent_release(mesg);
+ H5S__extent_release(mesg);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O__sdspace_reset() */
@@ -470,7 +470,7 @@ H5O_sdspace_pre_copy_file(H5F_t H5_ATTR_UNUSED *file_src, const void *mesg_src,
HGOTO_ERROR(H5E_DATASPACE, H5E_NOSPACE, FAIL, "dataspace extent allocation failed")
/* Create a copy of the dataspace extent */
- if(H5S_extent_copy_real(udata->src_space_extent, src_space_extent, TRUE) < 0)
+ if(H5S__extent_copy_real(udata->src_space_extent, src_space_extent, TRUE) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy extent")
} /* end if */
diff --git a/src/H5Oshared.c b/src/H5Oshared.c
index 4fc0488..67ca76f 100644
--- a/src/H5Oshared.c
+++ b/src/H5Oshared.c
@@ -39,6 +39,7 @@
#include "H5Fprivate.h" /* File access */
#include "H5Gprivate.h" /* Groups */
#include "H5HFprivate.h" /* Fractal heap */
+#include "H5MMprivate.h" /* Memory management */
#include "H5Opkg.h" /* Object headers */
#include "H5SMprivate.h" /* Shared object header messages */
#include "H5WBprivate.h" /* Wrapped Buffers */
@@ -358,7 +359,7 @@ H5O__shared_decode(H5F_t *f, H5O_t *open_oh, unsigned *ioflags, const uint8_t *b
*/
if(sh_mesg.type == H5O_SHARE_TYPE_SOHM) {
HDassert(version >= H5O_SHARED_VERSION_3);
- HDmemcpy(&sh_mesg.u.heap_id, buf, sizeof(sh_mesg.u.heap_id));
+ H5MM_memcpy(&sh_mesg.u.heap_id, buf, sizeof(sh_mesg.u.heap_id));
} /* end if */
else {
/* The H5O_COMMITTED_FLAG should be set if this message
@@ -426,7 +427,7 @@ H5O__shared_encode(const H5F_t *f, uint8_t *buf/*out*/, const H5O_shared_t *sh_m
* object header that holds it.
*/
if(sh_mesg->type == H5O_SHARE_TYPE_SOHM)
- HDmemcpy(buf, &(sh_mesg->u.heap_id), sizeof(sh_mesg->u.heap_id));
+ H5MM_memcpy(buf, &(sh_mesg->u.heap_id), sizeof(sh_mesg->u.heap_id));
else
H5F_addr_encode(f, &buf, sh_mesg->u.loc.oh_addr);
diff --git a/src/H5P.c b/src/H5P.c
index 72d7ae8..09ff7f0 100644
--- a/src/H5P.c
+++ b/src/H5P.c
@@ -817,14 +817,17 @@ done:
/*--------------------------------------------------------------------------
NAME
- H5Pencode
+ H5Pencode2
PURPOSE
- Routine to convert the property values in a property list into a binary buffer
+ Routine to convert the property values in a property list into a binary buffer.
+ The encoding of property values will be done according to the file format
+ setting in fapl_id.
USAGE
- herr_t H5Pencode(plist_id, buf, nalloc)
+ herr_t H5Pencode(plist_id, buf, nalloc, fapl_id)
hid_t plist_id; IN: Identifier to property list to encode
void *buf: OUT: buffer to gold the encoded plist
size_t *nalloc; IN/OUT: size of buffer needed to encode plist
+ hid_t fapl_id; IN: File access property list ID
RETURNS
Returns non-negative on success, negative on failure.
DESCRIPTION
@@ -837,25 +840,29 @@ done:
REVISION LOG
--------------------------------------------------------------------------*/
herr_t
-H5Pencode(hid_t plist_id, void *buf, size_t *nalloc)
+H5Pencode2(hid_t plist_id, void *buf, size_t *nalloc, hid_t fapl_id)
{
H5P_genplist_t *plist; /* Property list to query */
herr_t ret_value = SUCCEED; /* return value */
FUNC_ENTER_API(FAIL)
- H5TRACE3("e", "i*x*z", plist_id, buf, nalloc);
+ H5TRACE4("e", "i*x*zi", plist_id, buf, nalloc, fapl_id);
/* Check arguments. */
if(NULL == (plist = (H5P_genplist_t *)H5I_object_verify(plist_id, H5I_GENPROP_LST)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list");
+ /* Verify access property list and set up collective metadata if appropriate */
+ if(H5CX_set_apl(&fapl_id, H5P_CLS_FACC, H5I_INVALID_HID, TRUE) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info")
+
/* Call the internal encode routine */
if((ret_value = H5P__encode(plist, TRUE, buf, nalloc)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTENCODE, FAIL, "unable to encode property list");
done:
FUNC_LEAVE_API(ret_value)
-} /* H5Pencode() */
+} /* H5Pencode2() */
/*--------------------------------------------------------------------------
diff --git a/src/H5PB.c b/src/H5PB.c
index c9b550c..bd21ab9 100644
--- a/src/H5PB.c
+++ b/src/H5PB.c
@@ -75,32 +75,28 @@ static void H5PB__deallocate_page(H5PB_entry_t *entry_ptr);
static herr_t H5PB__evict_entry(H5PB_t *pb_ptr, H5PB_entry_t *entry_ptr,
hbool_t force);
-static herr_t H5PB__flush_entry(H5F_t *f, H5PB_t *pb_ptr,
- H5PB_entry_t *entry_ptr);
+static herr_t H5PB__flush_entry(H5F_shared_t *, H5PB_t *, H5PB_entry_t *);
-static herr_t H5PB__load_page(H5F_t *f, H5PB_t *pb_ptr, haddr_t addr,
- H5FD_mem_t type, H5PB_entry_t **entry_ptr_ptr);
+static herr_t H5PB__load_page(H5F_shared_t *, H5PB_t *, haddr_t,
+ H5FD_mem_t, H5PB_entry_t **);
-static herr_t H5PB__make_space(H5F_t *f, H5PB_t *pb_ptr,
- H5FD_mem_t inserted_type);
+static herr_t H5PB__make_space(H5F_shared_t *, H5PB_t *, H5FD_mem_t);
-static herr_t H5PB__mark_entry_clean(H5PB_t *pb_ptr,
- H5PB_entry_t *entry_ptr);
+static herr_t H5PB__mark_entry_clean(H5PB_t *, H5PB_entry_t *);
-static herr_t H5PB__mark_entry_dirty(H5F_t * f, H5PB_t *pb_ptr,
- H5PB_entry_t *entry_ptr);
+static herr_t H5PB__mark_entry_dirty(H5F_shared_t *, H5PB_t *, H5PB_entry_t *);
-static herr_t H5PB__read_meta(H5F_t *f, H5FD_mem_t type, haddr_t addr,
- size_t size, void *buf/*out*/);
+static herr_t H5PB__read_meta(H5F_shared_t *, H5FD_mem_t, haddr_t,
+ size_t, void *);
-static herr_t H5PB__read_raw(H5F_t *f, H5FD_mem_t type, haddr_t addr,
- size_t size, void *buf/*out*/);
+static herr_t H5PB__read_raw(H5F_shared_t *, H5FD_mem_t, haddr_t,
+ size_t, void *);
-static herr_t H5PB__write_meta(H5F_t *f, H5FD_mem_t type, haddr_t addr,
- size_t size, const void *buf/*out*/);
+static herr_t H5PB__write_meta(H5F_shared_t *, H5FD_mem_t, haddr_t,
+ size_t, const void *);
-static herr_t H5PB__write_raw(H5F_t *f, H5FD_mem_t type, haddr_t addr,
- size_t size, const void *buf/*out*/);
+static herr_t H5PB__write_raw(H5F_shared_t *, H5FD_mem_t, haddr_t,
+ size_t, const void *);
static void ldbgf(const char *, ...) H5_ATTR_FORMAT(printf, 1, 2);
@@ -438,7 +434,7 @@ H5PB_print_stats(const H5PB_t *pb_ptr)
*-------------------------------------------------------------------------
*/
herr_t
-H5PB_add_new_page(H5F_t *f, H5FD_mem_t type, haddr_t page_addr)
+H5PB_add_new_page(H5F_shared_t *shared, H5FD_mem_t type, haddr_t page_addr)
{
hbool_t can_insert = TRUE;
H5PB_t *pb_ptr = NULL;
@@ -448,11 +444,10 @@ H5PB_add_new_page(H5F_t *f, H5FD_mem_t type, haddr_t page_addr)
FUNC_ENTER_NOAPI(FAIL)
/* Sanity checks */
- HDassert(f);
- HDassert(f->shared);
- HDassert(f->shared->pb_ptr);
+ HDassert(shared);
+ HDassert(shared->pb_ptr);
- pb_ptr = f->shared->pb_ptr;
+ pb_ptr = shared->pb_ptr;
HDassert(pb_ptr->magic == H5PB__H5PB_T_MAGIC);
@@ -509,7 +504,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5PB_create(H5F_t *f, size_t size, unsigned page_buf_min_meta_perc,
+H5PB_create(H5F_shared_t *shared, size_t size, unsigned page_buf_min_meta_perc,
unsigned page_buf_min_raw_perc)
{
hbool_t vfd_swmr_writer = FALSE;
@@ -522,30 +517,29 @@ H5PB_create(H5F_t *f, size_t size, unsigned page_buf_min_meta_perc,
FUNC_ENTER_NOAPI(FAIL)
/* Sanity checks */
- HDassert(f);
- HDassert(f->shared);
+ HDassert(shared);
HDassert(page_buf_min_meta_perc <= 100);
HDassert(page_buf_min_raw_perc <= 100);
HDassert((page_buf_min_meta_perc + page_buf_min_raw_perc) <= 100);
/* Check args */
- if ( f->shared->fs_strategy != H5F_FSPACE_STRATEGY_PAGE )
+ if ( shared->fs_strategy != H5F_FSPACE_STRATEGY_PAGE )
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, \
"Enabling Page Buffering requires PAGE file space strategy")
- else if ( size > f->shared->fs_page_size ) {
+ else if ( size > shared->fs_page_size ) {
/* round size down to the next multiple of fs_page_size */
hsize_t temp_size;
- temp_size = (size / f->shared->fs_page_size) * f->shared->fs_page_size;
+ temp_size = (size / shared->fs_page_size) * shared->fs_page_size;
H5_CHECKED_ASSIGN(size, size_t, temp_size, hsize_t);
} /* end if */
- else if ( 0 != size % f->shared->fs_page_size )
+ else if ( 0 != size % shared->fs_page_size )
HGOTO_ERROR(H5E_PAGEBUF, H5E_CANTINIT, FAIL, \
"Page Buffer size must be >= to the page size")
@@ -554,19 +548,19 @@ H5PB_create(H5F_t *f, size_t size, unsigned page_buf_min_meta_perc,
* based on the fractions provided
*/
min_md_pages = (int32_t)((size * page_buf_min_meta_perc) /
- (f->shared->fs_page_size * 100));
+ (shared->fs_page_size * 100));
min_rd_pages = (int32_t)((size * page_buf_min_raw_perc) /
- (f->shared->fs_page_size * 100));
+ (shared->fs_page_size * 100));
HDassert(min_md_pages >= 0);
HDassert(min_rd_pages >= 0);
HDassert((min_md_pages + min_rd_pages) <=
- (int32_t)(size / f->shared->fs_page_size));
+ (int32_t)(size / shared->fs_page_size));
/* compute vfd_swmr_writer */
- if ( ( H5F_VFD_SWMR_CONFIG(f) ) && ( H5F_INTENT(f) & H5F_ACC_RDWR ) ) {
+ if ( ( H5F_SHARED_VFD_SWMR_CONFIG(shared) ) && ( H5F_SHARED_INTENT(shared) & H5F_ACC_RDWR ) ) {
- HDassert(f->shared->vfd_swmr_config.writer);
+ HDassert(shared->vfd_swmr_config.writer);
vfd_swmr_writer = TRUE;
}
@@ -579,10 +573,10 @@ H5PB_create(H5F_t *f, size_t size, unsigned page_buf_min_meta_perc,
/* initialize the new instance of H5PB_t */
pb_ptr->magic = H5PB__H5PB_T_MAGIC;
- pb_ptr->page_size = f->shared->fs_page_size;
+ pb_ptr->page_size = shared->fs_page_size;
H5_CHECKED_ASSIGN(pb_ptr->page_size, size_t, \
- f->shared->fs_page_size, hsize_t);
- pb_ptr->max_pages = (int32_t)(size / f->shared->fs_page_size);
+ shared->fs_page_size, hsize_t);
+ pb_ptr->max_pages = (int32_t)(size / shared->fs_page_size);
pb_ptr->curr_pages = 0;
pb_ptr->curr_md_pages = 0;
pb_ptr->curr_rd_pages = 0;
@@ -636,7 +630,7 @@ H5PB_create(H5F_t *f, size_t size, unsigned page_buf_min_meta_perc,
H5PB_reset_stats(pb_ptr);
- f->shared->pb_ptr = pb_ptr;
+ shared->pb_ptr = pb_ptr;
/* if this is a VFD SWMR reader, inform the reader VFD that the
* page buffer is configured. Note that this is for sanity
@@ -646,13 +640,13 @@ H5PB_create(H5F_t *f, size_t size, unsigned page_buf_min_meta_perc,
* removed.
* JRM -- 1/29/19
*/
- if ( ( H5F_VFD_SWMR_CONFIG(f) ) &&
- ( 0 == (H5F_INTENT(f) & H5F_ACC_RDWR) ) ) {
+ if ( ( H5F_SHARED_VFD_SWMR_CONFIG(shared) ) &&
+ ( 0 == (H5F_SHARED_INTENT(shared) & H5F_ACC_RDWR) ) ) {
- HDassert(f->shared->lf);
- HDassert(! f->shared->vfd_swmr_config.writer);
+ HDassert(shared->lf);
+ HDassert(! shared->vfd_swmr_config.writer);
- H5FD_vfd_swmr_set_pb_configured(f->shared->lf);
+ H5FD_vfd_swmr_set_pb_configured(shared->lf);
}
done:
@@ -687,7 +681,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5PB_dest(H5F_t *f)
+H5PB_dest(H5F_shared_t *shared)
{
int i;
H5PB_t *pb_ptr = NULL;
@@ -698,13 +692,12 @@ H5PB_dest(H5F_t *f)
FUNC_ENTER_NOAPI(FAIL)
/* Sanity check */
- HDassert(f);
- HDassert(f->shared);
+ HDassert(shared);
/* flush and destroy the page buffer, if it exists */
- if ( f->shared->pb_ptr ) {
+ if ( shared->pb_ptr ) {
- pb_ptr = f->shared->pb_ptr;
+ pb_ptr = shared->pb_ptr;
HDassert(pb_ptr->magic == H5PB__H5PB_T_MAGIC);
@@ -724,7 +717,7 @@ H5PB_dest(H5F_t *f)
if ( evict_ptr->is_dirty ) {
- if ( H5PB__flush_entry(f, pb_ptr, evict_ptr) < 0 )
+ if ( H5PB__flush_entry(shared, pb_ptr, evict_ptr) < 0 )
HGOTO_ERROR(H5E_PAGEBUF, H5E_WRITEERROR, FAIL, \
"Can't flush entry")
@@ -762,7 +755,7 @@ H5PB_dest(H5F_t *f)
HDassert(pb_ptr->tl_tail_ptr == NULL);
pb_ptr->magic = 0;
- f->shared->pb_ptr = H5FL_FREE(H5PB_t, pb_ptr);
+ shared->pb_ptr = H5FL_FREE(H5PB_t, pb_ptr);
}
done:
@@ -787,7 +780,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5PB_flush(H5F_t *f)
+H5PB_flush(H5F_shared_t *shared)
{
int i;
H5PB_t *pb_ptr = NULL;
@@ -798,10 +791,9 @@ H5PB_flush(H5F_t *f)
FUNC_ENTER_NOAPI(FAIL)
/* Sanity check */
- HDassert(f);
- HDassert(f->shared);
+ HDassert(shared);
- pb_ptr = f->shared->pb_ptr;
+ pb_ptr = shared->pb_ptr;
if ( pb_ptr ) {
@@ -830,11 +822,11 @@ H5PB_flush(H5F_t *f)
" until %" PRIu64 " (now %" PRIu64 ")\n",
__func__, flush_ptr->size, flush_ptr->page,
flush_ptr->delay_write_until,
- f->shared->tick_num);
+ shared->tick_num);
continue;
}
- if ( H5PB__flush_entry(f, pb_ptr, flush_ptr) < 0 )
+ if ( H5PB__flush_entry(shared, pb_ptr, flush_ptr) < 0 )
HGOTO_ERROR(H5E_PAGEBUF, H5E_WRITEERROR, FAIL, \
"Can't flush entry")
@@ -869,7 +861,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5PB_page_exists(H5F_t *f, haddr_t addr, hbool_t *page_exists_ptr)
+H5PB_page_exists(H5F_shared_t *shared, haddr_t addr, hbool_t *page_exists_ptr)
{
uint64_t page;
H5PB_t *pb_ptr = NULL;
@@ -879,11 +871,10 @@ H5PB_page_exists(H5F_t *f, haddr_t addr, hbool_t *page_exists_ptr)
FUNC_ENTER_NOAPI(FAIL)
/* Sanity check */
- HDassert(f);
- HDassert(f->shared);
- HDassert(f->shared->pb_ptr);
+ HDassert(shared);
+ HDassert(shared->pb_ptr);
- pb_ptr = f->shared->pb_ptr;
+ pb_ptr = shared->pb_ptr;
HDassert(pb_ptr->magic == H5PB__H5PB_T_MAGIC);
HDassert(page_exists_ptr);
@@ -1053,7 +1044,7 @@ done:
* are operating in parallel mode.
*/
herr_t
-H5PB_read(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
+H5PB_read(H5F_shared_t *shared, H5FD_mem_t type, haddr_t addr, size_t size,
void *buf/*out*/)
{
H5PB_t *pb_ptr; /* Page buffer for this file */
@@ -1063,11 +1054,10 @@ H5PB_read(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
FUNC_ENTER_NOAPI(FAIL)
/* Sanity checks */
- HDassert(f);
- HDassert(f->shared);
+ HDassert(shared);
HDassert(type != H5FD_MEM_GHEAP);
- pb_ptr = f->shared->pb_ptr;
+ pb_ptr = shared->pb_ptr;
if ( pb_ptr == NULL ) {
@@ -1099,7 +1089,7 @@ H5PB_read(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
/* at present, the page buffer must be disabled in the parallel case.
* However, just in case ...
*/
- if(H5F_HAS_FEATURE(f, H5FD_FEAT_HAS_MPI)) {
+ if(H5F_SHARED_HAS_FEATURE(shared, H5FD_FEAT_HAS_MPI)) {
bypass_pb = TRUE;
@@ -1108,7 +1098,7 @@ H5PB_read(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
if ( bypass_pb ) { /* cases 1, 2. and 5 */
- if ( H5FD_read(f->shared->lf, type, addr, size, buf) < 0 )
+ if ( H5FD_read(shared->lf, type, addr, size, buf) < 0 )
HGOTO_ERROR(H5E_PAGEBUF, H5E_READERROR, FAIL, \
"read through metadata accumulator failed")
@@ -1122,14 +1112,14 @@ H5PB_read(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
if ( H5FD_MEM_DRAW == type ) { /* cases 3 and 4 */
- if ( H5PB__read_raw(f, type, addr, size, buf) < 0 )
+ if ( H5PB__read_raw(shared, type, addr, size, buf) < 0 )
HGOTO_ERROR(H5E_PAGEBUF, H5E_READERROR, FAIL, \
"H5PB_read_raw() failed")
} else { /* cases 6, 7, 8, 9, and 10 */
- if ( H5PB__read_meta(f, type, addr, size, buf) < 0 )
+ if ( H5PB__read_meta(shared, type, addr, size, buf) < 0 )
HGOTO_ERROR(H5E_PAGEBUF, H5E_READERROR, FAIL, \
"H5PB_read_meta() failed")
@@ -1187,7 +1177,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5PB_remove_entry(const H5F_t *f, haddr_t addr)
+H5PB_remove_entry(const H5F_shared_t *shared, haddr_t addr)
{
uint64_t page;
H5PB_t *pb_ptr = NULL;
@@ -1197,11 +1187,10 @@ H5PB_remove_entry(const H5F_t *f, haddr_t addr)
FUNC_ENTER_NOAPI(FAIL)
/* Sanity checks */
- HDassert(f);
- HDassert(f->shared);
- HDassert(f->shared->pb_ptr);
+ HDassert(shared);
+ HDassert(shared->pb_ptr);
- pb_ptr = f->shared->pb_ptr;
+ pb_ptr = shared->pb_ptr;
/* Calculate the page offset */
page = (addr / pb_ptr->page_size);
@@ -1395,7 +1384,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5PB_vfd_swmr__release_delayed_writes(H5F_t * f)
+H5PB_vfd_swmr__release_delayed_writes(H5F_shared_t *shared)
{
H5PB_t * pb_ptr = NULL;
H5PB_entry_t *entry_ptr = NULL;
@@ -1404,19 +1393,18 @@ H5PB_vfd_swmr__release_delayed_writes(H5F_t * f)
FUNC_ENTER_NOAPI(FAIL)
/* Sanity checks */
- HDassert(f);
- HDassert(f->shared);
- HDassert(f->shared->vfd_swmr);
- HDassert(f->shared->vfd_swmr_writer);
+ HDassert(shared);
+ HDassert(shared->vfd_swmr);
+ HDassert(shared->vfd_swmr_writer);
- pb_ptr = f->shared->pb_ptr;
+ pb_ptr = shared->pb_ptr;
HDassert(pb_ptr);
HDassert(pb_ptr->magic == H5PB__H5PB_T_MAGIC);
HDassert(pb_ptr->vfd_swmr_writer);
while (pb_ptr->dwl_tail_ptr &&
- pb_ptr->dwl_tail_ptr->delay_write_until <= f->shared->tick_num) {
+ pb_ptr->dwl_tail_ptr->delay_write_until <= shared->tick_num) {
entry_ptr = pb_ptr->dwl_tail_ptr;
@@ -1428,7 +1416,7 @@ H5PB_vfd_swmr__release_delayed_writes(H5F_t * f)
if ( entry_ptr->is_mpmde ) { /* flush and evict now */
- if ( H5PB__flush_entry(f, pb_ptr, entry_ptr) < 0 )
+ if ( H5PB__flush_entry(shared, pb_ptr, entry_ptr) < 0 )
HGOTO_ERROR(H5E_PAGEBUF, H5E_WRITEERROR, FAIL, \
"flush of mpmde failed")
@@ -1472,7 +1460,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5PB_vfd_swmr__release_tick_list(H5F_t * f)
+H5PB_vfd_swmr__release_tick_list(H5F_shared_t *shared)
{
H5PB_t * pb_ptr = NULL;
H5PB_entry_t *entry_ptr = NULL;
@@ -1481,12 +1469,11 @@ H5PB_vfd_swmr__release_tick_list(H5F_t * f)
FUNC_ENTER_NOAPI(FAIL)
/* Sanity checks */
- HDassert(f);
- HDassert(f->shared);
- HDassert(f->shared->vfd_swmr);
- HDassert(f->shared->vfd_swmr_writer);
+ HDassert(shared);
+ HDassert(shared->vfd_swmr);
+ HDassert(shared->vfd_swmr_writer);
- pb_ptr = f->shared->pb_ptr;
+ pb_ptr = shared->pb_ptr;
HDassert(pb_ptr);
HDassert(pb_ptr->magic == H5PB__H5PB_T_MAGIC);
@@ -1508,7 +1495,7 @@ H5PB_vfd_swmr__release_tick_list(H5F_t * f)
if ( entry_ptr->delay_write_until == 0 ) {
/* flush and evict the multi-page metadata entry immediately */
- if ( H5PB__flush_entry(f, pb_ptr, entry_ptr) < 0 )
+ if ( H5PB__flush_entry(shared, pb_ptr, entry_ptr) < 0 )
HGOTO_ERROR(H5E_PAGEBUF, H5E_WRITEERROR, FAIL, \
"flush of mpmde failed")
@@ -1556,7 +1543,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5PB_vfd_swmr__set_tick(H5F_t * f)
+H5PB_vfd_swmr__set_tick(H5F_shared_t *shared)
{
H5PB_t * pb_ptr = NULL;
herr_t ret_value = SUCCEED; /* Return value */
@@ -1564,24 +1551,23 @@ H5PB_vfd_swmr__set_tick(H5F_t * f)
FUNC_ENTER_NOAPI(FAIL)
/* Sanity checks */
- HDassert(f);
- HDassert(f->shared);
- HDassert(f->shared->vfd_swmr);
- HDassert(f->shared->vfd_swmr_writer);
+ HDassert(shared);
+ HDassert(shared->vfd_swmr);
+ HDassert(shared->vfd_swmr_writer);
- pb_ptr = f->shared->pb_ptr;
+ pb_ptr = shared->pb_ptr;
HDassert(pb_ptr);
HDassert(pb_ptr->magic == H5PB__H5PB_T_MAGIC);
HDassert(pb_ptr->vfd_swmr_writer);
/* the tick must always increase by 1 -- verify this */
- if ( f->shared->tick_num != pb_ptr->cur_tick + 1 )
+ if ( shared->tick_num != pb_ptr->cur_tick + 1 )
HGOTO_ERROR(H5E_PAGEBUF, H5E_SYSTEM, FAIL, \
- "f->shared->tick_num != pb_ptr->cur_tick + 1 ?!?!")
+ "shared->tick_num != pb_ptr->cur_tick + 1 ?!?!")
- pb_ptr->cur_tick = f->shared->tick_num;
+ pb_ptr->cur_tick = shared->tick_num;
done:
@@ -1610,35 +1596,35 @@ done:
* This function is called to accomplish this. Its cycle of
* operation is as follows:
*
- * 1) Scan the tick list. For each entry (*pbe_ptr), test
+ * 1) Scan the tick list. For each entry (*entry), test
* to see if it appears in the index.
*
* If it does the entry must have been modified in the
* past tick. Update the index entry (*ie_ptr) as follows:
*
- * a) Set ie_ptr->entry_ptr = pbe_ptr->image_ptr. This
+ * a) Set ie_ptr->entry_ptr = entry->image_ptr. This
* is needed to give the metadata file update code
* access to the image of the target page or multi-page
* multi-date entry. Note that ie_ptr->entry_ptr will
* be set to NULL as soon as the metadata file is updated,
- * so the buffer pointed to by pbe_ptr->image_ptr can
+ * so the buffer pointed to by entry->image_ptr can
* be safely discarded at any time after the metadata
* file update.
*
* b) Set ie_ptr->tick_of_last_change to the current tick.
*
- * c) If pbe_ptr->is_dirty, set ie_ptr->clean to FALSE.
- * If pbe_ptr->is_dirty is FALSE, set ie_ptr->clean
+ * c) If entry->is_dirty, set ie_ptr->clean to FALSE.
+ * If entry->is_dirty is FALSE, set ie_ptr->clean
* to TRUE and set ie_ptr->tick_of_last_flush to the
* current tick.
*
- * If the tick list entry (*pbe_ptr) doesn't appear in
+ * If the tick list entry (*entry) doesn't appear in
* the index, allocate a metadata file index entry (*ie_ptr),
* and initialize it as follows:
*
- * ie_ptr->hdf5_page_offset = pbe_ptr->page
- * ie_ptr->length = pbe_ptr->size
- * ie_ptr->delayed_flush = pbe_ptr->delay_write_until
+ * ie_ptr->hdf5_page_offset = entry->page
+ * ie_ptr->length = entry->size
+ * ie_ptr->delayed_flush = entry->delay_write_until
*
* and then update the new entry as per the existing entry
* case described above.
@@ -1677,7 +1663,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5PB_vfd_swmr__update_index(H5F_t * f,
+H5PB_vfd_swmr__update_index(H5F_shared_t *shared,
uint32_t * idx_ent_added_ptr,
uint32_t * idx_ent_modified_ptr,
uint32_t * idx_ent_not_in_tl_ptr,
@@ -1689,7 +1675,7 @@ H5PB_vfd_swmr__update_index(H5F_t * f,
uint32_t idx_ent_not_in_tl = 0;
uint32_t idx_ent_not_in_tl_flushed = 0;
H5PB_t * pb_ptr = NULL;
- H5PB_entry_t *pbe_ptr = NULL;
+ H5PB_entry_t *entry;
H5FD_vfd_swmr_idx_entry_t * ie_ptr = NULL;
H5FD_vfd_swmr_idx_entry_t * idx = NULL;
herr_t ret_value = SUCCEED; /* Return value */
@@ -1697,16 +1683,15 @@ H5PB_vfd_swmr__update_index(H5F_t * f,
FUNC_ENTER_NOAPI(FAIL)
/* Sanity checks */
- HDassert(f);
- HDassert(f->shared);
- HDassert(f->shared->vfd_swmr);
- HDassert(f->shared->vfd_swmr_writer);
+ HDassert(shared);
+ HDassert(shared->vfd_swmr);
+ HDassert(shared->vfd_swmr_writer);
- idx = f->shared->mdf_idx;
+ idx = shared->mdf_idx;
HDassert(idx);
- pb_ptr = f->shared->pb_ptr;
+ pb_ptr = shared->pb_ptr;
HDassert(pb_ptr);
HDassert(pb_ptr->magic == H5PB__H5PB_T_MAGIC);
@@ -1721,44 +1706,19 @@ H5PB_vfd_swmr__update_index(H5F_t * f,
* as appropriate.
*/
- pbe_ptr = pb_ptr->tl_head_ptr;
-
- while ( pbe_ptr ) {
-
- uint64_t target_page;
- int32_t top;
- int32_t bottom;
- int32_t probe;
+ for (entry = pb_ptr->tl_head_ptr;
+ entry != NULL;
+ entry = entry->tl_next) {
+ uint64_t target_page = entry->page;
- HDassert(pbe_ptr->magic == H5PB__H5PB_ENTRY_T_MAGIC);
+ HDassert(entry->magic == H5PB__H5PB_ENTRY_T_MAGIC);
/* do a binary search on the metadata file index to see if
- * it already contains an entry for *pbe_ptr.
+ * it already contains an entry for *entry.
*/
- ie_ptr = NULL;
- top = f->shared->mdf_idx_entries_used - 1;
- bottom = 0;
- target_page = pbe_ptr->page;
-
- while ( top >= bottom ) {
-
- probe = (top + bottom) / 2;
-
- if ( idx[probe].hdf5_page_offset < target_page ) {
-
- bottom = probe + 1;
-
- } else if ( idx[probe].hdf5_page_offset > target_page ) {
-
- top = probe - 1;
-
- } else { /* found it */
-
- ie_ptr = idx + probe;
- bottom = top + 1; /* to exit loop */
- }
- }
+ ie_ptr = vfd_swmr_pageno_to_mdf_idx_entry(idx,
+ shared->mdf_idx_entries_used, target_page);
if ( ie_ptr == NULL ) { /* alloc new entry in the metadata file index*/
@@ -1769,14 +1729,15 @@ H5PB_vfd_swmr__update_index(H5F_t * f,
*/
uint32_t new_index_entry_index;
- new_index_entry_index = f->shared->mdf_idx_entries_used +
+ new_index_entry_index = shared->mdf_idx_entries_used +
idx_ent_added++;
- if ( new_index_entry_index >= f->shared->mdf_idx_len ) {
+ if ( new_index_entry_index >= shared->mdf_idx_len ) {
- HDfprintf(stderr, "\n\nmax mdf index len (%d)exceeded.\n\n",
- f->shared->mdf_idx_len);
- HDfprintf(stderr, "tick = %lld.\n", f->shared->tick_num);
+ HDfprintf(stderr,
+ "\n\nmax mdf index len (%" PRIu32 ") exceeded.\n\n",
+ shared->mdf_idx_len);
+ HDfprintf(stderr, "tick = %" PRIu64 ".\n", shared->tick_num);
exit(1);
}
@@ -1785,13 +1746,13 @@ H5PB_vfd_swmr__update_index(H5F_t * f,
/* partial initialization of new entry -- rest done later */
ie_ptr->hdf5_page_offset = target_page;
ie_ptr->md_file_page_offset = 0; /* undefined at this point */
- ie_ptr->length = (uint32_t)(pbe_ptr->size);
+ ie_ptr->length = (uint32_t)entry->size;
ie_ptr->chksum = 0; /* undefined at this point */
/* ie_ptr->entry_ptr initialized below */
/* ie_ptr->tick_of_last_change initialized below */
/* ie_ptr->clean initialized below */
/* ie_ptr->tick_of_last_flush initialized below */
- ie_ptr->delayed_flush = pbe_ptr->delay_write_until;
+ ie_ptr->delayed_flush = entry->delay_write_until;
ie_ptr->moved_to_hdf5_file = FALSE;
} else {
@@ -1799,13 +1760,13 @@ H5PB_vfd_swmr__update_index(H5F_t * f,
idx_ent_modified++;
}
- ie_ptr->entry_ptr = pbe_ptr->image_ptr;
- ie_ptr->tick_of_last_change = f->shared->tick_num;
- ie_ptr->clean = !(pbe_ptr->is_dirty);
+ ie_ptr->entry_ptr = entry->image_ptr;
+ ie_ptr->tick_of_last_change = shared->tick_num;
+ ie_ptr->clean = !entry->is_dirty;
if ( ie_ptr->clean ) {
- ie_ptr->tick_of_last_flush = f->shared->tick_num;
+ ie_ptr->tick_of_last_flush = shared->tick_num;
} else {
@@ -1813,8 +1774,6 @@ H5PB_vfd_swmr__update_index(H5F_t * f,
}
HDassert(ie_ptr);
-
- pbe_ptr = pbe_ptr->tl_next;
}
/* scan the metadata file index for entries that don't appear in the
@@ -1822,37 +1781,37 @@ H5PB_vfd_swmr__update_index(H5F_t * f,
* in the page buffer, or is clean in the page buffer, mark the index
* entry clean and as having been flushed in the current tick.
*/
- for ( i = 0; i < f->shared->mdf_idx_entries_used; i++ ) {
+ for ( i = 0; i < shared->mdf_idx_entries_used; i++ ) {
HDassert( ( i == 0 ) ||
( idx[i - 1].hdf5_page_offset < idx[i].hdf5_page_offset ) );
- if ( idx[i].tick_of_last_change < f->shared->tick_num ) {
+ if ( idx[i].tick_of_last_change < shared->tick_num ) {
idx_ent_not_in_tl++;
ie_ptr = idx + i;
- if ( ! ( ie_ptr->clean ) ) {
+ if (!ie_ptr->clean) {
H5PB__SEARCH_INDEX(pb_ptr, ie_ptr->hdf5_page_offset, \
- pbe_ptr, FAIL);
+ entry, FAIL);
- if ( ( ! pbe_ptr ) || ( ! ( pbe_ptr->is_dirty ) ) ) {
+ if (entry == NULL || !entry->is_dirty) {
idx_ent_not_in_tl_flushed++;
ie_ptr->clean = TRUE;
- ie_ptr->tick_of_last_flush = f->shared->tick_num;
+ ie_ptr->tick_of_last_flush = shared->tick_num;
}
}
}
}
HDassert(idx_ent_modified + idx_ent_not_in_tl ==
- f->shared->mdf_idx_entries_used);
+ shared->mdf_idx_entries_used);
HDassert(idx_ent_modified + idx_ent_not_in_tl + idx_ent_added <=
- f->shared->mdf_idx_len);
+ shared->mdf_idx_len);
*idx_ent_added_ptr = idx_ent_added;
*idx_ent_modified_ptr = idx_ent_modified;
@@ -1944,7 +1903,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5PB_write(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
+H5PB_write(H5F_shared_t *shared, H5FD_mem_t type, haddr_t addr, size_t size,
const void *buf)
{
H5PB_t *pb_ptr; /* Page buffer for this file */
@@ -1954,11 +1913,10 @@ H5PB_write(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
FUNC_ENTER_NOAPI(FAIL)
/* Sanity checks */
- HDassert(f);
- HDassert(f->shared);
+ HDassert(shared);
HDassert(type != H5FD_MEM_GHEAP);
- pb_ptr = f->shared->pb_ptr;
+ pb_ptr = shared->pb_ptr;
if ( pb_ptr == NULL ) {
@@ -1998,7 +1956,7 @@ H5PB_write(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
/* at present, the page buffer must be disabled in the parallel case.
* However, just in case ...
*/
- if(H5F_HAS_FEATURE(f, H5FD_FEAT_HAS_MPI)) {
+ if(H5F_SHARED_HAS_FEATURE(shared, H5FD_FEAT_HAS_MPI)) {
bypass_pb = TRUE;
@@ -2007,7 +1965,7 @@ H5PB_write(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
if ( bypass_pb ) { /* cases 1, 2. 5, and 6 */
- if ( H5FD_write(f->shared->lf, type, addr, size, buf) < 0 )
+ if ( H5FD_write(shared->lf, type, addr, size, buf) < 0 )
HGOTO_ERROR(H5E_PAGEBUF, H5E_WRITEERROR, FAIL, \
"write through metadata accumulator failed")
@@ -2021,14 +1979,14 @@ H5PB_write(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
if ( H5FD_MEM_DRAW == type ) { /* cases 3 and 4 */
- if ( H5PB__write_raw(f, type, addr, size, buf) < 0 )
+ if ( H5PB__write_raw(shared, type, addr, size, buf) < 0 )
HGOTO_ERROR(H5E_PAGEBUF, H5E_WRITEERROR, FAIL, \
"H5PB_read_raw() failed")
} else { /* cases 7, and 8 */
- if ( H5PB__write_meta(f, type, addr, size, buf) < 0 )
+ if ( H5PB__write_meta(shared, type, addr, size, buf) < 0 )
HGOTO_ERROR(H5E_PAGEBUF, H5E_WRITEERROR, FAIL, \
"H5PB_read_meta() failed")
@@ -2448,7 +2406,7 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5PB__flush_entry(H5F_t *f, H5PB_t *pb_ptr, H5PB_entry_t *entry_ptr)
+H5PB__flush_entry(H5F_shared_t *shared, H5PB_t *pb_ptr, H5PB_entry_t *entry_ptr)
{
haddr_t eoa; /* Current EOA for the file */
herr_t ret_value = SUCCEED; /* Return value */
@@ -2456,9 +2414,8 @@ H5PB__flush_entry(H5F_t *f, H5PB_t *pb_ptr, H5PB_entry_t *entry_ptr)
FUNC_ENTER_NOAPI(FAIL)
/* sanity checks */
- HDassert(f);
- HDassert(f->shared);
- HDassert(f->shared->lf);
+ HDassert(shared);
+ HDassert(shared->lf);
HDassert(pb_ptr);
HDassert(pb_ptr->magic == H5PB__H5PB_T_MAGIC);
HDassert(entry_ptr);
@@ -2475,7 +2432,7 @@ H5PB__flush_entry(H5F_t *f, H5PB_t *pb_ptr, H5PB_entry_t *entry_ptr)
__func__, entry_ptr->size, entry_ptr->page, entry_ptr->addr);
/* Retrieve the 'eoa' for the file */
- if ( HADDR_UNDEF == (eoa = H5F_get_eoa(f, entry_ptr->mem_type)) )
+ if ( HADDR_UNDEF == (eoa = H5FD_get_eoa(shared->lf, entry_ptr->mem_type)) )
HGOTO_ERROR(H5E_PAGEBUF, H5E_CANTGET, FAIL, \
"driver get_eoa request failed")
@@ -2499,7 +2456,7 @@ H5PB__flush_entry(H5F_t *f, H5PB_t *pb_ptr, H5PB_entry_t *entry_ptr)
HDassert( eoa >= entry_ptr->addr + entry_ptr->size );
/* flush the entry */
- if ( H5FD_write(f->shared->lf, entry_ptr->mem_type, entry_ptr->addr,
+ if ( H5FD_write(shared->lf, entry_ptr->mem_type, entry_ptr->addr,
entry_ptr->size, entry_ptr->image_ptr) < 0 )
HGOTO_ERROR(H5E_PAGEBUF, H5E_WRITEERROR, FAIL, "file write failed")
@@ -2558,8 +2515,8 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5PB__load_page(H5F_t *f, H5PB_t *pb_ptr, haddr_t addr, H5FD_mem_t type,
- H5PB_entry_t **entry_ptr_ptr)
+H5PB__load_page(H5F_shared_t *shared, H5PB_t *pb_ptr, haddr_t addr,
+ H5FD_mem_t type, H5PB_entry_t **entry_ptr_ptr)
{
hbool_t skip_read = FALSE;
haddr_t eof = HADDR_UNDEF;
@@ -2570,9 +2527,8 @@ H5PB__load_page(H5F_t *f, H5PB_t *pb_ptr, haddr_t addr, H5FD_mem_t type,
FUNC_ENTER_NOAPI(FAIL)
/* sanity checks */
- HDassert(f);
- HDassert(f->shared);
- HDassert(f->shared->lf);
+ HDassert(shared);
+ HDassert(shared->lf);
HDassert(pb_ptr);
HDassert(pb_ptr->magic == H5PB__H5PB_T_MAGIC);
HDassert((entry_ptr_ptr == NULL) || (*entry_ptr_ptr == NULL));
@@ -2580,7 +2536,7 @@ H5PB__load_page(H5F_t *f, H5PB_t *pb_ptr, haddr_t addr, H5FD_mem_t type,
#if 0 /* JRM */
haddr_t eoa;
/* Retrieve the 'eoa' for the file */
- if ( HADDR_UNDEF == (eoa = H5F_get_eoa(f, type)))
+ if ( HADDR_UNDEF == (eoa = H5FD_get_eoa(shared->lf, type)))
HGOTO_ERROR(H5E_PAGEBUF, H5E_CANTGET, FAIL, \
"driver get_eoa request failed")
@@ -2589,7 +2545,7 @@ H5PB__load_page(H5F_t *f, H5PB_t *pb_ptr, haddr_t addr, H5FD_mem_t type,
HGOTO_ERROR(H5E_PAGEBUF, H5E_SYSTEM, FAIL, \
"Attempt to load page that extends past EOA")
#endif /* JRM */
- if ( HADDR_UNDEF == (eof = H5FD_get_eof(f->shared->lf, H5FD_MEM_DEFAULT)) )
+ if ( HADDR_UNDEF == (eof = H5FD_get_eof(shared->lf, H5FD_MEM_DEFAULT)) )
HGOTO_ERROR(H5E_PAGEBUF, H5E_CANTGET, FAIL, \
"driver get_eof request failed")
@@ -2606,7 +2562,7 @@ H5PB__load_page(H5F_t *f, H5PB_t *pb_ptr, haddr_t addr, H5FD_mem_t type,
/* make space in the page buffer if necessary */
if ( ( pb_ptr->curr_pages >= pb_ptr->max_pages ) &&
- ( H5PB__make_space(f, pb_ptr, type) < 0 ) )
+ ( H5PB__make_space(shared, pb_ptr, type) < 0 ) )
HGOTO_ERROR(H5E_PAGEBUF, H5E_SYSTEM, FAIL, \
"H5PB__make_space() reports an error")
@@ -2631,7 +2587,7 @@ H5PB__load_page(H5F_t *f, H5PB_t *pb_ptr, haddr_t addr, H5FD_mem_t type,
* image buffer associated with the new entry.
*/
if ( ( ! skip_read ) &&
- ( H5FD_read(f->shared->lf, type, addr, entry_ptr->size, image_ptr) < 0 ) )
+ ( H5FD_read(shared->lf, type, addr, entry_ptr->size, image_ptr) < 0 ) )
HGOTO_ERROR(H5E_PAGEBUF, H5E_READERROR, FAIL, \
"driver read request failed")
@@ -2738,7 +2694,7 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5PB__make_space(H5F_t *f, H5PB_t *pb_ptr, H5FD_mem_t inserted_type)
+H5PB__make_space(H5F_shared_t *shared, H5PB_t *pb_ptr, H5FD_mem_t inserted_type)
{
hbool_t inserting_md;
H5PB_entry_t *search_ptr;
@@ -2749,7 +2705,6 @@ H5PB__make_space(H5F_t *f, H5PB_t *pb_ptr, H5FD_mem_t inserted_type)
FUNC_ENTER_NOAPI(FAIL)
/* sanity checks */
- HDassert(f);
HDassert(pb_ptr);
HDassert(pb_ptr->magic == H5PB__H5PB_T_MAGIC);
HDassert(pb_ptr->min_md_pages + pb_ptr->min_rd_pages <= pb_ptr->max_pages);
@@ -2813,7 +2768,7 @@ H5PB__make_space(H5F_t *f, H5PB_t *pb_ptr, H5FD_mem_t inserted_type)
search_ptr = search_ptr->prev;
}
- if ( H5PB__flush_entry(f, pb_ptr, flush_ptr) < 0 )
+ if ( H5PB__flush_entry(shared, pb_ptr, flush_ptr) < 0 )
HGOTO_ERROR(H5E_PAGEBUF, H5E_WRITEERROR, FAIL, \
"Can't flush entry")
@@ -2924,7 +2879,7 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5PB__mark_entry_dirty(H5F_t * f, H5PB_t *pb_ptr, H5PB_entry_t *entry_ptr)
+H5PB__mark_entry_dirty(H5F_shared_t *shared, H5PB_t *pb_ptr, H5PB_entry_t *entry_ptr)
{
herr_t ret_value = SUCCEED; /* Return value */
@@ -2954,7 +2909,7 @@ H5PB__mark_entry_dirty(H5F_t * f, H5PB_t *pb_ptr, H5PB_entry_t *entry_ptr)
if ( ( pb_ptr->vfd_swmr_writer ) &&
( entry_ptr->loaded ) &&
( entry_ptr->mem_type != H5FD_MEM_DRAW ) &&
- ( H5F_vfd_swmr_writer__delay_write(f, entry_ptr->page,
+ ( H5F_vfd_swmr_writer__delay_write(shared, entry_ptr->page,
&(entry_ptr->delay_write_until)) < 0 ) )
HGOTO_ERROR(H5E_PAGEBUF, H5E_SYSTEM, FAIL, \
@@ -3128,7 +3083,7 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5PB__read_meta(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
+H5PB__read_meta(H5F_shared_t *shared, H5FD_mem_t type, haddr_t addr, size_t size,
void *buf/*out*/)
{
H5PB_t *pb_ptr; /* Page buffer for this file */
@@ -3144,17 +3099,16 @@ H5PB__read_meta(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
FUNC_ENTER_NOAPI(FAIL)
/* Sanity checks */
- HDassert(f);
- HDassert(f->shared);
- HDassert(f->shared->pb_ptr);
+ HDassert(shared);
+ HDassert(shared->pb_ptr);
- pb_ptr = f->shared->pb_ptr;
+ pb_ptr = shared->pb_ptr;
HDassert(pb_ptr->magic == H5PB__H5PB_T_MAGIC);
HDassert(pb_ptr->min_rd_pages < pb_ptr->max_pages);
- HDassert(f->shared->lf);
+ HDassert(shared->lf);
- file = f->shared->lf;
+ file = shared->lf;
HDassert(H5FD_MEM_DRAW != type);
HDassert(buf);
@@ -3196,7 +3150,7 @@ H5PB__read_meta(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
TRUE, FALSE)
if ( ( NULL == entry_ptr ) &&
- ( H5PB__load_page(f, pb_ptr, page_addr, type, &entry_ptr) < 0 ) )
+ ( H5PB__load_page(shared, pb_ptr, page_addr, type, &entry_ptr) < 0 ) )
HGOTO_ERROR(H5E_PAGEBUF, H5E_READERROR, FAIL, \
"page buffer page load request failed (1)")
@@ -3372,7 +3326,7 @@ H5PB__read_meta(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
TRUE, FALSE)
if ( ( NULL == entry_ptr ) &&
- ( H5PB__load_page(f, pb_ptr, page_addr, type, &entry_ptr) < 0))
+ ( H5PB__load_page(shared, pb_ptr, page_addr, type, &entry_ptr) < 0))
HGOTO_ERROR(H5E_PAGEBUF, H5E_READERROR, FAIL, \
"page buffer page load request failed (2)")
@@ -3445,7 +3399,7 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5PB__read_raw(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
+H5PB__read_raw(H5F_shared_t *shared, H5FD_mem_t type, haddr_t addr, size_t size,
void *buf/*out*/)
{
H5PB_t *pb_ptr; /* Page buffer for this file */
@@ -3465,11 +3419,10 @@ H5PB__read_raw(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
FUNC_ENTER_NOAPI(FAIL)
/* Sanity checks */
- HDassert(f);
- HDassert(f->shared);
- HDassert(f->shared->pb_ptr);
+ HDassert(shared);
+ HDassert(shared->pb_ptr);
- pb_ptr = f->shared->pb_ptr;
+ pb_ptr = shared->pb_ptr;
HDassert(pb_ptr->magic == H5PB__H5PB_T_MAGIC);
HDassert(pb_ptr->min_md_pages < pb_ptr->max_pages);
@@ -3497,10 +3450,9 @@ H5PB__read_raw(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
/* case 3) raw data read of page size or greater. */
if ( size >= pb_ptr->page_size ) {
- if ( H5FD_read(f->shared->lf, type, addr, size, buf) < 0)
+ if ( H5FD_read(shared->lf, type, addr, size, buf) < 0)
- HGOTO_ERROR(H5E_PAGEBUF, H5E_READERROR, FAIL, \
- "read through metadata accumulator failed")
+ HGOTO_ERROR(H5E_PAGEBUF, H5E_READERROR, FAIL, "read failed")
H5PB__UPDATE_STATS_FOR_BYPASS(pb_ptr, type, size);
@@ -3532,8 +3484,8 @@ H5PB__read_raw(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
HDassert( entry_ptr->addr == search_addr );
HDassert( entry_ptr->size == pb_ptr->page_size );
HDassert( entry_ptr->delay_write_until == 0 );
- HDassert( entry_ptr->addr <= addr + size );
- HDassert( entry_ptr->addr + entry_ptr->size <= addr + size );
+ /* This page and [addr, addr + size) should NOT be disjoint. */
+ HDassert(!(addr + size <= entry_ptr->addr || entry_ptr->addr + entry_ptr->size <= addr));
if ( entry_ptr->is_dirty ) {
@@ -3587,7 +3539,7 @@ H5PB__read_raw(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
HDassert ( addr + offset == search_addr );
HDassert ( offset + pb_ptr->page_size <= size );
- HDmemcpy(((uint8_t *)(buf) + offset),
+ HDmemcpy((uint8_t *)buf + offset,
entry_ptr->image_ptr,
pb_ptr->page_size);
}
@@ -3643,7 +3595,7 @@ H5PB__read_raw(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
FALSE, FALSE)
if ( ( NULL == entry_ptr ) &&
- ( H5PB__load_page(f, pb_ptr, first_page_addr,
+ ( H5PB__load_page(shared, pb_ptr, first_page_addr,
type, &entry_ptr) < 0 ) )
HGOTO_ERROR(H5E_PAGEBUF, H5E_READERROR, FAIL, \
@@ -3676,7 +3628,7 @@ H5PB__read_raw(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
FALSE, FALSE)
if ( ( NULL == entry_ptr ) &&
- ( H5PB__load_page(f, pb_ptr, last_page_addr,
+ ( H5PB__load_page(shared, pb_ptr, last_page_addr,
type, &entry_ptr) < 0 ) )
HGOTO_ERROR(H5E_PAGEBUF, H5E_READERROR, FAIL, \
@@ -3763,8 +3715,8 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5PB__write_meta(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
- const void *buf/*in*/)
+H5PB__write_meta(H5F_shared_t *shared, H5FD_mem_t type, haddr_t addr,
+ size_t size, const void *buf/*in*/)
{
H5PB_t *pb_ptr; /* Page buffer for this file */
H5PB_entry_t *entry_ptr; /* Pointer to page buffer entry */
@@ -3776,11 +3728,10 @@ H5PB__write_meta(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
FUNC_ENTER_NOAPI(FAIL)
/* Sanity checks */
- HDassert(f);
- HDassert(f->shared);
- HDassert(f->shared->pb_ptr);
+ HDassert(shared);
+ HDassert(shared->pb_ptr);
- pb_ptr = f->shared->pb_ptr;
+ pb_ptr = shared->pb_ptr;
HDassert(pb_ptr->magic == H5PB__H5PB_T_MAGIC);
HDassert(pb_ptr->min_rd_pages < pb_ptr->max_pages);
@@ -3859,7 +3810,7 @@ H5PB__write_meta(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
HDmemcpy((uint8_t *)(entry_ptr->image_ptr), buf, size);
/* mark the entry dirty */
- if ( H5PB__mark_entry_dirty(f, pb_ptr, entry_ptr) < 0 )
+ if ( H5PB__mark_entry_dirty(shared, pb_ptr, entry_ptr) < 0 )
HGOTO_ERROR(H5E_PAGEBUF, H5E_SYSTEM, FAIL, \
"mark entry dirty failed (1)")
@@ -3889,7 +3840,7 @@ H5PB__write_meta(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
TRUE, FALSE)
if ( ( NULL == entry_ptr ) &&
- ( H5PB__load_page(f, pb_ptr, page_addr, type, &entry_ptr) < 0 ) )
+ ( H5PB__load_page(shared, pb_ptr, page_addr, type, &entry_ptr) < 0 ) )
HGOTO_ERROR(H5E_PAGEBUF, H5E_READERROR, FAIL, \
"page buffer page load request failed (1)")
@@ -3906,7 +3857,7 @@ H5PB__write_meta(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
HDmemcpy(((uint8_t *)(entry_ptr->image_ptr) + offset),
(const uint8_t *)buf, size);
- if ( H5PB__mark_entry_dirty(f, pb_ptr, entry_ptr) < 0 )
+ if ( H5PB__mark_entry_dirty(shared, pb_ptr, entry_ptr) < 0 )
HGOTO_ERROR(H5E_PAGEBUF, H5E_SYSTEM, FAIL, \
"mark entry dirty failed (2)")
@@ -3974,7 +3925,7 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5PB__write_raw(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
+H5PB__write_raw(H5F_shared_t *shared, H5FD_mem_t type, haddr_t addr, size_t size,
const void *buf/*out*/)
{
H5PB_t *pb_ptr; /* Page buffer for this file */
@@ -3994,15 +3945,14 @@ H5PB__write_raw(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
FUNC_ENTER_NOAPI(FAIL)
/* Sanity checks */
- HDassert(f);
- HDassert(f->shared);
- HDassert(f->shared->pb_ptr);
+ HDassert(shared);
+ HDassert(shared->pb_ptr);
- pb_ptr = f->shared->pb_ptr;
+ pb_ptr = shared->pb_ptr;
HDassert(pb_ptr->magic == H5PB__H5PB_T_MAGIC);
HDassert(pb_ptr->min_md_pages < pb_ptr->max_pages);
- HDassert(f->shared->lf);
+ HDassert(shared->lf);
HDassert(H5FD_MEM_DRAW == type);
@@ -4026,7 +3976,7 @@ H5PB__write_raw(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
/* case 3) raw data write of page size or greater. */
if ( size >= pb_ptr->page_size ) {
- if ( H5FD_write(f->shared->lf, type, addr, size, buf) < 0 )
+ if ( H5FD_write(shared->lf, type, addr, size, buf) < 0 )
HGOTO_ERROR(H5E_PAGEBUF, H5E_WRITEERROR, FAIL, \
"write through metadata accumulator failed")
@@ -4100,7 +4050,7 @@ H5PB__write_raw(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
HDmemcpy((uint8_t *)entry_ptr->image_ptr + offset, buf,
pb_ptr->page_size - (size_t)offset);
- if ( H5PB__mark_entry_dirty(f, pb_ptr, entry_ptr) < 0 )
+ if ( H5PB__mark_entry_dirty(shared, pb_ptr, entry_ptr) < 0 )
HGOTO_ERROR(H5E_PAGEBUF, H5E_SYSTEM, FAIL, \
"mark entry dirty failed (1)")
@@ -4121,7 +4071,7 @@ H5PB__write_raw(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
(const uint8_t *)buf + offset,
(size_t)((addr + size) - last_page_addr));
- if ( H5PB__mark_entry_dirty(f, pb_ptr, entry_ptr) < 0 )
+ if ( H5PB__mark_entry_dirty(shared, pb_ptr, entry_ptr) < 0 )
HGOTO_ERROR(H5E_PAGEBUF, H5E_SYSTEM, FAIL, \
"mark entry dirty failed (2)")
@@ -4168,7 +4118,7 @@ H5PB__write_raw(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
FALSE, FALSE)
if ( ( NULL == entry_ptr ) &&
- ( H5PB__load_page(f, pb_ptr, first_page_addr,
+ ( H5PB__load_page(shared, pb_ptr, first_page_addr,
type, &entry_ptr) < 0 ) )
HGOTO_ERROR(H5E_PAGEBUF, H5E_READERROR, FAIL, \
@@ -4183,7 +4133,7 @@ H5PB__write_raw(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
HDmemcpy(((uint8_t *)(entry_ptr->image_ptr)) + offset,
(const uint8_t *)buf, length);
- if ( H5PB__mark_entry_dirty(f, pb_ptr, entry_ptr) < 0 )
+ if ( H5PB__mark_entry_dirty(shared, pb_ptr, entry_ptr) < 0 )
HGOTO_ERROR(H5E_PAGEBUF, H5E_SYSTEM, FAIL, \
"mark entry dirty failed (3)")
@@ -4204,7 +4154,7 @@ H5PB__write_raw(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
FALSE, FALSE)
if ( ( NULL == entry_ptr ) &&
- ( H5PB__load_page(f, pb_ptr, last_page_addr,
+ ( H5PB__load_page(shared, pb_ptr, last_page_addr,
type, &entry_ptr) < 0 ) )
HGOTO_ERROR(H5E_PAGEBUF, H5E_READERROR, FAIL, \
@@ -4219,7 +4169,7 @@ H5PB__write_raw(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
HDmemcpy((uint8_t *)(entry_ptr->image_ptr),
((const uint8_t *)(buf) + offset), length);
- if ( H5PB__mark_entry_dirty(f, pb_ptr, entry_ptr) < 0 )
+ if ( H5PB__mark_entry_dirty(shared, pb_ptr, entry_ptr) < 0 )
HGOTO_ERROR(H5E_PAGEBUF, H5E_SYSTEM, FAIL, \
"mark entry dirty failed (3)")
diff --git a/src/H5PBprivate.h b/src/H5PBprivate.h
index 0149a6d..e94fb7d 100644
--- a/src/H5PBprivate.h
+++ b/src/H5PBprivate.h
@@ -658,52 +658,48 @@ typedef struct H5PB_t {
/***************************************/
/* General routines */
-H5_DLL herr_t H5PB_create(H5F_t *file, size_t page_buffer_size,
+H5_DLL herr_t H5PB_create(H5F_shared_t *shared, size_t page_buffer_size,
unsigned page_buf_min_meta_perc, unsigned page_buf_min_raw_perc);
-H5_DLL herr_t H5PB_flush(H5F_t *f);
+H5_DLL herr_t H5PB_flush(H5F_shared_t *);
-H5_DLL herr_t H5PB_dest(H5F_t *f);
+H5_DLL herr_t H5PB_dest(H5F_shared_t *);
-H5_DLL herr_t H5PB_add_new_page(H5F_t *f, H5FD_mem_t type, haddr_t page_addr);
+H5_DLL herr_t H5PB_add_new_page(H5F_shared_t *, H5FD_mem_t, haddr_t);
-H5_DLL herr_t H5PB_update_entry(H5PB_t *page_buf, haddr_t addr, size_t size,
- const void *buf);
+H5_DLL herr_t H5PB_update_entry(H5PB_t *, haddr_t, size_t, const void *);
-H5_DLL herr_t H5PB_remove_entry(const H5F_t *f, haddr_t addr);
+H5_DLL herr_t H5PB_remove_entry(const H5F_shared_t *, haddr_t);
-H5_DLL herr_t H5PB_read(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
- void *buf/*out*/);
-
-H5_DLL herr_t H5PB_write(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
- const void *buf);
+H5_DLL herr_t H5PB_read(H5F_shared_t *, H5FD_mem_t, haddr_t,
+ size_t, void * /*out*/);
+H5_DLL herr_t H5PB_write(H5F_shared_t *, H5FD_mem_t, haddr_t,
+ size_t, const void *);
/* VFD SWMR specific routines */
-H5_DLL herr_t H5PB_vfd_swmr__release_delayed_writes(H5F_t * f);
+H5_DLL herr_t H5PB_vfd_swmr__release_delayed_writes(H5F_shared_t *);
-H5_DLL herr_t H5PB_vfd_swmr__release_tick_list(H5F_t * f);
+H5_DLL herr_t H5PB_vfd_swmr__release_tick_list(H5F_shared_t *);
-H5_DLL herr_t H5PB_vfd_swmr__set_tick(H5F_t * f);
+H5_DLL herr_t H5PB_vfd_swmr__set_tick(H5F_shared_t *);
-H5_DLL herr_t H5PB_vfd_swmr__update_index(H5F_t * f,
+H5_DLL herr_t H5PB_vfd_swmr__update_index(H5F_shared_t *shared,
uint32_t * idx_ent_added_ptr, uint32_t * idx_ent_modified_ptr,
uint32_t * idx_ent_not_in_tl_ptr, uint32_t * idx_ent_not_in_tl_flushed_ptr);
-
/* Statistics routines */
-H5_DLL herr_t H5PB_reset_stats(H5PB_t *page_buf);
+H5_DLL herr_t H5PB_reset_stats(H5PB_t *);
H5_DLL herr_t H5PB_get_stats(const H5PB_t *page_buf, unsigned accesses[2],
unsigned hits[2], unsigned misses[2], unsigned evictions[2],
unsigned bypasses[2]);
-H5_DLL herr_t H5PB_print_stats(const H5PB_t *page_buf);
+H5_DLL herr_t H5PB_print_stats(const H5PB_t *);
/* test & debug functions */
-H5_DLL herr_t H5PB_page_exists(H5F_t *f, haddr_t addr,
- hbool_t *page_exists_ptr);
+H5_DLL herr_t H5PB_page_exists(H5F_shared_t *, haddr_t, hbool_t *);
#endif /* !_H5PBprivate_H */
diff --git a/src/H5PLint.c b/src/H5PLint.c
index b190746..8dec14b 100644
--- a/src/H5PLint.c
+++ b/src/H5PLint.c
@@ -235,7 +235,7 @@ done:
*-------------------------------------------------------------------------
*/
const void *
-H5PL_load(H5PL_type_t type, H5PL_key_t key)
+H5PL_load(H5PL_type_t type, const H5PL_key_t *key)
{
H5PL_search_params_t search_params; /* Plugin search parameters */
hbool_t found = FALSE; /* Whether the plugin was found */
@@ -250,6 +250,10 @@ H5PL_load(H5PL_type_t type, H5PL_key_t key)
if ((H5PL_plugin_control_mask_g & H5PL_FILTER_PLUGIN) == 0)
HGOTO_ERROR(H5E_PLUGIN, H5E_CANTLOAD, NULL, "filter plugins disabled")
break;
+ case H5PL_TYPE_VOL:
+ if((H5PL_plugin_control_mask_g & H5PL_VOL_PLUGIN) == 0)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTLOAD, NULL, "Virtual Object Layer (VOL) driver plugins disabled")
+ break;
case H5PL_TYPE_ERROR:
case H5PL_TYPE_NONE:
default:
@@ -258,7 +262,7 @@ H5PL_load(H5PL_type_t type, H5PL_key_t key)
/* Set up the search parameters */
search_params.type = type;
- search_params.key.id = key.id;
+ search_params.key = key;
/* Search in the table of already loaded plugin libraries */
if(H5PL__find_plugin_in_cache(&search_params, &found, &plugin_info) < 0)
@@ -303,9 +307,11 @@ done:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
herr_t
-H5PL__open(const char *path, H5PL_type_t type, H5PL_key_t key, hbool_t *success, const void **plugin_info)
+H5PL__open(const char *path, H5PL_type_t type, const H5PL_key_t *key,
+ hbool_t *success, const void **plugin_info)
{
H5PL_HANDLE handle = NULL;
+ H5PL_get_plugin_type_t get_plugin_type = NULL;
H5PL_get_plugin_info_t get_plugin_info = NULL;
herr_t ret_value = SUCCEED;
@@ -328,12 +334,22 @@ H5PL__open(const char *path, H5PL_type_t type, H5PL_key_t key, hbool_t *success,
HGOTO_DONE(SUCCEED)
}
+ /* Return a handle for the function H5PLget_plugin_type in the dynamic library.
+ * The plugin library is supposed to define this function.
+ */
+ if (NULL == (get_plugin_type = (H5PL_get_plugin_type_t)H5PL_GET_LIB_FUNC(handle, "H5PLget_plugin_type")))
+ HGOTO_DONE(SUCCEED)
+
/* Return a handle for the function H5PLget_plugin_info in the dynamic library.
- * The plugin library is suppose to define this function.
+ * The plugin library is supposed to define this function.
*/
if (NULL == (get_plugin_info = (H5PL_get_plugin_info_t)H5PL_GET_LIB_FUNC(handle, "H5PLget_plugin_info")))
HGOTO_DONE(SUCCEED)
+ /* Check the plugin type and return if it doesn't match the one passed in */
+ if(type != (H5PL_type_t)(*get_plugin_type)())
+ HGOTO_DONE(SUCCEED)
+
/* Get the plugin information */
switch (type) {
case H5PL_TYPE_FILTER:
@@ -345,13 +361,44 @@ H5PL__open(const char *path, H5PL_type_t type, H5PL_key_t key, hbool_t *success,
HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "can't get filter info from plugin")
/* If the filter IDs match, we're done. Set the output parameters. */
- if (filter_info->id == key.id) {
+ if (filter_info->id == key->id) {
*plugin_info = (const void *)filter_info;
*success = TRUE;
}
break;
}
+
+ case H5PL_TYPE_VOL:
+ {
+ const H5VL_class_t *cls;
+
+ /* Get the plugin info */
+ if(NULL == (cls = (const H5VL_class_t *)(*get_plugin_info)()))
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "can't get VOL connector info from plugin")
+
+ /* Which kind of key are we looking for? */
+ if(key->vol.kind == H5VL_GET_CONNECTOR_BY_NAME) {
+ /* If the plugin names match, we're done. Set the output parameters. */
+ if(cls->name && !HDstrcmp(cls->name, key->vol.u.name)) {
+ *plugin_info = (const void *)cls;
+ *success = TRUE;
+ } /* end if */
+ } /* end if */
+ else {
+ /* Sanity check */
+ HDassert(key->vol.kind == H5VL_GET_CONNECTOR_BY_VALUE);
+
+ /* If the plugin values match, we're done. Set the output parameters. */
+ if(cls->value == key->vol.u.value) {
+ *plugin_info = (const void *)cls;
+ *success = TRUE;
+ } /* end if */
+ } /* end else */
+
+ break;
+ }
+
case H5PL_TYPE_ERROR:
case H5PL_TYPE_NONE:
default:
diff --git a/src/H5PLpath.c b/src/H5PLpath.c
index 972f1d0..e270c73 100644
--- a/src/H5PLpath.c
+++ b/src/H5PLpath.c
@@ -242,6 +242,7 @@ H5PL__create_path_table(void)
* environment variable or the default.
*/
char *next_path = NULL; /* A path tokenized from the paths string */
+ char *lasts = NULL; /* Context pointer for strtok_r() call */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
@@ -265,8 +266,7 @@ H5PL__create_path_table(void)
HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't allocate memory for path copy")
/* Separate the paths and store them */
- /* XXX: strtok() is not thread-safe */
- next_path = HDstrtok(paths, H5PL_PATH_SEPARATOR);
+ next_path = HDstrtok_r(paths, H5PL_PATH_SEPARATOR, &lasts);
while (next_path) {
/* Insert the path into the table */
@@ -274,7 +274,7 @@ H5PL__create_path_table(void)
HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't insert path: %s", next_path)
/* Get the next path from the environment string */
- next_path = HDstrtok(NULL, H5PL_PATH_SEPARATOR);
+ next_path = HDstrtok_r(NULL, H5PL_PATH_SEPARATOR, &lasts);
} /* end while */
done:
@@ -673,7 +673,7 @@ H5PL__find_plugin_in_path(const H5PL_search_params_t *search_params, hbool_t *fo
size_t len;
/* Allocate & initialize the path name */
- len = HDstrlen(dir) + HDstrlen(H5PL_PATH_SEPARATOR) + HDstrlen(dp->d_name) + 1 /*\0*/;
+ len = HDstrlen(dir) + HDstrlen(H5PL_PATH_SEPARATOR) + HDstrlen(dp->d_name) + 1 /*\0*/ + 4; /* Extra "+4" to quiet GCC warning - 2019/07/05, QAK */
if (NULL == (path = (char *)H5MM_calloc(len)))
HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't allocate memory for path")
diff --git a/src/H5PLpkg.h b/src/H5PLpkg.h
index dfaa4af..8c2367f 100644
--- a/src/H5PLpkg.h
+++ b/src/H5PLpkg.h
@@ -79,6 +79,7 @@
/* maximum size for expanding env vars */
# define H5PL_EXPAND_BUFFER_SIZE 32767
+ typedef H5PL_type_t(__cdecl *H5PL_get_plugin_type_t)(void);
typedef const void *(__cdecl *H5PL_get_plugin_info_t)(void);
#else /* H5_HAVE_WIN32_API */
@@ -105,6 +106,7 @@
/* Clear error */
# define H5PL_CLR_ERROR HERROR(H5E_PLUGIN, H5E_CANTGET, "can't dlopen:%s", dlerror())
+ typedef H5PL_type_t(*H5PL_get_plugin_type_t)(void);
typedef const void *(*H5PL_get_plugin_info_t)(void);
#endif /* H5_HAVE_WIN32_API */
@@ -116,7 +118,7 @@
/* Data used to search for plugins */
typedef struct H5PL_search_params_t {
H5PL_type_t type;
- H5PL_key_t key;
+ const H5PL_key_t *key;
} H5PL_search_params_t;
@@ -134,13 +136,15 @@ H5_DLL herr_t H5PL__get_plugin_control_mask(unsigned int *mask /*out*/);
H5_DLL herr_t H5PL__set_plugin_control_mask(unsigned int mask);
/* Plugin search and manipulation */
-H5_DLL herr_t H5PL__open(const char *libname, H5PL_type_t type, H5PL_key_t key, hbool_t *success /*out*/, const void **plugin_info /*out*/);
+H5_DLL herr_t H5PL__open(const char *libname, H5PL_type_t type, const H5PL_key_t *key,
+ hbool_t *success /*out*/, const void **plugin_info /*out*/);
H5_DLL herr_t H5PL__close(H5PL_HANDLE handle);
/* Plugin cache calls */
H5_DLL herr_t H5PL__create_plugin_cache(void);
H5_DLL herr_t H5PL__close_plugin_cache(hbool_t *already_closed /*out*/);
-H5_DLL herr_t H5PL__add_plugin(H5PL_type_t type, H5PL_key_t key, H5PL_HANDLE handle);
+H5_DLL herr_t H5PL__add_plugin(H5PL_type_t type, const H5PL_key_t *key,
+ H5PL_HANDLE handle);
H5_DLL herr_t H5PL__find_plugin_in_cache(const H5PL_search_params_t *search_params, hbool_t *found /*out*/, const void **plugin_info /*out*/);
/* Plugin search path calls */
diff --git a/src/H5PLplugin_cache.c b/src/H5PLplugin_cache.c
index e905ac2..cd0b4d6 100644
--- a/src/H5PLplugin_cache.c
+++ b/src/H5PLplugin_cache.c
@@ -216,7 +216,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5PL__add_plugin(H5PL_type_t type, H5PL_key_t key, H5PL_HANDLE handle)
+H5PL__add_plugin(H5PL_type_t type, const H5PL_key_t *key, H5PL_HANDLE handle)
{
herr_t ret_value = SUCCEED;
@@ -229,7 +229,7 @@ H5PL__add_plugin(H5PL_type_t type, H5PL_key_t key, H5PL_HANDLE handle)
/* Store the plugin info and bump the # of plugins */
H5PL_cache_g[H5PL_num_plugins_g].type = type;
- H5PL_cache_g[H5PL_num_plugins_g].key = key;
+ H5PL_cache_g[H5PL_num_plugins_g].key = *key;
H5PL_cache_g[H5PL_num_plugins_g].handle = handle;
H5PL_num_plugins_g++;
@@ -276,7 +276,7 @@ H5PL__find_plugin_in_cache(const H5PL_search_params_t *search_params, hbool_t *f
for (u = 0; u < H5PL_num_plugins_g; u++) {
/* If the plugin type (filter, etc.) and ID match, query the plugin for its info */
- if ((search_params->type == (H5PL_cache_g[u]).type) && (search_params->key.id == (H5PL_cache_g[u]).key.id)) {
+ if ((search_params->type == (H5PL_cache_g[u]).type) && (search_params->key->id == (H5PL_cache_g[u]).key.id)) {
H5PL_get_plugin_info_t get_plugin_info_function;
const H5Z_class2_t *filter_info;
diff --git a/src/H5PLprivate.h b/src/H5PLprivate.h
index cc2e258..5ce9b87 100644
--- a/src/H5PLprivate.h
+++ b/src/H5PLprivate.h
@@ -21,7 +21,8 @@
#include "H5PLpublic.h"
/* Private headers needed by this file */
-#include "H5private.h" /* Generic Functions */
+#include "H5private.h" /* Generic Functions */
+#include "H5VLprivate.h" /* Virtual Object Layer */
/**************************/
@@ -35,7 +36,14 @@
/* The key that will be used to find the plugin */
typedef union H5PL_key_t {
- int id; /* filters */
+ int id; /* I/O filters */
+ struct {
+ H5VL_get_connector_kind_t kind; /* Kind of VOL lookup to do */
+ union {
+ H5VL_class_value_t value; /* VOL connector value */
+ const char *name; /* VOL connector name */
+ } u;
+ } vol;
} H5PL_key_t;
@@ -49,7 +57,7 @@ typedef union H5PL_key_t {
/***************************************/
/* Internal API routines */
-H5_DLL const void *H5PL_load(H5PL_type_t plugin_type, H5PL_key_t key);
+H5_DLL const void *H5PL_load(H5PL_type_t plugin_type, const H5PL_key_t *key);
#endif /* _H5PLprivate_H */
diff --git a/src/H5PLpublic.h b/src/H5PLpublic.h
index fe5bdfb..8e022cc 100644
--- a/src/H5PLpublic.h
+++ b/src/H5PLpublic.h
@@ -32,11 +32,13 @@
typedef enum H5PL_type_t {
H5PL_TYPE_ERROR = -1, /* Error */
H5PL_TYPE_FILTER = 0, /* Filter */
- H5PL_TYPE_NONE = 1 /* This must be last! */
+ H5PL_TYPE_VOL = 1, /* VOL driver */
+ H5PL_TYPE_NONE = 2 /* This must be last! */
} H5PL_type_t;
/* Common dynamic plugin type flags used by the set/get_loading_state functions */
#define H5PL_FILTER_PLUGIN 0x0001
+#define H5PL_VOL_PLUGIN 0x0002
#define H5PL_ALL_PLUGIN 0xFFFF
#ifdef __cplusplus
diff --git a/src/H5Pacpl.c b/src/H5Pacpl.c
index 530ede3..53e68fa 100644
--- a/src/H5Pacpl.c
+++ b/src/H5Pacpl.c
@@ -33,6 +33,7 @@
#include "H5private.h" /* Generic Functions */
#include "H5Eprivate.h" /* Error handling */
#include "H5Ppkg.h" /* Property lists */
+#include "H5VLprivate.h" /* Virtual Object Layer */
/****************/
@@ -83,4 +84,3 @@ const H5P_libclass_t H5P_CLS_ACRT[1] = {{
/* Library Private Variables */
/*****************************/
-
diff --git a/src/H5Pdapl.c b/src/H5Pdapl.c
index 00e598f..5ce12b4 100644
--- a/src/H5Pdapl.c
+++ b/src/H5Pdapl.c
@@ -37,8 +37,8 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5Fprivate.h" /* Files */
#include "H5Iprivate.h" /* IDs */
+#include "H5MMprivate.h" /* Memory management */
#include "H5Ppkg.h" /* Property lists */
-#include "H5MMprivate.h" /* Memory management */
/****************/
@@ -341,7 +341,7 @@ H5P__dapl_vds_file_pref_enc(const void *value, void **_pp, size_t *size)
/* encode the prefix */
if(NULL != vds_file_pref) {
- HDmemcpy(*(char **)pp, vds_file_pref, len);
+ H5MM_memcpy(*(char **)pp, vds_file_pref, len);
*pp += len;
} /* end if */
} /* end if */
@@ -589,7 +589,7 @@ H5P__dapl_efile_pref_enc(const void *value, void **_pp, size_t *size)
/* encode the prefix */
if(NULL != efile_pref) {
- HDmemcpy(*(char **)pp, efile_pref, len);
+ H5MM_memcpy(*(char **)pp, efile_pref, len);
*pp += len;
} /* end if */
} /* end if */
diff --git a/src/H5Pdcpl.c b/src/H5Pdcpl.c
index 7e9fc52..721ba89 100644
--- a/src/H5Pdcpl.c
+++ b/src/H5Pdcpl.c
@@ -117,6 +117,11 @@
#define H5D_CRT_EXT_FILE_LIST_COPY H5P__dcrt_ext_file_list_copy
#define H5D_CRT_EXT_FILE_LIST_CMP H5P__dcrt_ext_file_list_cmp
#define H5D_CRT_EXT_FILE_LIST_CLOSE H5P__dcrt_ext_file_list_close
+/* Definitions for dataset object header minimization */
+#define H5D_CRT_MIN_DSET_HDR_SIZE_SIZE sizeof(hbool_t)
+#define H5D_CRT_MIN_DSET_HDR_SIZE_DEF FALSE
+#define H5D_CRT_MIN_DSET_HDR_SIZE_ENC H5P__encode_hbool_t
+#define H5D_CRT_MIN_DSET_HDR_SIZE_DEC H5P__decode_hbool_t
/******************/
@@ -209,6 +214,7 @@ static const H5O_layout_t H5D_def_layout_g = H5D_CRT_LAYOUT_DEF; /* Defau
static const H5O_fill_t H5D_def_fill_g = H5D_CRT_FILL_VALUE_DEF; /* Default fill value */
static const unsigned H5D_def_alloc_time_state_g = H5D_CRT_ALLOC_TIME_STATE_DEF; /* Default allocation time state */
static const H5O_efl_t H5D_def_efl_g = H5D_CRT_EXT_FILE_LIST_DEF; /* Default external file list */
+static const unsigned H5O_ohdr_min_g = H5D_CRT_MIN_DSET_HDR_SIZE_DEF; /* Default object header minimization */
/* Defaults for each type of layout */
#ifdef H5_HAVE_C99_DESIGNATED_INITIALIZER
@@ -268,6 +274,12 @@ H5P__dcrt_reg_prop(H5P_genclass_t *pclass)
H5D_CRT_EXT_FILE_LIST_DEL, H5D_CRT_EXT_FILE_LIST_COPY, H5D_CRT_EXT_FILE_LIST_CMP, H5D_CRT_EXT_FILE_LIST_CLOSE) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
+ /* Register the object header minimization property */
+ if(H5P__register_real(pclass, H5D_CRT_MIN_DSET_HDR_SIZE_NAME, H5D_CRT_MIN_DSET_HDR_SIZE_SIZE, &H5O_ohdr_min_g,
+ NULL, NULL, NULL, H5D_CRT_MIN_DSET_HDR_SIZE_ENC, H5D_CRT_MIN_DSET_HDR_SIZE_DEC,
+ NULL, NULL, NULL, NULL) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
+
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5P__dcrt_reg_prop() */
@@ -409,13 +421,13 @@ H5P__dcrt_layout_enc(const void *value, void **_pp, size_t *size)
for(u = 0; u < layout->storage.u.virt.list_nused; u++) {
/* Source file name */
tmp_size = HDstrlen(layout->storage.u.virt.list[u].source_file_name) + (size_t)1;
- (void)HDmemcpy(*pp, layout->storage.u.virt.list[u].source_file_name, tmp_size);
+ (void)H5MM_memcpy(*pp, layout->storage.u.virt.list[u].source_file_name, tmp_size);
*pp += tmp_size;
*size += tmp_size;
/* Source dataset name */
tmp_size = HDstrlen(layout->storage.u.virt.list[u].source_dset_name) + (size_t)1;
- (void)HDmemcpy(*pp, layout->storage.u.virt.list[u].source_dset_name, tmp_size);
+ (void)H5MM_memcpy(*pp, layout->storage.u.virt.list[u].source_dset_name, tmp_size);
*pp += tmp_size;
*size += tmp_size;
@@ -585,14 +597,14 @@ H5P__dcrt_layout_dec(const void **_pp, void *value)
tmp_size = HDstrlen((const char *)*pp) + 1;
if(NULL == (tmp_layout.storage.u.virt.list[u].source_file_name = (char *)H5MM_malloc(tmp_size)))
HGOTO_ERROR(H5E_PLIST, H5E_CANTALLOC, FAIL, "unable to allocate memory for source file name")
- (void)HDmemcpy(tmp_layout.storage.u.virt.list[u].source_file_name, *pp, tmp_size);
+ (void)H5MM_memcpy(tmp_layout.storage.u.virt.list[u].source_file_name, *pp, tmp_size);
*pp += tmp_size;
/* Source dataset name */
tmp_size = HDstrlen((const char *)*pp) + 1;
if(NULL == (tmp_layout.storage.u.virt.list[u].source_dset_name = (char *)H5MM_malloc(tmp_size)))
HGOTO_ERROR(H5E_PLIST, H5E_CANTALLOC, FAIL, "unable to allocate memory for source dataset name")
- (void)HDmemcpy(tmp_layout.storage.u.virt.list[u].source_dset_name, *pp, tmp_size);
+ (void)H5MM_memcpy(tmp_layout.storage.u.virt.list[u].source_dset_name, *pp, tmp_size);
*pp += tmp_size;
/* Source selection */
@@ -657,7 +669,7 @@ H5P__dcrt_layout_dec(const void **_pp, void *value)
} /* end switch */
/* Set the value */
- HDmemcpy(value, layout, sizeof(H5O_layout_t));
+ H5MM_memcpy(value, layout, sizeof(H5O_layout_t));
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -815,7 +827,7 @@ H5P__dcrt_layout_cmp(const void *_layout1, const void *_layout2,
if((equal = H5S_extent_equal(layout1->storage.u.virt.list[u].source_dset.virtual_select, layout2->storage.u.virt.list[u].source_dset.virtual_select)) < 0) HGOTO_DONE(-1)
if(!equal)
HGOTO_DONE(1)
- if((equal = H5S_select_shape_same(layout1->storage.u.virt.list[u].source_dset.virtual_select, layout2->storage.u.virt.list[u].source_dset.virtual_select)) < 0) HGOTO_DONE(-1)
+ if((equal = H5S_SELECT_SHAPE_SAME(layout1->storage.u.virt.list[u].source_dset.virtual_select, layout2->storage.u.virt.list[u].source_dset.virtual_select)) < 0) HGOTO_DONE(-1)
if(!equal)
HGOTO_DONE(1)
@@ -835,7 +847,7 @@ H5P__dcrt_layout_cmp(const void *_layout1, const void *_layout2,
if((equal = H5S_extent_equal(layout1->storage.u.virt.list[u].source_select, layout2->storage.u.virt.list[u].source_select)) < 0) HGOTO_DONE(-1)
if(!equal)
HGOTO_DONE(1)
- if((equal = H5S_select_shape_same(layout1->storage.u.virt.list[u].source_select, layout2->storage.u.virt.list[u].source_select)) < 0) HGOTO_DONE(-1)
+ if((equal = H5S_SELECT_SHAPE_SAME(layout1->storage.u.virt.list[u].source_select, layout2->storage.u.virt.list[u].source_select)) < 0) HGOTO_DONE(-1)
if(!equal)
HGOTO_DONE(1)
} /* end for */
@@ -1006,7 +1018,7 @@ H5P__dcrt_fill_value_enc(const void *value, void **_pp, size_t *size)
/* Encode the fill value & datatype */
if(fill->size > 0) {
/* Encode the fill value itself */
- HDmemcpy(*pp, (uint8_t *)fill->buf, (size_t)fill->size);
+ H5MM_memcpy(*pp, (uint8_t *)fill->buf, (size_t)fill->size);
*pp += fill->size;
/* Encode fill value datatype */
@@ -1103,7 +1115,7 @@ H5P__dcrt_fill_value_dec(const void **_pp, void *_value)
/* Allocate fill buffer and copy the contents in it */
if(NULL == (fill->buf = H5MM_malloc((size_t)fill->size)))
HGOTO_ERROR(H5E_PLIST, H5E_CANTALLOC, FAIL, "memory allocation failed for fill value buffer")
- HDmemcpy((uint8_t *)fill->buf, *pp, (size_t)fill->size);
+ H5MM_memcpy((uint8_t *)fill->buf, *pp, (size_t)fill->size);
*pp += fill->size;
enc_size = *(*pp)++;
@@ -1418,7 +1430,7 @@ H5P__dcrt_ext_file_list_enc(const void *value, void **_pp, size_t *size)
UINT64ENCODE_VAR(*pp, enc_value, enc_size);
/* Encode name */
- HDmemcpy(*pp, (uint8_t *)(efl->slot[u].name), len);
+ H5MM_memcpy(*pp, (uint8_t *)(efl->slot[u].name), len);
*pp += len;
/* Encode offset */
@@ -2005,7 +2017,7 @@ H5Pset_chunk(hid_t plist_id, int ndims, const hsize_t dim[/*ndims*/])
#endif /* H5_HAVE_C99_DESIGNATED_INITIALIZER */
/* Verify & initialize property's chunk dims */
- HDmemcpy(&chunk_layout, &H5D_def_layout_chunk_g, sizeof(H5D_def_layout_chunk_g));
+ H5MM_memcpy(&chunk_layout, &H5D_def_layout_chunk_g, sizeof(H5D_def_layout_chunk_g));
HDmemset(&chunk_layout.u.chunk.dim, 0, sizeof(chunk_layout.u.chunk.dim));
chunk_nelmts = 1;
for(u = 0; u < (unsigned)ndims; u++) {
@@ -2174,7 +2186,7 @@ H5Pset_virtual(hid_t dcpl_id, hid_t vspace_id, const char *src_file_name,
HGOTO_ERROR(H5E_PLIST, H5E_CANTRESET, FAIL, "can't release layout message")
/* Copy the default virtual layout */
- HDmemcpy(&virtual_layout, &H5D_def_layout_virtual_g, sizeof(H5D_def_layout_virtual_g));
+ H5MM_memcpy(&virtual_layout, &H5D_def_layout_virtual_g, sizeof(H5D_def_layout_virtual_g));
/* Sanity check */
HDassert(virtual_layout.storage.u.virt.list_nalloc == 0);
@@ -3213,7 +3225,7 @@ H5Pset_fill_value(hid_t plist_id, hid_t type_id, const void *value)
fill.size = (ssize_t)H5T_get_size(type);
if(NULL == (fill.buf = H5MM_malloc((size_t)fill.size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "memory allocation failed for fill value")
- HDmemcpy(fill.buf, value, (size_t)fill.size);
+ H5MM_memcpy(fill.buf, value, (size_t)fill.size);
/* Set up type conversion function */
if(NULL == (tpath = H5T_path_find(type, type)))
@@ -3321,7 +3333,7 @@ H5P_get_fill_value(H5P_genplist_t *plist, const H5T_t *type, void *value/*out*/)
if(H5T_path_bkg(tpath) && NULL == (bkg = H5MM_malloc(H5T_get_size(fill.type))))
HGOTO_ERROR(H5E_PLIST, H5E_CANTALLOC, FAIL, "memory allocation failed for type conversion")
} /* end else */
- HDmemcpy(buf, fill.buf, H5T_get_size(fill.type));
+ H5MM_memcpy(buf, fill.buf, H5T_get_size(fill.type));
/* Do the conversion */
if((dst_id = H5I_register(H5I_DATATYPE, H5T_copy(type, H5T_COPY_TRANSIENT), FALSE)) < 0)
@@ -3329,7 +3341,7 @@ H5P_get_fill_value(H5P_genplist_t *plist, const H5T_t *type, void *value/*out*/)
if(H5T_convert(tpath, src_id, dst_id, (size_t)1, (size_t)0, (size_t)0, buf, bkg) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "datatype conversion failed")
if(buf != value)
- HDmemcpy(value, buf, H5T_get_size(type));
+ H5MM_memcpy(value, buf, H5T_get_size(type));
done:
if(buf != value)
@@ -3731,3 +3743,95 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Pget_fill_time() */
+
+/*-----------------------------------------------------------------------------
+ * Function: H5Pget_dset_no_attrs_hint
+ *
+ * Purpose:
+ *
+ * Access the flag for whether or not datasets created by the given dcpl
+ * will be created with a "minimized" object header.
+ *
+ * Return:
+ *
+ * Failure: Negative value (FAIL)
+ * Success: Non-negative value (SUCCEED)
+ *
+ * Programmer: Jacob Smith
+ * 2018 August 14
+ *
+ * Modifications: None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+herr_t
+H5Pget_dset_no_attrs_hint(hid_t dcpl_id, hbool_t *minimize)
+{
+ hbool_t setting = FALSE;
+ H5P_genplist_t *plist = NULL;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE2("e", "i*b", dcpl_id, minimize);
+
+ if(NULL == minimize)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "receiving pointer cannot be NULL")
+
+ plist = H5P_object_verify(dcpl_id, H5P_DATASET_CREATE);
+ if(NULL == plist)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
+
+ if(H5P_peek(plist, H5D_CRT_MIN_DSET_HDR_SIZE_NAME, &setting) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get dset oh minimize flag value")
+
+ *minimize = setting;
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* H5Pget_dset_no_attrs_hint() */
+
+
+/*-----------------------------------------------------------------------------
+ * Function: H5Pset_dset_no_attrs_hint
+ *
+ * Purpose:
+ *
+ * Set the dcpl to minimize (or explicitly to not minimized) dataset object
+ * headers upon creation.
+ *
+ * Return:
+ *
+ * Failure: Negative value (FAIL)
+ * Success: Non-negative value (SUCCEED)
+ *
+ * Programmer: Jacob Smith
+ * 2018 August 14
+ *
+ * Modifications: None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+herr_t
+H5Pset_dset_no_attrs_hint(hid_t dcpl_id, hbool_t minimize)
+{
+ H5P_genplist_t *plist = NULL;
+ hbool_t prev_set = FALSE;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE2("e", "ib", dcpl_id, minimize);
+
+ plist = H5P_object_verify(dcpl_id, H5P_DATASET_CREATE);
+ if(NULL == plist)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
+
+ if(H5P_peek(plist, H5D_CRT_MIN_DSET_HDR_SIZE_NAME, &prev_set) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get extant dset oh minimize flag value")
+
+ if(H5P_poke(plist, H5D_CRT_MIN_DSET_HDR_SIZE_NAME, &minimize) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't get dset oh minimize flag value")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* H5Pset_dset_no_attrs_hint() */
+
diff --git a/src/H5Pdeprec.c b/src/H5Pdeprec.c
index 4a63b36..1b5f581 100644
--- a/src/H5Pdeprec.c
+++ b/src/H5Pdeprec.c
@@ -36,6 +36,7 @@
/* Headers */
/***********/
#include "H5private.h" /* Generic Functions */
+#include "H5CXprivate.h" /* API Contexts */
#include "H5Eprivate.h" /* Error handling */
#include "H5Fprivate.h" /* Files */
#include "H5Iprivate.h" /* IDs */
@@ -486,6 +487,54 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Pget_version() */
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Pencode1
+ PURPOSE
+ Routine to convert the property values in a property list into a binary buffer
+ USAGE
+ herr_t H5Pencode1(plist_id, buf, nalloc)
+ hid_t plist_id; IN: Identifier to property list to encode
+ void *buf: OUT: buffer to gold the encoded plist
+ size_t *nalloc; IN/OUT: size of buffer needed to encode plist
+ RETURNS
+ Returns non-negative on success, negative on failure.
+ DESCRIPTION
+ Encodes a property list into a binary buffer. If the buffer is NULL, then
+ the call will set the size needed to encode the plist in nalloc. Otherwise
+ the routine will encode the plist in buf.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5Pencode1(hid_t plist_id, void *buf, size_t *nalloc)
+{
+ H5P_genplist_t *plist; /* Property list to query */
+ hid_t temp_fapl_id = H5P_DEFAULT;
+ herr_t ret_value = SUCCEED; /* return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE3("e", "i*x*z", plist_id, buf, nalloc);
+
+ /* Check arguments. */
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object_verify(plist_id, H5I_GENPROP_LST)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list");
+
+ /* Verify access property list and set up collective metadata if appropriate */
+ if(H5CX_set_apl(&temp_fapl_id, H5P_CLS_FACC, H5I_INVALID_HID, TRUE) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info")
+
+ /* Call the internal encode routine */
+ if((ret_value = H5P__encode(plist, TRUE, buf, nalloc)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTENCODE, FAIL, "unable to encode property list");
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* H5Pencode1() */
+
/*-------------------------------------------------------------------------
* Function: H5Pset_file_space
*
diff --git a/src/H5Pdxpl.c b/src/H5Pdxpl.c
index bfc1d93..9baa201 100644
--- a/src/H5Pdxpl.c
+++ b/src/H5Pdxpl.c
@@ -695,7 +695,7 @@ H5P__dxfr_xform_enc(const void *value, void **_pp, size_t *size)
HDassert(pexp);
/* Copy the expression into the buffer */
- HDmemcpy(*pp, (const uint8_t *)pexp, len);
+ H5MM_memcpy(*pp, (const uint8_t *)pexp, len);
*pp += len;
*pp[0] = '\0';
} /* end if */
@@ -1519,7 +1519,7 @@ done:
*
* Purpose: Sets the memory allocate/free pair for VL datatypes. The
* allocation routine is called when data is read into a new
- * array and the free routine is called when H5Dvlen_reclaim is
+ * array and the free routine is called when H5Treclaim is
* called. The alloc_info and free_info are user parameters
* which are passed to the allocation and freeing functions
* respectively. To reset the allocate/free functions to the
@@ -1563,7 +1563,7 @@ done:
*
* Purpose: Sets the memory allocate/free pair for VL datatypes. The
* allocation routine is called when data is read into a new
- * array and the free routine is called when H5Dvlen_reclaim is
+ * array and the free routine is called when H5Treclaim is
* called. The alloc_info and free_info are user parameters
* which are passed to the allocation and freeing functions
* respectively. To reset the allocate/free functions to the
@@ -2017,6 +2017,7 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Pget_mpio_actual_io_mode() */
+
/*-------------------------------------------------------------------------
* Function: H5Pget_mpio_no_collective_cause
*
@@ -2053,8 +2054,6 @@ H5Pget_mpio_no_collective_cause(hid_t plist_id, uint32_t *local_no_collective_ca
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Pget_mpio_no_collective_cause() */
-
-
#endif /* H5_HAVE_PARALLEL */
diff --git a/src/H5Pencdec.c b/src/H5Pencdec.c
index 8b9962f..2a07a67 100644
--- a/src/H5Pencdec.c
+++ b/src/H5Pencdec.c
@@ -722,7 +722,7 @@ H5P__decode(const void *buf)
/* Get the type of the property list */
type = (H5P_plist_type_t)*p++;
- if(type <= H5P_TYPE_USER || type > H5P_TYPE_LINK_ACCESS)
+ if(type <= H5P_TYPE_USER || type >= H5P_TYPE_MAX_TYPE)
HGOTO_ERROR(H5E_PLIST, H5E_BADRANGE, FAIL, "bad type of encoded information: %u", (unsigned)type)
/* Create new property list of the specified type */
diff --git a/src/H5Pfapl.c b/src/H5Pfapl.c
index 0f17959..a3873b4 100644
--- a/src/H5Pfapl.c
+++ b/src/H5Pfapl.c
@@ -30,24 +30,28 @@
/***********/
/* Headers */
/***********/
-#include "H5private.h" /* Generic Functions */
-#include "H5ACprivate.h" /* Metadata cache */
-#include "H5Dprivate.h" /* Datasets */
-#include "H5Eprivate.h" /* Error handling */
-#include "H5Fprivate.h" /* Files */
-#include "H5FDprivate.h" /* File drivers */
-#include "H5Iprivate.h" /* IDs */
-#include "H5MMprivate.h" /* Memory Management */
-#include "H5Ppkg.h" /* Property lists */
-
-/* Includes needed to set as default file driver */
-#include "H5FDsec2.h" /* Posix unbuffered I/O file driver */
-#include "H5FDstdio.h" /* Standard C buffered I/O */
+#include "H5private.h" /* Generic Functions */
+#include "H5ACprivate.h" /* Metadata cache */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fprivate.h" /* Files */
+#include "H5FDprivate.h" /* File drivers */
+#include "H5Iprivate.h" /* IDs */
+#include "H5MMprivate.h" /* Memory Management */
+#include "H5Ppkg.h" /* Property lists */
+#include "H5VLprivate.h" /* Virtual Object Layer */
+#include "H5VMprivate.h" /* Vector Functions */
+
+/* Includes needed to set default file driver */
+#include "H5FDsec2.h" /* POSIX unbuffered I/O */
+#include "H5FDstdio.h" /* Standard C buffered I/O */
#ifdef H5_HAVE_WINDOWS
-#include "H5FDwindows.h" /* Win32 I/O */
+#include "H5FDwindows.h" /* Win32 I/O */
#endif
#include "H5FDvfd_swmr.h" /* Posix unbuffered I/O file driver */
+/* Includes needed to set default VOL connector */
+#include "H5VLnative_private.h" /* Native VOL connector */
+
/****************/
/* Local Macros */
@@ -108,7 +112,7 @@
#define H5F_ACS_GARBG_COLCT_REF_DEF 0
#define H5F_ACS_GARBG_COLCT_REF_ENC H5P__encode_unsigned
#define H5F_ACS_GARBG_COLCT_REF_DEC H5P__decode_unsigned
-/* Definition for file driver ID & info*/
+/* Definition for file driver ID & info */
#define H5F_ACS_FILE_DRV_SIZE sizeof(H5FD_driver_prop_t)
#define H5F_ACS_FILE_DRV_DEF {H5_DEFAULT_VFD, NULL}
#define H5F_ACS_FILE_DRV_CRT H5P__facc_file_driver_create
@@ -132,10 +136,11 @@
* property only used by h5repart */
#define H5F_ACS_FAMILY_NEWSIZE_SIZE sizeof(hsize_t)
#define H5F_ACS_FAMILY_NEWSIZE_DEF 0
-/* Definition for whether to convert family to sec2 driver. It's private
- * property only used by h5repart */
-#define H5F_ACS_FAMILY_TO_SEC2_SIZE sizeof(hbool_t)
-#define H5F_ACS_FAMILY_TO_SEC2_DEF FALSE
+/* Definition for whether to convert family to a single-file driver.
+ * It's a private property only used by h5repart.
+ */
+#define H5F_ACS_FAMILY_TO_SINGLE_SIZE sizeof(hbool_t)
+#define H5F_ACS_FAMILY_TO_SINGLE_DEF FALSE
/* Definition for data type in multi file driver */
#define H5F_ACS_MULTI_TYPE_SIZE sizeof(H5FD_mem_t)
#define H5F_ACS_MULTI_TYPE_DEF H5FD_MEM_DEFAULT
@@ -173,16 +178,6 @@
#define H5F_ACS_FILE_IMAGE_INFO_COPY H5P__facc_file_image_info_copy
#define H5F_ACS_FILE_IMAGE_INFO_CMP H5P__facc_file_image_info_cmp
#define H5F_ACS_FILE_IMAGE_INFO_CLOSE H5P__facc_file_image_info_close
-/* Definition of core VFD write tracking flag */
-#define H5F_ACS_CORE_WRITE_TRACKING_FLAG_SIZE sizeof(hbool_t)
-#define H5F_ACS_CORE_WRITE_TRACKING_FLAG_DEF FALSE
-#define H5F_ACS_CORE_WRITE_TRACKING_FLAG_ENC H5P__encode_hbool_t
-#define H5F_ACS_CORE_WRITE_TRACKING_FLAG_DEC H5P__decode_hbool_t
-/* Definition of core VFD write tracking page size */
-#define H5F_ACS_CORE_WRITE_TRACKING_PAGE_SIZE_SIZE sizeof(size_t)
-#define H5F_ACS_CORE_WRITE_TRACKING_PAGE_SIZE_DEF 524288
-#define H5F_ACS_CORE_WRITE_TRACKING_PAGE_SIZE_ENC H5P__encode_size_t
-#define H5F_ACS_CORE_WRITE_TRACKING_PAGE_SIZE_DEC H5P__decode_size_t
/* Definition for # of metadata read attempts */
#define H5F_ACS_METADATA_READ_ATTEMPTS_SIZE sizeof(unsigned)
#define H5F_ACS_METADATA_READ_ATTEMPTS_DEF 0
@@ -237,6 +232,24 @@
#define H5F_ACS_COLL_MD_WRITE_FLAG_DEF FALSE
#define H5F_ACS_COLL_MD_WRITE_FLAG_ENC H5P__encode_hbool_t
#define H5F_ACS_COLL_MD_WRITE_FLAG_DEC H5P__decode_hbool_t
+/* Definition for the file's MPI communicator */
+#define H5F_ACS_MPI_PARAMS_COMM_SIZE sizeof(MPI_Comm)
+#define H5F_ACS_MPI_PARAMS_COMM_DEF MPI_COMM_NULL
+#define H5F_ACS_MPI_PARAMS_COMM_SET H5P__facc_mpi_comm_set
+#define H5F_ACS_MPI_PARAMS_COMM_GET H5P__facc_mpi_comm_get
+#define H5F_ACS_MPI_PARAMS_COMM_DEL H5P__facc_mpi_comm_del
+#define H5F_ACS_MPI_PARAMS_COMM_COPY H5P__facc_mpi_comm_copy
+#define H5F_ACS_MPI_PARAMS_COMM_CMP H5P__facc_mpi_comm_cmp
+#define H5F_ACS_MPI_PARAMS_COMM_CLOSE H5P__facc_mpi_comm_close
+/* Definition for the file's MPI info */
+#define H5F_ACS_MPI_PARAMS_INFO_SIZE sizeof(MPI_Info)
+#define H5F_ACS_MPI_PARAMS_INFO_DEF MPI_INFO_NULL
+#define H5F_ACS_MPI_PARAMS_INFO_SET H5P__facc_mpi_info_set
+#define H5F_ACS_MPI_PARAMS_INFO_GET H5P__facc_mpi_info_get
+#define H5F_ACS_MPI_PARAMS_INFO_DEL H5P__facc_mpi_info_del
+#define H5F_ACS_MPI_PARAMS_INFO_COPY H5P__facc_mpi_info_copy
+#define H5F_ACS_MPI_PARAMS_INFO_CMP H5P__facc_mpi_info_cmp
+#define H5F_ACS_MPI_PARAMS_INFO_CLOSE H5P__facc_mpi_info_close
#endif /* H5_HAVE_PARALLEL */
/* Definitions for the initial metadata cache image configuration */
#define H5F_ACS_META_CACHE_INIT_IMAGE_CONFIG_SIZE sizeof(H5AC_cache_image_config_t)
@@ -259,6 +272,16 @@
#define H5F_ACS_PAGE_BUFFER_MIN_RAW_PERC_DEF 0
#define H5F_ACS_PAGE_BUFFER_MIN_RAW_PERC_ENC H5P__encode_unsigned
#define H5F_ACS_PAGE_BUFFER_MIN_RAW_PERC_DEC H5P__decode_unsigned
+/* Definition for file VOL connector properties (ID, etc.) */
+#define H5F_ACS_VOL_CONN_SIZE sizeof(H5VL_connector_prop_t)
+#define H5F_ACS_VOL_CONN_DEF {H5_DEFAULT_VOL, NULL}
+#define H5F_ACS_VOL_CONN_CRT H5P__facc_vol_create
+#define H5F_ACS_VOL_CONN_SET H5P__facc_vol_set
+#define H5F_ACS_VOL_CONN_GET H5P__facc_vol_get
+#define H5F_ACS_VOL_CONN_DEL H5P__facc_vol_del
+#define H5F_ACS_VOL_CONN_COPY H5P__facc_vol_copy
+#define H5F_ACS_VOL_CONN_CMP H5P__facc_vol_cmp
+#define H5F_ACS_VOL_CONN_CLOSE H5P__facc_vol_close
/* Definitions for the VFD SWMR configuration */
#define H5F_ACS_VFD_SWMR_CONFIG_SIZE sizeof(H5F_vfd_swmr_config_t)
@@ -328,6 +351,33 @@ static int H5P__facc_cache_image_config_cmp(const void *_config1, const void *_c
static herr_t H5P__facc_cache_image_config_enc(const void *value, void **_pp, size_t *size);
static herr_t H5P__facc_cache_image_config_dec(const void **_pp, void *_value);
+/* VOL connector callbacks */
+static herr_t H5P__facc_vol_create(const char *name, size_t size, void *value);
+static herr_t H5P__facc_vol_set(hid_t prop_id, const char *name, size_t size, void *value);
+static herr_t H5P__facc_vol_get(hid_t prop_id, const char *name, size_t size, void *value);
+static herr_t H5P__facc_vol_del(hid_t prop_id, const char *name, size_t size, void *value);
+static herr_t H5P__facc_vol_copy(const char *name, size_t size, void *value);
+static int H5P__facc_vol_cmp(const void *value1, const void *value2, size_t size);
+static herr_t H5P__facc_vol_close(const char *name, size_t size, void *value);
+
+#ifdef H5_HAVE_PARALLEL
+/* MPI communicator callbacks */
+static herr_t H5P__facc_mpi_comm_set(hid_t prop_id, const char *name, size_t size, void *value);
+static herr_t H5P__facc_mpi_comm_get(hid_t prop_id, const char *name, size_t size, void *value);
+static herr_t H5P__facc_mpi_comm_del(hid_t prop_id, const char *name, size_t size, void *value);
+static herr_t H5P__facc_mpi_comm_copy(const char *name, size_t size, void *value);
+static int H5P__facc_mpi_comm_cmp(const void *value1, const void *value2, size_t size);
+static herr_t H5P__facc_mpi_comm_close(const char *name, size_t size, void *value);
+
+/* MPI info callbacks */
+static herr_t H5P__facc_mpi_info_set(hid_t prop_id, const char *name, size_t size, void *value);
+static herr_t H5P__facc_mpi_info_get(hid_t prop_id, const char *name, size_t size, void *value);
+static herr_t H5P__facc_mpi_info_del(hid_t prop_id, const char *name, size_t size, void *value);
+static herr_t H5P__facc_mpi_info_copy(const char *name, size_t size, void *value);
+static int H5P__facc_mpi_info_cmp(const void *value1, const void *value2, size_t size);
+static herr_t H5P__facc_mpi_info_close(const char *name, size_t size, void *value);
+#endif /* H5_HAVE_PARALLEL */
+
/*********************/
/* Package Variables */
@@ -376,7 +426,7 @@ static const unsigned H5F_def_gc_ref_g = H5F_ACS_GARBG_COLCT_REF_DEF;
static const H5F_close_degree_t H5F_def_close_degree_g = H5F_CLOSE_DEGREE_DEF; /* Default file close degree */
static const hsize_t H5F_def_family_offset_g = H5F_ACS_FAMILY_OFFSET_DEF; /* Default offset for family VFD */
static const hsize_t H5F_def_family_newsize_g = H5F_ACS_FAMILY_NEWSIZE_DEF; /* Default size of new files for family VFD */
-static const hbool_t H5F_def_family_to_sec2_g = H5F_ACS_FAMILY_TO_SEC2_DEF; /* Default ?? for family VFD */
+static const hbool_t H5F_def_family_to_single_g = H5F_ACS_FAMILY_TO_SINGLE_DEF; /* Default ?? for family VFD */
static const H5FD_mem_t H5F_def_mem_type_g = H5F_ACS_MULTI_TYPE_DEF; /* Default file space type for multi VFD */
static const H5F_libver_t H5F_def_libver_low_bound_g = H5F_ACS_LIBVER_LOW_BOUND_DEF; /* Default setting for "low" bound of format version */
@@ -385,8 +435,6 @@ static const H5F_libver_t H5F_def_libver_high_bound_g = H5F_ACS_LIBVER_HIGH_BOUN
static const hbool_t H5F_def_want_posix_fd_g = H5F_ACS_WANT_POSIX_FD_DEF; /* Default setting for retrieving 'handle' from core VFD */
static const unsigned H5F_def_efc_size_g = H5F_ACS_EFC_SIZE_DEF; /* Default external file cache size */
static const H5FD_file_image_info_t H5F_def_file_image_info_g = H5F_ACS_FILE_IMAGE_INFO_DEF; /* Default file image info and callbacks */
-static const hbool_t H5F_def_core_write_tracking_flag_g = H5F_ACS_CORE_WRITE_TRACKING_FLAG_DEF; /* Default setting for core VFD write tracking */
-static const size_t H5F_def_core_write_tracking_page_size_g = H5F_ACS_CORE_WRITE_TRACKING_PAGE_SIZE_DEF; /* Default core VFD write tracking page size */
static const unsigned H5F_def_metadata_read_attempts_g = H5F_ACS_METADATA_READ_ATTEMPTS_DEF; /* Default setting for the # of metadata read attempts */
static const H5F_object_flush_t H5F_def_object_flush_cb_g = H5F_ACS_OBJECT_FLUSH_CB_DEF; /* Default setting for object flush callback */
static const hbool_t H5F_def_clear_status_flags_g = H5F_ACS_CLEAR_STATUS_FLAGS_DEF; /* Default to clear the superblock status_flags */
@@ -400,6 +448,8 @@ static const hbool_t H5F_def_evict_on_close_flag_g = H5F_ACS_EVICT_ON_CLOSE_FLAG
#ifdef H5_HAVE_PARALLEL
static const H5P_coll_md_read_flag_t H5F_def_coll_md_read_flag_g = H5F_ACS_COLL_MD_READ_FLAG_DEF; /* Default setting for the collective metedata read flag */
static const hbool_t H5F_def_coll_md_write_flag_g = H5F_ACS_COLL_MD_WRITE_FLAG_DEF; /* Default setting for the collective metedata write flag */
+static const MPI_Comm H5F_def_mpi_params_comm_g = H5F_ACS_MPI_PARAMS_COMM_DEF; /* Default MPI communicator */
+static const MPI_Info H5F_def_mpi_params_info_g = H5F_ACS_MPI_PARAMS_INFO_DEF; /* Default MPI info struct */
#endif /* H5_HAVE_PARALLEL */
static const H5AC_cache_image_config_t H5F_def_mdc_initCacheImageCfg_g = H5F_ACS_META_CACHE_INIT_IMAGE_CONFIG_DEF; /* Default metadata cache image settings */
static const size_t H5F_def_page_buf_size_g = H5F_ACS_PAGE_BUFFER_SIZE_DEF; /* Default page buffer size */
@@ -424,6 +474,7 @@ static herr_t
H5P__facc_reg_prop(H5P_genclass_t *pclass)
{
const H5FD_driver_prop_t def_driver_prop = H5F_ACS_FILE_DRV_DEF; /* Default VFL driver ID & info (initialized from a variable) */
+ const H5VL_connector_prop_t def_vol_prop = H5F_ACS_VOL_CONN_DEF; /* Default VOL connector ID & info (initialized from a variable) */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC
@@ -513,9 +564,9 @@ H5P__facc_reg_prop(H5P_genclass_t *pclass)
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
- /* Register the private property of whether convert family to sec2 driver. It's used by h5repart only. */
+ /* Register the private property of whether convert family to a single-file driver. It's used by h5repart only. */
/* (Note: this property should not have an encode/decode callback -QAK) */
- if(H5P__register_real(pclass, H5F_ACS_FAMILY_TO_SEC2_NAME, H5F_ACS_FAMILY_TO_SEC2_SIZE, &H5F_def_family_to_sec2_g,
+ if(H5P__register_real(pclass, H5F_ACS_FAMILY_TO_SINGLE_NAME, H5F_ACS_FAMILY_TO_SINGLE_SIZE, &H5F_def_family_to_single_g,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
@@ -557,18 +608,6 @@ H5P__facc_reg_prop(H5P_genclass_t *pclass)
H5F_ACS_FILE_IMAGE_INFO_DEL, H5F_ACS_FILE_IMAGE_INFO_COPY, H5F_ACS_FILE_IMAGE_INFO_CMP, H5F_ACS_FILE_IMAGE_INFO_CLOSE) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
- /* Register the core VFD backing store write tracking flag */
- if(H5P__register_real(pclass, H5F_ACS_CORE_WRITE_TRACKING_FLAG_NAME, H5F_ACS_CORE_WRITE_TRACKING_FLAG_SIZE, &H5F_def_core_write_tracking_flag_g,
- NULL, NULL, NULL, H5F_ACS_CORE_WRITE_TRACKING_FLAG_ENC, H5F_ACS_CORE_WRITE_TRACKING_FLAG_DEC,
- NULL, NULL, NULL, NULL) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
-
- /* Register the size of the core VFD backing store page size */
- if(H5P__register_real(pclass, H5F_ACS_CORE_WRITE_TRACKING_PAGE_SIZE_NAME, H5F_ACS_CORE_WRITE_TRACKING_PAGE_SIZE_SIZE, &H5F_def_core_write_tracking_page_size_g,
- NULL, NULL, NULL, H5F_ACS_CORE_WRITE_TRACKING_PAGE_SIZE_ENC, H5F_ACS_CORE_WRITE_TRACKING_PAGE_SIZE_DEC,
- NULL, NULL, NULL, NULL) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
-
/* Register the # of read attempts */
if(H5P__register_real(pclass, H5F_ACS_METADATA_READ_ATTEMPTS_NAME, H5F_ACS_METADATA_READ_ATTEMPTS_SIZE, &H5F_def_metadata_read_attempts_g,
NULL, NULL, NULL, H5F_ACS_METADATA_READ_ATTEMPTS_ENC, H5F_ACS_METADATA_READ_ATTEMPTS_DEC,
@@ -630,6 +669,19 @@ H5P__facc_reg_prop(H5P_genclass_t *pclass)
NULL, NULL, NULL, H5F_ACS_COLL_MD_WRITE_FLAG_ENC, H5F_ACS_COLL_MD_WRITE_FLAG_DEC,
NULL, NULL, NULL, NULL) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
+
+ /* Register the MPI communicator */
+ if(H5P__register_real(pclass, H5F_ACS_MPI_PARAMS_COMM_NAME, H5F_ACS_MPI_PARAMS_COMM_SIZE, &H5F_def_mpi_params_comm_g,
+ NULL, H5F_ACS_MPI_PARAMS_COMM_SET, H5F_ACS_MPI_PARAMS_COMM_GET, NULL, NULL,
+ H5F_ACS_MPI_PARAMS_COMM_DEL, H5F_ACS_MPI_PARAMS_COMM_COPY, H5F_ACS_MPI_PARAMS_COMM_CMP, H5F_ACS_MPI_PARAMS_COMM_CLOSE) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
+
+ /* Register the MPI info struct */
+ if(H5P__register_real(pclass, H5F_ACS_MPI_PARAMS_INFO_NAME, H5F_ACS_MPI_PARAMS_INFO_SIZE, &H5F_def_mpi_params_info_g,
+ NULL, H5F_ACS_MPI_PARAMS_INFO_SET, H5F_ACS_MPI_PARAMS_INFO_GET, NULL, NULL,
+ H5F_ACS_MPI_PARAMS_INFO_DEL, H5F_ACS_MPI_PARAMS_INFO_COPY, H5F_ACS_MPI_PARAMS_INFO_CMP, H5F_ACS_MPI_PARAMS_INFO_CLOSE) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
+
#endif /* H5_HAVE_PARALLEL */
/* Register the initial metadata cache image configuration */
@@ -643,11 +695,13 @@ H5P__facc_reg_prop(H5P_genclass_t *pclass)
NULL, NULL, NULL, H5F_ACS_PAGE_BUFFER_SIZE_ENC, H5F_ACS_PAGE_BUFFER_SIZE_DEC,
NULL, NULL, NULL, NULL) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
+
/* Register the size of the page buffer minimum metadata size */
if(H5P__register_real(pclass, H5F_ACS_PAGE_BUFFER_MIN_META_PERC_NAME, H5F_ACS_PAGE_BUFFER_MIN_META_PERC_SIZE, &H5F_def_page_buf_min_meta_perc_g,
NULL, NULL, NULL, H5F_ACS_PAGE_BUFFER_MIN_META_PERC_ENC, H5F_ACS_PAGE_BUFFER_MIN_META_PERC_DEC,
NULL, NULL, NULL, NULL) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
+
/* Register the size of the page buffer minimum raw data size */
if(H5P__register_real(pclass, H5F_ACS_PAGE_BUFFER_MIN_RAW_PERC_NAME, H5F_ACS_PAGE_BUFFER_MIN_RAW_PERC_SIZE, &H5F_def_page_buf_min_raw_perc_g,
NULL, NULL, NULL, H5F_ACS_PAGE_BUFFER_MIN_RAW_PERC_ENC, H5F_ACS_PAGE_BUFFER_MIN_RAW_PERC_DEC,
@@ -660,6 +714,13 @@ H5P__facc_reg_prop(H5P_genclass_t *pclass)
NULL, NULL, NULL, NULL) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
+ /* Register the file VOL connector ID & info */
+ /* (Note: this property should not have an encode/decode callback -QAK) */
+ if(H5P__register_real(pclass, H5F_ACS_VOL_CONN_NAME, H5F_ACS_VOL_CONN_SIZE, &def_vol_prop,
+ H5F_ACS_VOL_CONN_CRT, H5F_ACS_VOL_CONN_SET, H5F_ACS_VOL_CONN_GET, NULL, NULL,
+ H5F_ACS_VOL_CONN_DEL, H5F_ACS_VOL_CONN_COPY, H5F_ACS_VOL_CONN_CMP, H5F_ACS_VOL_CONN_CLOSE) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
+
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5P__facc_reg_prop() */
@@ -1072,7 +1133,7 @@ H5P__file_driver_copy(void *value)
else if(driver->fapl_size > 0) {
if(NULL == (new_pl = H5MM_malloc(driver->fapl_size)))
HGOTO_ERROR(H5E_PLIST, H5E_CANTALLOC, FAIL, "driver info allocation failed")
- HDmemcpy(new_pl, info->driver_info, driver->fapl_size);
+ H5MM_memcpy(new_pl, info->driver_info, driver->fapl_size);
} /* end else-if */
else
HGOTO_ERROR(H5E_PLIST, H5E_UNSUPPORTED, FAIL, "no way to copy driver info")
@@ -2605,7 +2666,7 @@ H5Pset_file_image(hid_t fapl_id, void *buf_ptr, size_t buf_len)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTCOPY, FAIL, "image_memcpy callback failed")
} /* end if */
else
- HDmemcpy(image_info.buffer, buf_ptr, buf_len);
+ H5MM_memcpy(image_info.buffer, buf_ptr, buf_len);
} /* end if */
else
image_info.buffer = NULL;
@@ -2699,7 +2760,7 @@ H5Pget_file_image(hid_t fapl_id, void **buf_ptr_ptr, size_t *buf_len_ptr)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTCOPY, FAIL, "image_memcpy callback failed")
} /* end if */
else
- HDmemcpy(copy_ptr, image_info.buffer, image_info.size);
+ H5MM_memcpy(copy_ptr, image_info.buffer, image_info.size);
} /* end if */
*buf_ptr_ptr = copy_ptr;
@@ -2902,7 +2963,7 @@ H5P__file_image_info_copy(void *value)
HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "image_memcpy callback failed")
} /* end if */
else
- HDmemcpy(info->buffer, old_buffer, info->size);
+ H5MM_memcpy(info->buffer, old_buffer, info->size);
} /* end if */
/* Copy udata if it exists */
@@ -3097,7 +3158,7 @@ H5P__facc_cache_image_config_dec(const void **_pp, void *_value)
HDcompile_assert(sizeof(size_t) <= sizeof(uint64_t));
/* Set property to default value */
- HDmemcpy(config, &H5F_def_mdc_initCacheImageCfg_g, sizeof(H5AC_cache_image_config_t));
+ H5MM_memcpy(config, &H5F_def_mdc_initCacheImageCfg_g, sizeof(H5AC_cache_image_config_t));
/* Decode type sizes */
enc_size = *(*pp)++;
@@ -3488,7 +3549,7 @@ H5P__facc_cache_config_enc(const void *value, void **_pp, size_t *size)
H5_ENCODE_UNSIGNED(*pp, config->close_trace_file);
- HDmemcpy(*pp, (const uint8_t *)(config->trace_file_name), (size_t)(H5AC__MAX_TRACE_FILE_NAME_LEN + 1));
+ H5MM_memcpy(*pp, (const uint8_t *)(config->trace_file_name), (size_t)(H5AC__MAX_TRACE_FILE_NAME_LEN + 1));
*pp += H5AC__MAX_TRACE_FILE_NAME_LEN + 1;
H5_ENCODE_UNSIGNED(*pp, config->evictions_enabled);
@@ -3623,7 +3684,7 @@ H5P__facc_cache_config_dec(const void **_pp, void *_value)
HDcompile_assert(sizeof(size_t) <= sizeof(uint64_t));
/* Set property to default value */
- HDmemcpy(config, &H5F_def_mdc_initCacheCfg_g, sizeof(H5AC_cache_config_t));
+ H5MM_memcpy(config, &H5F_def_mdc_initCacheCfg_g, sizeof(H5AC_cache_config_t));
/* Decode type sizes */
enc_size = *(*pp)++;
@@ -4045,88 +4106,6 @@ H5P__facc_vfd_swmr_config_dec(const void **_pp, void *_value)
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5P__facc_vfd_swmr_config_dec() */
-/*-------------------------------------------------------------------------
- * Function: H5Pset_core_write_tracking
- *
- * Purpose: Enables/disables core VFD write tracking and page
- * aggregation size.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Dana Robinson
- * Tuesday, April 8, 2014
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5Pset_core_write_tracking(hid_t plist_id, hbool_t is_enabled, size_t page_size)
-{
- H5P_genplist_t *plist; /* Property list pointer */
- herr_t ret_value = SUCCEED; /* return value */
-
- FUNC_ENTER_API(FAIL)
- H5TRACE3("e", "ibz", plist_id, is_enabled, page_size);
-
- /* The page size cannot be zero */
- if(page_size == 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "page_size cannot be zero")
-
- /* Get the plist structure */
- if(NULL == (plist = H5P_object_verify(plist_id, H5P_FILE_ACCESS)))
- HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
-
- /* Set values */
- if(H5P_set(plist, H5F_ACS_CORE_WRITE_TRACKING_FLAG_NAME, &is_enabled) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set core VFD write tracking flag")
- if(H5P_set(plist, H5F_ACS_CORE_WRITE_TRACKING_PAGE_SIZE_NAME, &page_size) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set core VFD write tracking page size")
-
-done:
- FUNC_LEAVE_API(ret_value)
-} /* end H5Pset_core_write_tracking() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5Pget_core_write_tracking
- *
- * Purpose: Gets information about core VFD write tracking and page
- * aggregation size.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Dana Robinson
- * Tuesday, April 8, 2014
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5Pget_core_write_tracking(hid_t plist_id, hbool_t *is_enabled, size_t *page_size)
-{
- H5P_genplist_t *plist; /* Property list pointer */
- herr_t ret_value = SUCCEED; /* return value */
-
- FUNC_ENTER_API(FAIL)
- H5TRACE3("e", "i*b*z", plist_id, is_enabled, page_size);
-
- /* Get the plist structure */
- if(NULL == (plist = H5P_object_verify(plist_id, H5P_FILE_ACCESS)))
- HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
-
- /* Get values */
- if(is_enabled) {
- if(H5P_get(plist, H5F_ACS_CORE_WRITE_TRACKING_FLAG_NAME, is_enabled) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get core VFD write tracking flag")
- } /* end if */
-
- if(page_size) {
- if(H5P_get(plist, H5F_ACS_CORE_WRITE_TRACKING_PAGE_SIZE_NAME, page_size) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get core VFD write tracking page size")
- } /* end if */
-
-done:
- FUNC_LEAVE_API(ret_value)
-} /* end H5Pget_core_write_tracking() */
-
/*-------------------------------------------------------------------------
* Function: H5Pset_metadata_read_attempts
@@ -4389,7 +4368,7 @@ H5Pget_mdc_log_options(hid_t plist_id, hbool_t *is_enabled, char *location,
/* Copy log location to output buffer */
if(location_ptr && location)
- HDmemcpy(location, location_ptr, *location_size);
+ H5MM_memcpy(location, location_ptr, *location_size);
/* Get location size, including terminating NULL */
if(location_size) {
@@ -4444,7 +4423,7 @@ H5P_facc_mdc_log_location_enc(const void *value, void **_pp, size_t *size)
/* encode the prefix */
if(NULL != log_location) {
- HDmemcpy(*(char **)pp, log_location, len);
+ H5MM_memcpy(*(char **)pp, log_location, len);
*pp += len;
} /* end if */
} /* end if */
@@ -4730,7 +4709,7 @@ H5P__encode_coll_md_read_flag_t(const void *value, void **_pp, size_t *size)
if(NULL != *pp) {
/* Encode the value */
- HDmemcpy(*pp, coll_md_read_flag, sizeof(H5P_coll_md_read_flag_t));
+ H5MM_memcpy(*pp, coll_md_read_flag, sizeof(H5P_coll_md_read_flag_t));
*pp += sizeof(H5P_coll_md_read_flag_t);
} /* end if */
@@ -4932,6 +4911,468 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5Pget_mpi_params
+ *
+ * Purpose: Gets the MPI communicator and info stored in the fapl.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Dana Robinson
+ * August 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Pget_mpi_params(hid_t plist_id, MPI_Comm *comm, MPI_Info *info)
+{
+ H5P_genplist_t *plist; /* Property list pointer */
+ herr_t ret_value = SUCCEED; /* return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE3("e", "i*Mc*Mi", plist_id, comm, info);
+
+ /* Make sure that the property list is a fapl */
+ if(TRUE != H5P_isa_class(plist_id, H5P_FILE_ACCESS))
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, FAIL, "property list is not a file access plist")
+
+ /* Get the plist structure */
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(plist_id)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
+
+ /* Get the properties */
+ if(H5P_get(plist, H5F_ACS_MPI_PARAMS_COMM_NAME, comm) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get MPI communicator from plist")
+ if(H5P_get(plist, H5F_ACS_MPI_PARAMS_INFO_NAME, info) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get MPI info from plist")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Pget_mpi_params() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Pset_mpi_params
+ *
+ * Purpose: Set the MPI communicator and info
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Dana Robinson
+ * August 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Pset_mpi_params(hid_t plist_id, MPI_Comm comm, MPI_Info info)
+{
+ H5P_genplist_t *plist; /* Property list pointer */
+ herr_t ret_value = SUCCEED; /* return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE3("e", "iMcMi", plist_id, comm, info);
+
+ /* Make sure the MPI communicator is valid */
+ if(MPI_COMM_NULL == comm)
+ HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "not a valid argument")
+
+ /* Make sure that the property list is a fapl */
+ if(TRUE != H5P_isa_class(plist_id, H5P_FILE_ACCESS))
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, FAIL, "property list is not a file access plist")
+
+ /* Get the plist structure */
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(plist_id)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
+
+ /* Set values */
+ if(H5P_set(plist, H5F_ACS_MPI_PARAMS_COMM_NAME, &comm) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set MPI communicator")
+ if(H5P_set(plist, H5F_ACS_MPI_PARAMS_INFO_NAME, &info) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set MPI info object")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Pset_mpi_params() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5P__facc_mpi_comm_set
+ *
+ * Purpose: Copies an MPI comminicator property when it's set for a property list
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5P__facc_mpi_comm_set(hid_t H5_ATTR_UNUSED prop_id, const char H5_ATTR_UNUSED *name,
+ size_t H5_ATTR_UNUSED size, void *value)
+{
+ MPI_Comm *comm = (MPI_Comm *)value;
+ MPI_Comm comm_tmp = MPI_COMM_NULL;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Make a copy of the MPI communicator */
+ if(H5_mpi_comm_dup(*comm, &comm_tmp) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "unable to duplicate MPI communicator")
+
+done:
+ /* Copy the communicator to the in/out parameter */
+ if(ret_value != SUCCEED)
+ *comm = MPI_COMM_NULL;
+ else
+ *comm = comm_tmp;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5P__facc_mpi_comm_set() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5P__facc_mpi_comm_get
+ *
+ * Purpose: Copies an MPI comminicator property when it's retrieved from a property list
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5P__facc_mpi_comm_get(hid_t H5_ATTR_UNUSED prop_id, const char H5_ATTR_UNUSED *name,
+ size_t H5_ATTR_UNUSED size, void *value)
+{
+ MPI_Comm *comm = (MPI_Comm *)value;
+ MPI_Comm comm_tmp = MPI_COMM_NULL;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Make a copy of the MPI communicator */
+ if(H5_mpi_comm_dup(*comm, &comm_tmp) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "unable to duplicate MPI communicator")
+
+done:
+ /* Copy the communicator to the out parameter */
+ if(ret_value != SUCCEED)
+ *comm = MPI_COMM_NULL;
+ else
+ *comm = comm_tmp;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5P__facc_mpi_comm_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5P__facc_mpi_comm_del
+ *
+ * Purpose: Frees an MPI communicator property
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5P__facc_mpi_comm_del(hid_t H5_ATTR_UNUSED prop_id, const char H5_ATTR_UNUSED *name, size_t H5_ATTR_UNUSED size, void *value)
+{
+ MPI_Comm *comm = (MPI_Comm *)value;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Free the MPI communicator */
+ if(H5_mpi_comm_free(comm) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTFREE, FAIL, "unable to free MPI communicator")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5P__facc_mpi_comm_del() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5P__facc_mpi_comm_copy
+ *
+ * Purpose: Copy callback for the MPI communicator property.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5P__facc_mpi_comm_copy(const char H5_ATTR_UNUSED *name, size_t H5_ATTR_UNUSED size, void *value)
+{
+ MPI_Comm *comm = (MPI_Comm *)value;
+ MPI_Comm comm_tmp = MPI_COMM_NULL;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Make a copy of the MPI communicator */
+ if(H5_mpi_comm_dup(*comm, &comm_tmp) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "unable to duplicate MPI communicator")
+
+done:
+ /* Copy the communicator to the in/out parameter */
+ if(ret_value != SUCCEED)
+ *comm = MPI_COMM_NULL;
+ else
+ *comm = comm_tmp;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5P__facc_mpi_comm_copy() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5P__facc_mpi_comm_cmp
+ *
+ * Purpose: Callback routine which is called whenever the MPI
+ * communicator property in the file access property list
+ * is compared.
+ *
+ * Return: positive if VALUE1 is greater than VALUE2, negative if
+ * VALUE2 is greater than VALUE1 and zero if VALUE1 and
+ * VALUE2 are equal.
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+H5P__facc_mpi_comm_cmp(const void *_comm1, const void *_comm2, size_t H5_ATTR_UNUSED size)
+{
+ const MPI_Comm *comm1 = (const MPI_Comm *)_comm1;
+ const MPI_Comm *comm2 = (const MPI_Comm *)_comm2;
+ int ret_value = 0;
+
+ FUNC_ENTER_STATIC
+
+ /* Compare the MPI communicators */
+ if(H5_mpi_comm_cmp(*comm1, *comm2, &ret_value) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, 0, "unable to compare MPI communicator")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5P__facc_mpi_comm_cmp() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5P__facc_mpi_comm_close
+ *
+ * Purpose: Close callback for the MPI communicator property.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5P__facc_mpi_comm_close(const char H5_ATTR_UNUSED *name, size_t H5_ATTR_UNUSED size, void *value)
+{
+ MPI_Comm *comm = (MPI_Comm *)value;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Free the MPI communicator */
+ if(H5_mpi_comm_free(comm) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTFREE, FAIL, "unable to free MPI communicator")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5P__facc_mpi_comm_close() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5P__facc_mpi_info_set
+ *
+ * Purpose: Copies an MPI info object property when it's set for a property list
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5P__facc_mpi_info_set(hid_t H5_ATTR_UNUSED prop_id, const char H5_ATTR_UNUSED *name,
+ size_t H5_ATTR_UNUSED size, void *value)
+{
+ MPI_Info *info = (MPI_Info *)value;
+ MPI_Info info_tmp = MPI_INFO_NULL;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Make a copy of the MPI info object */
+ if(H5_mpi_info_dup(*info, &info_tmp) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "unable to duplicate MPI info object")
+
+done:
+ /* Copy the info object to the in/out parameter */
+ if(ret_value != SUCCEED)
+ *info = MPI_INFO_NULL;
+ else
+ *info = info_tmp;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5P__facc_mpi_info_set() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5P__facc_mpi_info_get
+ *
+ * Purpose: Copies an MPI comminicator property when it's retrieved from a property list
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5P__facc_mpi_info_get(hid_t H5_ATTR_UNUSED prop_id, const char H5_ATTR_UNUSED *name,
+ size_t H5_ATTR_UNUSED size, void *value)
+{
+ MPI_Info *info = (MPI_Info *)value;
+ MPI_Info info_tmp = MPI_INFO_NULL;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Make a copy of the MPI communicator */
+ if(H5_mpi_info_dup(*info, &info_tmp) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "unable to duplicate MPI info object")
+
+done:
+ /* Copy the info object to the out parameter */
+ if(ret_value != SUCCEED)
+ *info = MPI_INFO_NULL;
+ else
+ *info = info_tmp;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5P__facc_mpi_info_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5P__facc_mpi_info_del
+ *
+ * Purpose: Frees an MPI info object property
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5P__facc_mpi_info_del(hid_t H5_ATTR_UNUSED prop_id, const char H5_ATTR_UNUSED *name, size_t H5_ATTR_UNUSED size, void *value)
+{
+ MPI_Info *info = (MPI_Info *)value;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Free the MPI info object */
+ if(H5_mpi_info_free(info) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTFREE, FAIL, "unable to free MPI info object")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5P__facc_mpi_info_del() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5P__facc_mpi_info_copy
+ *
+ * Purpose: Copy callback for the MPI info object property.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5P__facc_mpi_info_copy(const char H5_ATTR_UNUSED *name, size_t H5_ATTR_UNUSED size, void *value)
+{
+ MPI_Info *info = (MPI_Info *)value;
+ MPI_Info info_tmp = MPI_INFO_NULL;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Make a copy of the MPI info object */
+ if(H5_mpi_info_dup(*info, &info_tmp) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "unable to duplicate MPI info object")
+
+done:
+ /* Copy the info object to the in/out parameter */
+ if(ret_value != SUCCEED)
+ *info = MPI_INFO_NULL;
+ else
+ *info = info_tmp;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5P__facc_mpi_info_copy() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5P__facc_mpi_info_cmp
+ *
+ * Purpose: Callback routine which is called whenever the MPI
+ * info object property in the file access property list
+ * is compared.
+ *
+ * Return: positive if VALUE1 is greater than VALUE2, negative if
+ * VALUE2 is greater than VALUE1 and zero if VALUE1 and
+ * VALUE2 are equal.
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+H5P__facc_mpi_info_cmp(const void *_info1, const void *_info2, size_t H5_ATTR_UNUSED size)
+{
+ const MPI_Info *info1 = (const MPI_Info *)_info1;
+ const MPI_Info *info2 = (const MPI_Info *)_info2;
+ int ret_value = 0;
+
+ FUNC_ENTER_STATIC
+
+ /* Compare the MPI info objects */
+ if(H5_mpi_info_cmp(*info1, *info2, &ret_value) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, 0, "unable to compare MPI info objects")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5P__facc_mpi_info_cmp() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5P__facc_mpi_info_close
+ *
+ * Purpose: Close callback for the MPI info object property.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5P__facc_mpi_info_close(const char H5_ATTR_UNUSED *name, size_t H5_ATTR_UNUSED size, void *value)
+{
+ MPI_Info *info = (MPI_Info *)value;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Free the MPI info object */
+ if(H5_mpi_info_free(info) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTFREE, FAIL, "unable to free MPI info object")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5P__facc_mpi_info_close() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5Pget_coll_metadata_write
*
* Purpose: Gets information about collective metadata write mode.
@@ -5058,6 +5499,47 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Pget_page_buffer_size() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5P_set_vol
+ *
+ * Purpose: Set the VOL connector for a file access property list
+ * (PLIST_ID). The VOL properties will
+ * be copied into the property list and the reference count on
+ * the VOL will be incremented.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5P_set_vol(H5P_genplist_t *plist, hid_t vol_id, const void *vol_info)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ if(NULL == H5I_object_verify(vol_id, H5I_VOL))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a VOL connector ID")
+
+ if(TRUE == H5P_isa_class(plist->plist_id, H5P_FILE_ACCESS)) {
+ H5VL_connector_prop_t vol_prop; /* Property for VOL ID & info */
+
+ /* Prepare the VOL connector property */
+ vol_prop.connector_id = vol_id;
+ vol_prop.connector_info = (void *)vol_info;
+
+ /* Set the connector ID & info property */
+ if(H5P_set(plist, H5F_ACS_VOL_CONN_NAME, &vol_prop) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set VOL connector ID & info")
+ } /* end if */
+ else
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list");
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5P_set_vol() */
+
/*-------------------------------------------------------------------------
* Function: H5Pset_vfd_swmr_config
*
@@ -5096,10 +5578,6 @@ H5Pset_vfd_swmr_config(hid_t plist_id, H5F_vfd_swmr_config_t *config_ptr)
if(config_ptr->version != H5F__CURR_VFD_SWMR_CONFIG_VERSION)
HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "Unknown config version")
- /* This field must be >= 0 */
- if(config_ptr->tick_len < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "tick_len must be greater than 0")
-
/* This field must be at least 3 */
if(config_ptr->max_lag < 3 )
HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "max_lag must be at least 3")
@@ -5134,6 +5612,125 @@ done:
} /* H5Pset_vfd_swmr_config() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5P_reset_vol_class
+ *
+ * Purpose: Change the VOL connector for a file access property class.
+ *
+ * Note: The VOL property will be copied into the property list and
+ * the reference count on the previous VOL will _NOT_ be decremented.
+ * The reference count on the new VOL will _NOT_ be incremented.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * March 8, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5P_reset_vol_class(const H5P_genclass_t *pclass, const H5VL_connector_prop_t *vol_prop)
+{
+ H5VL_connector_prop_t old_vol_prop; /* Previous VOL connector property */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Get the connector ID & info property */
+ if(H5P__class_get(pclass, H5F_ACS_VOL_CONN_NAME, &old_vol_prop) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get VOL connector ID & info")
+
+ /* Set the new connector ID & info property */
+ if(H5P__class_set(pclass, H5F_ACS_VOL_CONN_NAME, vol_prop) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set VOL connector ID & info")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5P_set_vol_class() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Pset_vol
+ *
+ * Purpose: Set the file VOL connector (VOL_ID) for a file access
+ * property list (PLIST_ID)
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Pset_vol(hid_t plist_id, hid_t new_vol_id, const void *new_vol_info)
+{
+ H5P_genplist_t *plist; /* Property list pointer */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE3("e", "ii*x", plist_id, new_vol_id, new_vol_info);
+
+ /* Check arguments */
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object_verify(plist_id, H5I_GENPROP_LST)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
+ if(NULL == H5I_object_verify(new_vol_id, H5I_VOL))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file VOL ID")
+
+ /* Set the VOL */
+ if(H5P_set_vol(plist, new_vol_id, new_vol_info) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set VOL")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Pset_vol() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Pget_vol_id
+ *
+ * Purpose: Returns the ID of the current VOL connector.
+ * This ID should be closed with H5VLclose().
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Pget_vol_id(hid_t plist_id, hid_t *vol_id)
+{
+ H5P_genplist_t *plist; /* Property list pointer */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE2("e", "i*i", plist_id, vol_id);
+
+ /* Get property list for ID */
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object_verify(plist_id, H5I_GENPROP_LST)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
+
+ /* Get the current VOL ID */
+ if(TRUE == H5P_isa_class(plist->plist_id, H5P_FILE_ACCESS)) {
+ H5VL_connector_prop_t connector_prop; /* Property for VOL connector ID & info */
+
+ /* Get the connector property */
+ if(H5P_peek(plist, H5F_ACS_VOL_CONN_NAME, &connector_prop) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get VOL connector info")
+
+ /* Increment the VOL ID's ref count */
+ if(H5I_inc_ref(connector_prop.connector_id, TRUE) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTINC, FAIL, "unable to increment ref count on VOL connector ID")
+
+ /* Set the connector ID to return */
+ *vol_id = connector_prop.connector_id;
+ } /* end if */
+ else
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Pget_vol_id() */
+
/*-------------------------------------------------------------------------
* Function: H5Pget_vfd_swmr_config
*
@@ -5169,3 +5766,285 @@ H5Pget_vfd_swmr_config(hid_t plist_id, H5F_vfd_swmr_config_t *config_ptr)
done:
FUNC_LEAVE_API(ret_value)
} /* H5Pget_vfd_swmr_config() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Pget_vol_info
+ *
+ * Purpose: Returns a copy of the VOL info for a connector.
+ * This information should be freed with H5VLfree_connector_info.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Pget_vol_info(hid_t plist_id, void **vol_info)
+{
+ H5P_genplist_t *plist; /* Property list pointer */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE2("e", "i**x", plist_id, vol_info);
+
+ /* Get property list for ID */
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object_verify(plist_id, H5I_GENPROP_LST)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
+
+ /* Get the current VOL info */
+ if(TRUE == H5P_isa_class(plist->plist_id, H5P_FILE_ACCESS)) {
+ void *new_connector_info = NULL; /* Copy of connector info */
+ H5VL_connector_prop_t connector_prop; /* Property for VOL connector ID & info */
+
+ /* Get the connector property */
+ if(H5P_peek(plist, H5F_ACS_VOL_CONN_NAME, &connector_prop) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get VOL connector property")
+
+ /* Copy connector info, if it exists */
+ if(connector_prop.connector_info) {
+ H5VL_class_t *connector; /* Pointer to connector */
+
+ /* Retrieve the connector for the ID */
+ if(NULL == (connector = (H5VL_class_t *)H5I_object(connector_prop.connector_id)))
+ HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a VOL connector ID")
+
+ /* Allocate and copy connector info */
+ if(H5VL_copy_connector_info(connector, &new_connector_info, connector_prop.connector_info) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "connector info copy failed")
+ } /* end if */
+
+ /* Set the connector info */
+ *vol_info = new_connector_info;
+ } /* end if */
+ else
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Pget_vol_info() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5P__facc_vol_create
+ *
+ connectorose: Create callback for the VOL connector ID & info property.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5P__facc_vol_create(const char H5_ATTR_UNUSED *name, size_t H5_ATTR_UNUSED size, void *value)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Make copy of the VOL connector */
+ if(H5VL_conn_copy((H5VL_connector_prop_t *)value) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "can't copy VOL connector")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5P__facc_vol_create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5P__facc_vol_set
+ *
+ * Purpose: Copies a VOL connector property when it's set for a property list
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5P__facc_vol_set(hid_t H5_ATTR_UNUSED prop_id, const char H5_ATTR_UNUSED *name,
+ size_t H5_ATTR_UNUSED size, void *value)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity check */
+ HDassert(value);
+
+ /* Make copy of VOL connector ID & info */
+ if(H5VL_conn_copy((H5VL_connector_prop_t *)value) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "can't copy VOL connector")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5P__facc_vol_set() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5P__facc_vol_get
+ *
+ * Purpose: Copies a VOL connector property when it's retrieved from a property list
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5P__facc_vol_get(hid_t H5_ATTR_UNUSED prop_id, const char H5_ATTR_UNUSED *name,
+ size_t H5_ATTR_UNUSED size, void *value)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity check */
+ HDassert(value);
+
+ /* Make copy of VOL connector */
+ if(H5VL_conn_copy((H5VL_connector_prop_t *)value) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "can't copy VOL connector")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5P__facc_vol_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5P__facc_vol_del
+ *
+ * Purpose: Frees memory used to store the VOL connector ID & info property
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5P__facc_vol_del(hid_t H5_ATTR_UNUSED prop_id, const char H5_ATTR_UNUSED *name, size_t H5_ATTR_UNUSED size, void *value)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Free the VOL connector ID & info */
+ if(H5VL_conn_free((H5VL_connector_prop_t *)value) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTRELEASE, FAIL, "can't release VOL connector")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5P__facc_vol_del() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5P__facc_vol_copy
+ *
+ * Purpose: Copy callback for the VOL connector ID & info property.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5P__facc_vol_copy(const char H5_ATTR_UNUSED *name, size_t H5_ATTR_UNUSED size, void *value)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Make copy of VOL connector */
+ if(H5VL_conn_copy((H5VL_connector_prop_t *)value) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "can't copy VOL connector")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5P__facc_vol_copy() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5P__facc_vol_cmp
+ *
+ * Purpose: Callback routine which is called whenever the VOL connector
+ * ID & info property in the file access property list
+ * is compared.
+ *
+ * Return: positive if VALUE1 is greater than VALUE2, negative if
+ * VALUE2 is greater than VALUE1 and zero if VALUE1 and
+ * VALUE2 are equal.
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+H5P__facc_vol_cmp(const void *_info1, const void *_info2, size_t H5_ATTR_UNUSED size)
+{
+ const H5VL_connector_prop_t *info1 = (const H5VL_connector_prop_t *)_info1; /* Create local aliases for values */
+ const H5VL_connector_prop_t *info2 = (const H5VL_connector_prop_t *)_info2;
+ H5VL_class_t *cls1, *cls2; /* connector class for each property */
+ int cmp_value = 0; /* Value from comparison */
+ herr_t status; /* Status from info comparison */
+ int ret_value = 0; /* Return value */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Sanity check */
+ HDassert(info1);
+ HDassert(info2);
+ HDassert(size == sizeof(H5VL_connector_prop_t));
+
+ /* Compare connectors */
+ if(NULL == (cls1 = (H5VL_class_t *)H5I_object(info1->connector_id)))
+ HGOTO_DONE(-1)
+ if(NULL == (cls2 = (H5VL_class_t *)H5I_object(info2->connector_id)))
+ HGOTO_DONE(1)
+ status = H5VL_cmp_connector_cls(&cmp_value, cls1, cls2);
+ HDassert(status >= 0);
+ if(cmp_value != 0)
+ HGOTO_DONE(cmp_value);
+
+ /* At this point, we should be able to assume that we are dealing with
+ * the same connector class struct (or a copies of the same class struct)
+ */
+
+
+ /* Use one of the classes (cls1) info comparison routines to compare the
+ * info objects
+ */
+ HDassert(cls1->info_cls.cmp == cls2->info_cls.cmp);
+ status = H5VL_cmp_connector_info(cls1, &cmp_value, info1->connector_info, info2->connector_info);
+ HDassert(status >= 0);
+
+ /* Set return value */
+ ret_value = cmp_value;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5P__facc_vol_cmp() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5P__facc_vol_close
+ *
+ * Purpose: Close callback for the VOL connector ID & info property.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5P__facc_vol_close(const char H5_ATTR_UNUSED *name, size_t H5_ATTR_UNUSED size, void *value)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Free the VOL connector */
+ if(H5VL_conn_free((H5VL_connector_prop_t *)value) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTRELEASE, FAIL, "can't release VOL connector")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5P__facc_vol_close() */
+
diff --git a/src/H5Pint.c b/src/H5Pint.c
index 179f883..2911eef 100644
--- a/src/H5Pint.c
+++ b/src/H5Pint.c
@@ -127,62 +127,74 @@ static herr_t H5P__free_del_name_cb(void *item, void H5_ATTR_UNUSED *key, void H
* Predefined property list classes. These are initialized at runtime by
* H5P__init_package() in this source file.
*/
-hid_t H5P_CLS_ROOT_ID_g = FAIL;
+hid_t H5P_CLS_ROOT_ID_g = H5I_INVALID_HID;
H5P_genclass_t *H5P_CLS_ROOT_g = NULL;
-hid_t H5P_CLS_OBJECT_CREATE_ID_g = FAIL;
+hid_t H5P_CLS_OBJECT_CREATE_ID_g = H5I_INVALID_HID;
H5P_genclass_t *H5P_CLS_OBJECT_CREATE_g = NULL;
-hid_t H5P_CLS_FILE_CREATE_ID_g = FAIL;
+hid_t H5P_CLS_FILE_CREATE_ID_g = H5I_INVALID_HID;
H5P_genclass_t *H5P_CLS_FILE_CREATE_g = NULL;
-hid_t H5P_CLS_FILE_ACCESS_ID_g = FAIL;
+hid_t H5P_CLS_FILE_ACCESS_ID_g = H5I_INVALID_HID;
H5P_genclass_t *H5P_CLS_FILE_ACCESS_g = NULL;
-hid_t H5P_CLS_DATASET_CREATE_ID_g = FAIL;
+hid_t H5P_CLS_DATASET_CREATE_ID_g = H5I_INVALID_HID;
H5P_genclass_t *H5P_CLS_DATASET_CREATE_g = NULL;
-hid_t H5P_CLS_DATASET_ACCESS_ID_g = FAIL;
+hid_t H5P_CLS_DATASET_ACCESS_ID_g = H5I_INVALID_HID;
H5P_genclass_t *H5P_CLS_DATASET_ACCESS_g = NULL;
-hid_t H5P_CLS_DATASET_XFER_ID_g = FAIL;
+hid_t H5P_CLS_DATASET_XFER_ID_g = H5I_INVALID_HID;
H5P_genclass_t *H5P_CLS_DATASET_XFER_g = NULL;
-hid_t H5P_CLS_FILE_MOUNT_ID_g = FAIL;
+hid_t H5P_CLS_FILE_MOUNT_ID_g = H5I_INVALID_HID;
H5P_genclass_t *H5P_CLS_FILE_MOUNT_g = NULL;
-hid_t H5P_CLS_GROUP_CREATE_ID_g = FAIL;
+hid_t H5P_CLS_GROUP_CREATE_ID_g = H5I_INVALID_HID;
H5P_genclass_t *H5P_CLS_GROUP_CREATE_g = NULL;
-hid_t H5P_CLS_GROUP_ACCESS_ID_g = FAIL;
+hid_t H5P_CLS_GROUP_ACCESS_ID_g = H5I_INVALID_HID;
H5P_genclass_t *H5P_CLS_GROUP_ACCESS_g = NULL;
-hid_t H5P_CLS_DATATYPE_CREATE_ID_g = FAIL;
+hid_t H5P_CLS_DATATYPE_CREATE_ID_g = H5I_INVALID_HID;
H5P_genclass_t *H5P_CLS_DATATYPE_CREATE_g = NULL;
-hid_t H5P_CLS_DATATYPE_ACCESS_ID_g = FAIL;
+hid_t H5P_CLS_DATATYPE_ACCESS_ID_g = H5I_INVALID_HID;
H5P_genclass_t *H5P_CLS_DATATYPE_ACCESS_g = NULL;
-hid_t H5P_CLS_ATTRIBUTE_CREATE_ID_g = FAIL;
+hid_t H5P_CLS_MAP_CREATE_ID_g = H5I_INVALID_HID;
+H5P_genclass_t *H5P_CLS_MAP_CREATE_g = NULL;
+hid_t H5P_CLS_MAP_ACCESS_ID_g = H5I_INVALID_HID;
+H5P_genclass_t *H5P_CLS_MAP_ACCESS_g = NULL;
+hid_t H5P_CLS_ATTRIBUTE_CREATE_ID_g = H5I_INVALID_HID;
H5P_genclass_t *H5P_CLS_ATTRIBUTE_CREATE_g = NULL;
-hid_t H5P_CLS_ATTRIBUTE_ACCESS_ID_g = FAIL;
+hid_t H5P_CLS_ATTRIBUTE_ACCESS_ID_g = H5I_INVALID_HID;
H5P_genclass_t *H5P_CLS_ATTRIBUTE_ACCESS_g = NULL;
-hid_t H5P_CLS_OBJECT_COPY_ID_g = FAIL;
+hid_t H5P_CLS_OBJECT_COPY_ID_g = H5I_INVALID_HID;
H5P_genclass_t *H5P_CLS_OBJECT_COPY_g = NULL;
-hid_t H5P_CLS_LINK_CREATE_ID_g = FAIL;
+hid_t H5P_CLS_LINK_CREATE_ID_g = H5I_INVALID_HID;
H5P_genclass_t *H5P_CLS_LINK_CREATE_g = NULL;
-hid_t H5P_CLS_LINK_ACCESS_ID_g = FAIL;
+hid_t H5P_CLS_LINK_ACCESS_ID_g = H5I_INVALID_HID;
H5P_genclass_t *H5P_CLS_LINK_ACCESS_g = NULL;
-hid_t H5P_CLS_STRING_CREATE_ID_g = FAIL;
+hid_t H5P_CLS_STRING_CREATE_ID_g = H5I_INVALID_HID;
H5P_genclass_t *H5P_CLS_STRING_CREATE_g = NULL;
+hid_t H5P_CLS_VOL_INITIALIZE_ID_g = H5I_INVALID_HID;
+H5P_genclass_t *H5P_CLS_VOL_INITIALIZE_g = NULL;
+hid_t H5P_CLS_REFERENCE_ACCESS_ID_g = H5I_INVALID_HID;
+H5P_genclass_t *H5P_CLS_REFERENCE_ACCESS_g = NULL;
/*
* Predefined property lists for each predefined class. These are initialized
* at runtime by H5P__init_package() in this source file.
*/
-hid_t H5P_LST_FILE_CREATE_ID_g = FAIL;
-hid_t H5P_LST_FILE_ACCESS_ID_g = FAIL;
-hid_t H5P_LST_DATASET_CREATE_ID_g = FAIL;
-hid_t H5P_LST_DATASET_ACCESS_ID_g = FAIL;
-hid_t H5P_LST_DATASET_XFER_ID_g = FAIL;
-hid_t H5P_LST_FILE_MOUNT_ID_g = FAIL;
-hid_t H5P_LST_GROUP_CREATE_ID_g = FAIL;
-hid_t H5P_LST_GROUP_ACCESS_ID_g = FAIL;
-hid_t H5P_LST_DATATYPE_CREATE_ID_g = FAIL;
-hid_t H5P_LST_DATATYPE_ACCESS_ID_g = FAIL;
-hid_t H5P_LST_ATTRIBUTE_CREATE_ID_g = FAIL;
-hid_t H5P_LST_ATTRIBUTE_ACCESS_ID_g = FAIL;
-hid_t H5P_LST_OBJECT_COPY_ID_g = FAIL;
-hid_t H5P_LST_LINK_CREATE_ID_g = FAIL;
-hid_t H5P_LST_LINK_ACCESS_ID_g = FAIL;
+hid_t H5P_LST_FILE_CREATE_ID_g = H5I_INVALID_HID;
+hid_t H5P_LST_FILE_ACCESS_ID_g = H5I_INVALID_HID;
+hid_t H5P_LST_DATASET_CREATE_ID_g = H5I_INVALID_HID;
+hid_t H5P_LST_DATASET_ACCESS_ID_g = H5I_INVALID_HID;
+hid_t H5P_LST_DATASET_XFER_ID_g = H5I_INVALID_HID;
+hid_t H5P_LST_FILE_MOUNT_ID_g = H5I_INVALID_HID;
+hid_t H5P_LST_GROUP_CREATE_ID_g = H5I_INVALID_HID;
+hid_t H5P_LST_GROUP_ACCESS_ID_g = H5I_INVALID_HID;
+hid_t H5P_LST_DATATYPE_CREATE_ID_g = H5I_INVALID_HID;
+hid_t H5P_LST_DATATYPE_ACCESS_ID_g = H5I_INVALID_HID;
+hid_t H5P_LST_MAP_CREATE_ID_g = H5I_INVALID_HID;
+hid_t H5P_LST_MAP_ACCESS_ID_g = H5I_INVALID_HID;
+hid_t H5P_LST_ATTRIBUTE_CREATE_ID_g = H5I_INVALID_HID;
+hid_t H5P_LST_ATTRIBUTE_ACCESS_ID_g = H5I_INVALID_HID;
+hid_t H5P_LST_OBJECT_COPY_ID_g = H5I_INVALID_HID;
+hid_t H5P_LST_LINK_CREATE_ID_g = H5I_INVALID_HID;
+hid_t H5P_LST_LINK_ACCESS_ID_g = H5I_INVALID_HID;
+hid_t H5P_LST_VOL_INITIALIZE_ID_g = H5I_INVALID_HID;
+hid_t H5P_LST_REFERENCE_ACCESS_ID_g = H5I_INVALID_HID;
/* Root property list class library initialization object */
const H5P_libclass_t H5P_CLS_ROOT[1] = {{
@@ -283,6 +295,45 @@ const H5P_libclass_t H5P_CLS_TACC[1] = {{
NULL /* Class close callback info */
}};
+/* VOL initialization property list class library initialization object */
+/* (move to proper source code file when used for real) */
+const H5P_libclass_t H5P_CLS_VINI[1] = {{
+ "VOL initialization", /* Class name for debugging */
+ H5P_TYPE_VOL_INITIALIZE, /* Class type */
+
+ &H5P_CLS_ROOT_g, /* Parent class */
+ &H5P_CLS_VOL_INITIALIZE_g, /* Pointer to class */
+ &H5P_CLS_VOL_INITIALIZE_ID_g, /* Pointer to class ID */
+ &H5P_LST_VOL_INITIALIZE_ID_g, /* Pointer to default property list ID */
+ NULL, /* Default property registration routine */
+
+ NULL, /* Class creation callback */
+ NULL, /* Class creation callback info */
+ NULL, /* Class copy callback */
+ NULL, /* Class copy callback info */
+ NULL, /* Class close callback */
+ NULL /* Class close callback info */
+}};
+
+/* Reference access property list class library initialization object */
+/* (move to proper source code file when used for real) */
+const H5P_libclass_t H5P_CLS_RACC[1] = {{
+ "reference access", /* Class name for debugging */
+ H5P_TYPE_REFERENCE_ACCESS, /* Class type */
+
+ &H5P_CLS_FILE_ACCESS_g, /* Parent class */
+ &H5P_CLS_REFERENCE_ACCESS_g, /* Pointer to class */
+ &H5P_CLS_REFERENCE_ACCESS_ID_g, /* Pointer to class ID */
+ &H5P_LST_REFERENCE_ACCESS_ID_g, /* Pointer to default property list ID */
+ NULL, /* Default property registration routine*/
+
+ NULL, /* Class creation callback */
+ NULL, /* Class creation callback info */
+ NULL, /* Class copy callback */
+ NULL, /* Class copy callback info */
+ NULL, /* Class close callback */
+ NULL /* Class close callback info */
+}};
/* Library property list classes defined in other code modules */
/* (And not present in src/H5Pprivate.h) */
@@ -291,6 +342,7 @@ H5_DLLVAR const H5P_libclass_t H5P_CLS_STRCRT[1]; /* String create */
H5_DLLVAR const H5P_libclass_t H5P_CLS_GCRT[1]; /* Group create */
H5_DLLVAR const H5P_libclass_t H5P_CLS_FCRT[1]; /* File creation */
H5_DLLVAR const H5P_libclass_t H5P_CLS_DCRT[1]; /* Dataset creation */
+H5_DLLVAR const H5P_libclass_t H5P_CLS_MCRT[1]; /* Map creation */
H5_DLLVAR const H5P_libclass_t H5P_CLS_DXFR[1]; /* Data transfer */
H5_DLLVAR const H5P_libclass_t H5P_CLS_FMNT[1]; /* File mount */
H5_DLLVAR const H5P_libclass_t H5P_CLS_ACRT[1]; /* Attribute creation */
@@ -329,9 +381,13 @@ static H5P_libclass_t const * const init_class[] = {
H5P_CLS_FMNT, /* File mount */
H5P_CLS_TCRT, /* Datatype creation */
H5P_CLS_TACC, /* Datatype access */
+ H5P_CLS_MCRT, /* Map creation */
+ H5P_CLS_MACC, /* Map access */
H5P_CLS_ACRT, /* Attribute creation */
H5P_CLS_AACC, /* Attribute access */
- H5P_CLS_LCRT /* Link creation */
+ H5P_CLS_LCRT, /* Link creation */
+ H5P_CLS_VINI, /* VOL initialization */
+ H5P_CLS_RACC /* Reference access */
};
/* Declare a free list to manage the H5P_genclass_t struct */
@@ -406,6 +462,9 @@ H5P__init_package(void)
FUNC_ENTER_PACKAGE
+ /* Sanity check */
+ HDcompile_assert(H5P_TYPE_REFERENCE_ACCESS == (H5P_TYPE_MAX_TYPE - 1));
+
/*
* Initialize the Generic Property class & object groups.
*/
@@ -415,8 +474,8 @@ H5P__init_package(void)
HGOTO_ERROR(H5E_ATOM, H5E_CANTINIT, FAIL, "unable to initialize ID group")
/* Repeatedly pass over the list of property list classes for the library,
- * initializing each class if it's parent class is initialized, until no
- * more progress is made.
+ * initializing each class if its parent class is initialized, until no
+ * more progress is made.
*/
tot_init = 0;
do {
@@ -520,12 +579,16 @@ H5P_term_package(void)
H5P_LST_GROUP_ACCESS_ID_g =
H5P_LST_DATATYPE_CREATE_ID_g =
H5P_LST_DATATYPE_ACCESS_ID_g =
+ H5P_LST_MAP_CREATE_ID_g =
+ H5P_LST_MAP_ACCESS_ID_g =
H5P_LST_ATTRIBUTE_CREATE_ID_g =
H5P_LST_ATTRIBUTE_ACCESS_ID_g =
H5P_LST_OBJECT_COPY_ID_g =
H5P_LST_LINK_CREATE_ID_g =
H5P_LST_LINK_ACCESS_ID_g =
- H5P_LST_FILE_MOUNT_ID_g = (-1);
+ H5P_LST_VOL_INITIALIZE_ID_g =
+ H5P_LST_REFERENCE_ACCESS_ID_g =
+ H5P_LST_FILE_MOUNT_ID_g = H5I_INVALID_HID;
} /* end if */
} /* end if */
@@ -546,12 +609,16 @@ H5P_term_package(void)
H5P_CLS_GROUP_ACCESS_g =
H5P_CLS_DATATYPE_CREATE_g =
H5P_CLS_DATATYPE_ACCESS_g =
+ H5P_CLS_MAP_CREATE_g =
+ H5P_CLS_MAP_ACCESS_g =
H5P_CLS_STRING_CREATE_g =
H5P_CLS_ATTRIBUTE_CREATE_g =
H5P_CLS_ATTRIBUTE_ACCESS_g =
H5P_CLS_OBJECT_COPY_g =
H5P_CLS_LINK_CREATE_g =
H5P_CLS_LINK_ACCESS_g =
+ H5P_CLS_VOL_INITIALIZE_g =
+ H5P_CLS_REFERENCE_ACCESS_g =
H5P_CLS_FILE_MOUNT_g = NULL;
H5P_CLS_ROOT_ID_g =
@@ -565,13 +632,17 @@ H5P_term_package(void)
H5P_CLS_GROUP_ACCESS_ID_g =
H5P_CLS_DATATYPE_CREATE_ID_g =
H5P_CLS_DATATYPE_ACCESS_ID_g =
+ H5P_CLS_MAP_CREATE_ID_g =
+ H5P_CLS_MAP_ACCESS_ID_g =
H5P_CLS_STRING_CREATE_ID_g =
H5P_CLS_ATTRIBUTE_CREATE_ID_g =
H5P_CLS_ATTRIBUTE_ACCESS_ID_g =
H5P_CLS_OBJECT_COPY_ID_g =
H5P_CLS_LINK_CREATE_ID_g =
H5P_CLS_LINK_ACCESS_ID_g =
- H5P_CLS_FILE_MOUNT_ID_g = (-1);
+ H5P_CLS_VOL_INITIALIZE_ID_g =
+ H5P_CLS_REFERENCE_ACCESS_ID_g =
+ H5P_CLS_FILE_MOUNT_ID_g = H5I_INVALID_HID;
} /* end if */
} /* end if */
@@ -631,7 +702,7 @@ H5P__do_prop_cb1(H5SL_t *slist, H5P_genprop_t *prop, H5P_prp_cb1_t cb)
/* Allocate space for a temporary copy of the property value */
if(NULL == (tmp_value = H5MM_malloc(prop->size)))
HGOTO_ERROR(H5E_PLIST, H5E_CANTALLOC, FAIL, "memory allocation failed for temporary property value")
- HDmemcpy(tmp_value, prop->value, prop->size);
+ H5MM_memcpy(tmp_value, prop->value, prop->size);
/* Call "type 1" callback ('create', 'copy' or 'close') */
if(cb(prop->name, prop->size, tmp_value) < 0)
@@ -642,7 +713,7 @@ H5P__do_prop_cb1(H5SL_t *slist, H5P_genprop_t *prop, H5P_prp_cb1_t cb)
HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "Can't copy property")
/* Copy the changed value into the new property */
- HDmemcpy(pcopy->value, tmp_value, prop->size);
+ H5MM_memcpy(pcopy->value, tmp_value, prop->size);
/* Insert the changed property into the property list */
if(H5P__add_prop(slist, pcopy) < 0)
@@ -990,7 +1061,7 @@ H5P__dup_prop(H5P_genprop_t *oprop, H5P_prop_within_t type)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* Copy basic property information */
- HDmemcpy(prop, oprop, sizeof(H5P_genprop_t));
+ H5MM_memcpy(prop, oprop, sizeof(H5P_genprop_t));
/* Check if we should duplicate the name or share it */
@@ -1030,7 +1101,7 @@ H5P__dup_prop(H5P_genprop_t *oprop, H5P_prop_within_t type)
HDassert(prop->size > 0);
if(NULL == (prop->value = H5MM_malloc(prop->size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- HDmemcpy(prop->value, oprop->value, prop->size);
+ H5MM_memcpy(prop->value, oprop->value, prop->size);
} /* end if */
/* Set return value */
@@ -1117,7 +1188,7 @@ H5P__create_prop(const char *name, size_t size, H5P_prop_within_t type,
if(value != NULL) {
if(NULL == (prop->value = H5MM_malloc (prop->size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- HDmemcpy(prop->value, value, prop->size);
+ H5MM_memcpy(prop->value, value, prop->size);
} /* end if */
else
prop->value = NULL;
@@ -2727,7 +2798,7 @@ H5P__poke_plist_cb(H5P_genplist_t *plist, const char *name, H5P_genprop_t *prop,
HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "property has zero size")
/* Overwrite value in property */
- HDmemcpy(prop->value, udata->value, prop->size);
+ H5MM_memcpy(prop->value, udata->value, prop->size);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -2779,7 +2850,7 @@ H5P__poke_pclass_cb(H5P_genplist_t *plist, const char *name, H5P_genprop_t *prop
if(NULL == (pcopy = H5P__dup_prop(prop, H5P_PROP_WITHIN_LIST)))
HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "Can't copy property")
- HDmemcpy(pcopy->value, udata->value, pcopy->size);
+ H5MM_memcpy(pcopy->value, udata->value, pcopy->size);
/* Insert the changed property into the property list */
if(H5P__add_prop(plist->props, pcopy) < 0)
@@ -2888,7 +2959,7 @@ H5P__set_plist_cb(H5P_genplist_t *plist, const char *name, H5P_genprop_t *prop,
/* Make a copy of the current value, in case the callback fails */
if(NULL == (tmp_value = H5MM_malloc(prop->size)))
HGOTO_ERROR(H5E_PLIST, H5E_CANTALLOC, FAIL, "memory allocation failed temporary property value")
- HDmemcpy(tmp_value, udata->value, prop->size);
+ H5MM_memcpy(tmp_value, udata->value, prop->size);
/* Call user's callback */
if((*(prop->set))(plist->plist_id, name, prop->size, tmp_value) < 0)
@@ -2909,7 +2980,7 @@ H5P__set_plist_cb(H5P_genplist_t *plist, const char *name, H5P_genprop_t *prop,
} /* end if */
/* Copy new [possibly unchanged] value into property value */
- HDmemcpy(prop->value, prp_value, prop->size);
+ H5MM_memcpy(prop->value, prp_value, prop->size);
done:
/* Free the temporary value buffer */
@@ -2968,7 +3039,7 @@ H5P__set_pclass_cb(H5P_genplist_t *plist, const char *name, H5P_genprop_t *prop,
/* Make a copy of the current value, in case the callback fails */
if(NULL == (tmp_value = H5MM_malloc(prop->size)))
HGOTO_ERROR(H5E_PLIST, H5E_CANTALLOC, FAIL, "memory allocation failed temporary property value")
- HDmemcpy(tmp_value, udata->value, prop->size);
+ H5MM_memcpy(tmp_value, udata->value, prop->size);
/* Call user's callback */
if((*(prop->set))(plist->plist_id, name, prop->size, tmp_value) < 0)
@@ -2985,7 +3056,7 @@ H5P__set_pclass_cb(H5P_genplist_t *plist, const char *name, H5P_genprop_t *prop,
if(NULL == (pcopy = H5P__dup_prop(prop, H5P_PROP_WITHIN_LIST)))
HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "Can't copy property")
- HDmemcpy(pcopy->value, prp_value, pcopy->size);
+ H5MM_memcpy(pcopy->value, prp_value, pcopy->size);
/* Insert the changed property into the property list */
if(H5P__add_prop(plist->props, pcopy) < 0)
@@ -3061,6 +3132,116 @@ done:
/*--------------------------------------------------------------------------
NAME
+ H5P__class_get
+ PURPOSE
+ Internal routine to get a property's value from a property class.
+ USAGE
+ herr_t H5P__class_get(pclass, name, value)
+ const H5P_genclass_t *pclass; IN: Property class to find property in
+ const char *name; IN: Name of property to get
+ void *value; IN: Pointer to the value for the property
+ RETURNS
+ Returns non-negative on success, negative on failure.
+ DESCRIPTION
+ Gets the current value for a property in a property class. The property
+ name must exist or this routine will fail.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ The 'get' callback routine registered for this property will _NOT_ be
+ called, this routine is designed for internal library use only!
+
+ This routine may not be called for zero-sized properties and will
+ return an error in that case.
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5P__class_get(const H5P_genclass_t *pclass, const char *name, void *value)
+{
+ H5P_genprop_t *prop; /* Temporary property pointer */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Sanity check */
+ HDassert(pclass);
+ HDassert(name);
+ HDassert(value);
+
+ /* Find property in list */
+ if(NULL == (prop = (H5P_genprop_t *)H5SL_search(pclass->props, name)))
+ HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "property doesn't exist")
+
+ /* Check for property size >0 */
+ if(0 == prop->size)
+ HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "property has zero size")
+
+ /* Copy the property value */
+ H5MM_memcpy(value, prop->value, prop->size);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5P__class_get() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5P__class_set
+ PURPOSE
+ Internal routine to set a property's value in a property class.
+ USAGE
+ herr_t H5P__class_set(pclass, name, value)
+ const H5P_genclass_t *pclass; IN: Property class to find property in
+ const char *name; IN: Name of property to set
+ const void *value; IN: Pointer to the value for the property
+ RETURNS
+ Returns non-negative on success, negative on failure.
+ DESCRIPTION
+ Sets a new value for a property in a property class. The property name
+ must exist or this routine will fail.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ The 'set' callback routine registered for this property will _NOT_ be
+ called, this routine is designed for internal library use only!
+
+ This routine may not be called for zero-sized properties and will
+ return an error in that case.
+
+ The previous value is overwritten, not released in any way.
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5P__class_set(const H5P_genclass_t *pclass, const char *name, const void *value)
+{
+ H5P_genprop_t *prop; /* Temporary property pointer */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Sanity check */
+ HDassert(pclass);
+ HDassert(name);
+ HDassert(value);
+
+ /* Find property in list */
+ if(NULL == (prop = (H5P_genprop_t *)H5SL_search(pclass->props, name)))
+ HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "property doesn't exist")
+
+ /* Check for property size >0 */
+ if(0 == prop->size)
+ HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "property has zero size")
+
+ /* Copy the property value */
+ H5MM_memcpy(prop->value, value, prop->size);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5P__class_set() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
H5P_exist_plist
PURPOSE
Internal routine to query the existance of a property in a property list.
@@ -4234,7 +4415,7 @@ H5P__peek_cb(H5P_genplist_t *plist, const char *name, H5P_genprop_t *prop,
HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "property has zero size")
/* Make a (shallow) copy of the value */
- HDmemcpy(udata->value, prop->value, prop->size);
+ H5MM_memcpy(udata->value, prop->value, prop->size);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -4334,18 +4515,18 @@ H5P__get_cb(H5P_genplist_t *plist, const char *name, H5P_genprop_t *prop,
/* Make a copy of the current value, in case the callback fails */
if(NULL == (tmp_value = H5MM_malloc(prop->size)))
HGOTO_ERROR(H5E_PLIST, H5E_CANTALLOC, FAIL, "memory allocation failed temporary property value")
- HDmemcpy(tmp_value, prop->value, prop->size);
+ H5MM_memcpy(tmp_value, prop->value, prop->size);
/* Call user's callback */
if((*(prop->get))(plist->plist_id, name, prop->size, tmp_value) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "can't set property value")
/* Copy new [possibly unchanged] value into return value */
- HDmemcpy(udata->value, tmp_value, prop->size);
+ H5MM_memcpy(udata->value, tmp_value, prop->size);
} /* end if */
/* No 'get' callback, just copy value */
else
- HDmemcpy(udata->value, prop->value, prop->size);
+ H5MM_memcpy(udata->value, prop->value, prop->size);
done:
/* Free the temporary value buffer */
@@ -4518,7 +4699,7 @@ H5P__del_pclass_cb(H5P_genplist_t *plist, const char *name, H5P_genprop_t *prop,
/* Allocate space for a temporary copy of the property value */
if(NULL == (tmp_value = H5MM_malloc(prop->size)))
HGOTO_ERROR(H5E_PLIST, H5E_CANTALLOC, FAIL, "memory allocation failed for temporary property value")
- HDmemcpy(tmp_value, prop->value, prop->size);
+ H5MM_memcpy(tmp_value, prop->value, prop->size);
/* Call user's callback */
if((*(prop->del))(plist->plist_id, name, prop->size, tmp_value) < 0)
@@ -4967,7 +5148,7 @@ H5P_close(void *_plist)
/* Allocate space for a temporary copy of the property value */
if(NULL==(tmp_value=H5MM_malloc(tmp->size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for temporary property value")
- HDmemcpy(tmp_value,tmp->value,tmp->size);
+ H5MM_memcpy(tmp_value,tmp->value,tmp->size);
/* Call the 'close' callback */
(tmp->close)(tmp->name,tmp->size,tmp_value);
@@ -5098,7 +5279,7 @@ H5P__get_class_path(H5P_genclass_t *pclass)
/* Allocate enough space for the parent class's path, plus the '/'
* separator, this class's name and the string terminator
*/
- ret_str_len = HDstrlen(par_path) + 1 + HDstrlen(pclass->name) + 1;
+ ret_str_len = HDstrlen(par_path) + HDstrlen(pclass->name) + 1 + 3; /* Extra "+3" to quiet GCC warning - 2019/07/05, QAK */
if(NULL == (ret_value = (char *)H5MM_malloc(ret_str_len)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for class name")
@@ -5298,8 +5479,8 @@ H5P__new_plist_of_type(H5P_plist_type_t type)
FUNC_ENTER_PACKAGE
/* Sanity checks */
- HDcompile_assert(H5P_TYPE_ATTRIBUTE_ACCESS == (H5P_TYPE_MAX_TYPE - 1));
- HDassert(type >= H5P_TYPE_USER && type <= H5P_TYPE_LINK_ACCESS);
+ HDcompile_assert(H5P_TYPE_REFERENCE_ACCESS == (H5P_TYPE_MAX_TYPE - 1));
+ HDassert(type >= H5P_TYPE_USER && type <= H5P_TYPE_REFERENCE_ACCESS);
/* Check arguments */
if(type == H5P_TYPE_USER)
@@ -5353,6 +5534,14 @@ H5P__new_plist_of_type(H5P_plist_type_t type)
class_id = H5P_CLS_DATATYPE_ACCESS_ID_g;
break;
+ case H5P_TYPE_MAP_CREATE:
+ class_id = H5P_CLS_MAP_CREATE_ID_g;
+ break;
+
+ case H5P_TYPE_MAP_ACCESS:
+ class_id = H5P_CLS_MAP_ACCESS_ID_g;
+ break;
+
case H5P_TYPE_STRING_CREATE:
class_id = H5P_CLS_STRING_CREATE_ID_g;
break;
@@ -5377,6 +5566,14 @@ H5P__new_plist_of_type(H5P_plist_type_t type)
class_id = H5P_CLS_LINK_ACCESS_ID_g;
break;
+ case H5P_TYPE_VOL_INITIALIZE:
+ class_id = H5P_CLS_VOL_INITIALIZE_ID_g;
+ break;
+
+ case H5P_TYPE_REFERENCE_ACCESS:
+ class_id = H5P_CLS_REFERENCE_ACCESS_ID_g;
+ break;
+
case H5P_TYPE_USER: /* shut compiler warnings up */
case H5P_TYPE_ROOT:
case H5P_TYPE_MAX_TYPE:
@@ -5452,3 +5649,22 @@ H5P_get_class(const H5P_genplist_t *plist)
FUNC_LEAVE_NOAPI(plist->pclass)
} /* end H5P_get_class() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5P_ignore_cmp
+ *
+ * Purpose: Callback routine to ignore comparing property values.
+ *
+ * Return: zero
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+H5P_ignore_cmp(const void H5_ATTR_UNUSED *val1, const void H5_ATTR_UNUSED *val2,
+ size_t H5_ATTR_UNUSED size)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ FUNC_LEAVE_NOAPI(0)
+} /* end H5P_ignore_cmp() */
+
diff --git a/src/H5Plapl.c b/src/H5Plapl.c
index bedeed9..7a7cc23 100644
--- a/src/H5Plapl.c
+++ b/src/H5Plapl.c
@@ -715,7 +715,7 @@ H5P__lacc_elink_pref_enc(const void *value, void **_pp, size_t *size)
/* encode the prefix */
if(NULL != elink_pref) {
- HDmemcpy(*(char **)pp, elink_pref, len);
+ H5MM_memcpy(*(char **)pp, elink_pref, len);
*pp += len;
} /* end if */
} /* end if */
diff --git a/src/H5Plcpl.c b/src/H5Plcpl.c
index 1d45bed..ace853a 100644
--- a/src/H5Plcpl.c
+++ b/src/H5Plcpl.c
@@ -48,6 +48,7 @@
#define H5L_CRT_INTERMEDIATE_GROUP_ENC H5P__encode_unsigned
#define H5L_CRT_INTERMEDIATE_GROUP_DEC H5P__decode_unsigned
+
/******************/
/* Local Typedefs */
/******************/
diff --git a/src/H5Pmapl.c b/src/H5Pmapl.c
new file mode 100644
index 0000000..fe5be0f
--- /dev/null
+++ b/src/H5Pmapl.c
@@ -0,0 +1,217 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Purpose: Map access property list class routines
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#include "H5Pmodule.h" /* This source code file is part of the H5P module */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Mprivate.h" /* Maps */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Iprivate.h" /* IDs */
+#include "H5Ppkg.h" /* Property lists */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+/* ========= Map Access properties ============ */
+/* Definitions for key prefetch size */
+#define H5M_ACS_KEY_PREFETCH_SIZE_SIZE sizeof(size_t)
+#define H5M_ACS_KEY_PREFETCH_SIZE_DEF (size_t)(16 * 1024)
+#define H5M_ACS_KEY_PREFETCH_SIZE_ENC H5P__encode_size_t
+#define H5M_ACS_KEY_PREFETCH_SIZE_DEC H5P__decode_size_t
+/* Definition for key prefetch buffer size */
+#define H5M_ACS_KEY_ALLOC_SIZE_SIZE sizeof(size_t)
+#define H5M_ACS_KEY_ALLOC_SIZE_DEF (size_t)(1024 * 1024)
+#define H5M_ACS_KEY_ALLOC_SIZE_ENC H5P__encode_size_t
+#define H5M_ACS_KEY_ALLOC_SIZE_DEC H5P__decode_size_t
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+/* Property class callbacks */
+static herr_t H5P__macc_reg_prop(H5P_genclass_t *pclass);
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+/* Map access property list class library initialization object */
+const H5P_libclass_t H5P_CLS_MACC[1] = {{
+ "map access", /* Class name for debugging */
+ H5P_TYPE_MAP_ACCESS, /* Class type */
+
+ &H5P_CLS_LINK_ACCESS_g, /* Parent class */
+ &H5P_CLS_MAP_ACCESS_g, /* Pointer to class */
+ &H5P_CLS_MAP_ACCESS_ID_g, /* Pointer to class ID */
+ &H5P_LST_MAP_ACCESS_ID_g, /* Pointer to default property list ID */
+ H5P__macc_reg_prop, /* Default property registration routine */
+
+ NULL, /* Class creation callback */
+ NULL, /* Class creation callback info */
+ NULL, /* Class copy callback */
+ NULL, /* Class copy callback info */
+ NULL, /* Class close callback */
+ NULL /* Class close callback info */
+}};
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5P__macc_reg_prop
+ *
+ * Purpose: Register the map access property list class's
+ * properties
+ *
+ * Return: Non-negative on success/Negative on failure
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5P__macc_reg_prop(H5P_genclass_t *pclass)
+{
+ size_t key_prefetch_size = H5M_ACS_KEY_PREFETCH_SIZE_DEF; /* Default key prefetch size for iteration */
+ size_t key_alloc_size = H5M_ACS_KEY_ALLOC_SIZE_DEF; /* Default key prefetch allocation size for iteration */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Register the key prefetch size for iteration */
+ if(H5P__register_real(pclass, H5M_ACS_KEY_PREFETCH_SIZE_NAME, H5M_ACS_KEY_PREFETCH_SIZE_SIZE, &key_prefetch_size,
+ NULL, NULL, NULL, H5M_ACS_KEY_PREFETCH_SIZE_ENC, H5M_ACS_KEY_PREFETCH_SIZE_DEC, NULL, NULL, NULL, NULL) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
+
+ /* Register the key prefetch allocation size for iteration */
+ if(H5P__register_real(pclass, H5M_ACS_KEY_ALLOC_SIZE_NAME, H5M_ACS_KEY_ALLOC_SIZE_SIZE, &key_alloc_size,
+ NULL, NULL, NULL, H5M_ACS_KEY_ALLOC_SIZE_ENC, H5M_ACS_KEY_ALLOC_SIZE_DEC, NULL, NULL, NULL, NULL) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5P__macc_reg_prop() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Pset_map_iterate_hints
+ *
+ * Purpose: H5Pset_map_iterate_hints adjusts the behavior of
+ * H5Miterate when prefetching keys for iteration. The
+ * KEY_PREFETCH_SIZE parameter specifies the number of keys
+ * to prefetch at a time during iteration. The KEY_ALLOC_SIZE
+ * parameter specifies the initial size of the buffer
+ * allocated to hold these prefetched keys. If this buffer is
+ * too small it will be reallocated to a larger size, though
+ * this may result in an additional I/O.
+ *
+ * Move to DAOS VOL code? DSINC
+ *
+ * Return: Non-negative on success/Negative on failure
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Pset_map_iterate_hints(hid_t mapl_id, size_t key_prefetch_size, size_t key_alloc_size)
+{
+ H5P_genplist_t *plist; /* Property list pointer */
+ herr_t ret_value = SUCCEED; /* return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE3("e", "izz", mapl_id, key_prefetch_size, key_alloc_size);
+
+ /* Get the plist structure */
+ if(NULL == (plist = H5P_object_verify(mapl_id, H5P_MAP_ACCESS)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID");
+
+ /* Set sizes */
+ if(H5P_set(plist, H5M_ACS_KEY_PREFETCH_SIZE_NAME, &key_prefetch_size) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET,FAIL, "can't set key prefetch size");
+ if(H5P_set(plist, H5M_ACS_KEY_ALLOC_SIZE_NAME, &key_alloc_size) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET,FAIL, "can't set key allocation size");
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Pset_map_iterate_hints() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Pget_map_iterate_hints
+ *
+ * Purpose: Returns the map iterate hints, KEY_PREFETCH_SIZE and
+ * KEY_ALLOC_SIZE, as set by H5Pset_map_iterate_hints.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Pget_map_iterate_hints(hid_t mapl_id, size_t *key_prefetch_size, size_t *key_alloc_size)
+{
+ H5P_genplist_t *plist; /* Property list pointer */
+ herr_t ret_value = SUCCEED; /* return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE3("e", "i*z*z", mapl_id, key_prefetch_size, key_alloc_size);
+
+ /* Get the plist structure */
+ if(NULL == (plist = H5P_object_verify(mapl_id, H5P_MAP_ACCESS)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID");
+
+ /* Get the properties */
+ if(key_prefetch_size) {
+ if(H5P_get(plist, H5M_ACS_KEY_PREFETCH_SIZE_NAME, key_prefetch_size) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get key prefetch size");
+ } /* end if */
+ if(key_alloc_size) {
+ if(H5P_get(plist, H5M_ACS_KEY_ALLOC_SIZE_NAME, key_alloc_size) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get key allocation size");
+ } /* end if */
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Pget_map_iterate_hints() */
+
diff --git a/src/H5Pmcpl.c b/src/H5Pmcpl.c
new file mode 100644
index 0000000..41a6659
--- /dev/null
+++ b/src/H5Pmcpl.c
@@ -0,0 +1,115 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5Pmcpl.c
+ *
+ * Purpose: Map creation property list class routines
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#include "H5Pmodule.h" /* This source code file is part of the H5P module */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Mprivate.h" /* Maps */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Iprivate.h" /* IDs */
+#include "H5Ppkg.h" /* Property lists */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+/* Property class callbacks */
+static herr_t H5P__mcrt_reg_prop(H5P_genclass_t *pclass);
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+/* Map create property list class library initialization object */
+const H5P_libclass_t H5P_CLS_MCRT[1] = {{
+ "map create", /* Class name for debugging */
+ H5P_TYPE_MAP_CREATE, /* Class type */
+
+ &H5P_CLS_OBJECT_CREATE_g, /* Parent class */
+ &H5P_CLS_MAP_CREATE_g, /* Pointer to class */
+ &H5P_CLS_MAP_CREATE_ID_g, /* Pointer to class ID */
+ &H5P_LST_MAP_CREATE_ID_g, /* Pointer to default property list ID */
+ H5P__mcrt_reg_prop, /* Default property registration routine */
+
+ NULL, /* Class creation callback */
+ NULL, /* Class creation callback info */
+ NULL, /* Class copy callback */
+ NULL, /* Class copy callback info */
+ NULL, /* Class close callback */
+ NULL /* Class close callback info */
+}};
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/***************************/
+/* Local Private Variables */
+/***************************/
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5P__mcrt_reg_prop
+ *
+ * Purpose: Register the map creation property list class's properties
+ *
+ * Return: Non-negative on success/Negative on failure
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5P__mcrt_reg_prop(H5P_genclass_t H5_ATTR_UNUSED *pclass)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5P__mcrt_reg_prop() */
+
diff --git a/src/H5Pocpl.c b/src/H5Pocpl.c
index c2bf6cb..a60c593 100644
--- a/src/H5Pocpl.c
+++ b/src/H5Pocpl.c
@@ -1501,7 +1501,7 @@ H5P__ocrt_pipeline_enc(const void *value, void **_pp, size_t *size)
*(*pp)++ = (uint8_t)TRUE;
/* encode filter name */
- HDmemcpy(*pp, (uint8_t *)(pline->filter[u].name), H5Z_COMMON_NAME_LEN);
+ H5MM_memcpy(*pp, (uint8_t *)(pline->filter[u].name), H5Z_COMMON_NAME_LEN);
*pp += H5Z_COMMON_NAME_LEN;
} /* end if */
else
diff --git a/src/H5Pocpypl.c b/src/H5Pocpypl.c
index 666a945..2dc92f9 100644
--- a/src/H5Pocpypl.c
+++ b/src/H5Pocpypl.c
@@ -384,7 +384,7 @@ H5P__ocpy_merge_comm_dt_list_enc(const void *value, void **_pp, size_t *size)
/* Encode merge committed dtype list */
if(*pp) {
- HDmemcpy(*(char **)pp, dt_list->path, len);
+ H5MM_memcpy(*(char **)pp, dt_list->path, len);
*pp += len;
} /* end if */
diff --git a/src/H5Ppkg.h b/src/H5Ppkg.h
index 13f3b13..c8e5e98 100644
--- a/src/H5Ppkg.h
+++ b/src/H5Ppkg.h
@@ -151,6 +151,10 @@ H5_DLL herr_t H5P__register(H5P_genclass_t **pclass, const char *name, size_t si
H5P_prp_close_func_t prp_close);
H5_DLL herr_t H5P__add_prop(H5SL_t *props, H5P_genprop_t *prop);
H5_DLL herr_t H5P__access_class(H5P_genclass_t *pclass, H5P_class_mod_t mod);
+H5_DLL herr_t H5P__class_get(const H5P_genclass_t *pclass, const char *name,
+ void *value);
+H5_DLL herr_t H5P__class_set(const H5P_genclass_t *pclass, const char *name,
+ const void *value);
H5_DLL htri_t H5P__exist_pclass(H5P_genclass_t *pclass, const char *name);
H5_DLL herr_t H5P__get_size_plist(const H5P_genplist_t *plist, const char *name,
size_t *size);
diff --git a/src/H5Pprivate.h b/src/H5Pprivate.h
index 7792671..f7253a0 100644
--- a/src/H5Pprivate.h
+++ b/src/H5Pprivate.h
@@ -78,6 +78,10 @@ typedef enum H5P_plist_type_t {
H5P_TYPE_LINK_CREATE = 16,
H5P_TYPE_LINK_ACCESS = 17,
H5P_TYPE_ATTRIBUTE_ACCESS = 18,
+ H5P_TYPE_VOL_INITIALIZE = 19,
+ H5P_TYPE_MAP_CREATE = 20,
+ H5P_TYPE_MAP_ACCESS = 21,
+ H5P_TYPE_REFERENCE_ACCESS = 22,
H5P_TYPE_MAX_TYPE
} H5P_plist_type_t;
@@ -124,6 +128,8 @@ H5_DLLVAR H5P_genclass_t *H5P_CLS_GROUP_CREATE_g;
H5_DLLVAR H5P_genclass_t *H5P_CLS_GROUP_ACCESS_g;
H5_DLLVAR H5P_genclass_t *H5P_CLS_DATATYPE_CREATE_g;
H5_DLLVAR H5P_genclass_t *H5P_CLS_DATATYPE_ACCESS_g;
+H5_DLLVAR H5P_genclass_t *H5P_CLS_MAP_CREATE_g;
+H5_DLLVAR H5P_genclass_t *H5P_CLS_MAP_ACCESS_g;
H5_DLLVAR H5P_genclass_t *H5P_CLS_ATTRIBUTE_CREATE_g;
H5_DLLVAR H5P_genclass_t *H5P_CLS_ATTRIBUTE_ACCESS_g;
H5_DLLVAR H5P_genclass_t *H5P_CLS_OBJECT_COPY_g;
@@ -138,6 +144,7 @@ H5_DLLVAR const struct H5P_libclass_t H5P_CLS_AACC[1]; /* Attribute access */
H5_DLLVAR const struct H5P_libclass_t H5P_CLS_DACC[1]; /* Dataset access */
H5_DLLVAR const struct H5P_libclass_t H5P_CLS_GACC[1]; /* Group access */
H5_DLLVAR const struct H5P_libclass_t H5P_CLS_TACC[1]; /* Named datatype access */
+H5_DLLVAR const struct H5P_libclass_t H5P_CLS_MACC[1]; /* Map access */
H5_DLLVAR const struct H5P_libclass_t H5P_CLS_FACC[1]; /* File access */
H5_DLLVAR const struct H5P_libclass_t H5P_CLS_OCPY[1]; /* Object copy */
@@ -148,6 +155,7 @@ H5_DLLVAR const struct H5P_libclass_t H5P_CLS_OCPY[1]; /* Object copy */
/* Forward declaration of structs used below */
struct H5O_fill_t;
struct H5T_t;
+struct H5VL_connector_prop_t;
/* Package initialization routine */
H5_DLL herr_t H5P_init(void);
@@ -177,6 +185,9 @@ H5_DLL hid_t H5P_peek_driver(H5P_genplist_t *plist);
H5_DLL const void *H5P_peek_driver_info(H5P_genplist_t *plist);
H5_DLL herr_t H5P_set_driver(H5P_genplist_t *plist, hid_t new_driver_id,
const void *new_driver_info);
+H5_DLL herr_t H5P_set_vol(H5P_genplist_t *plist, hid_t vol_id, const void *vol_info);
+H5_DLL herr_t H5P_reset_vol_class(const H5P_genclass_t *pclass,
+ const struct H5VL_connector_prop_t *vol_prop);
H5_DLL herr_t H5P_set_vlen_mem_manager(H5P_genplist_t *plist,
H5MM_allocate_t alloc_func, void *alloc_info, H5MM_free_t free_func,
void *free_info);
@@ -204,6 +215,8 @@ H5_DLL herr_t H5P_fill_value_defined(H5P_genplist_t *plist,
H5D_fill_value_t *status);
H5_DLL herr_t H5P_get_fill_value(H5P_genplist_t *plist, const struct H5T_t *type,
void *value);
+H5_DLL int H5P_ignore_cmp(const void H5_ATTR_UNUSED *val1, const void H5_ATTR_UNUSED *val2,
+ size_t H5_ATTR_UNUSED size);
#endif /* _H5Pprivate_H */
diff --git a/src/H5Ppublic.h b/src/H5Ppublic.h
index 3abb3fd..150b371 100644
--- a/src/H5Ppublic.h
+++ b/src/H5Ppublic.h
@@ -62,12 +62,16 @@
#define H5P_GROUP_ACCESS (H5OPEN H5P_CLS_GROUP_ACCESS_ID_g)
#define H5P_DATATYPE_CREATE (H5OPEN H5P_CLS_DATATYPE_CREATE_ID_g)
#define H5P_DATATYPE_ACCESS (H5OPEN H5P_CLS_DATATYPE_ACCESS_ID_g)
+#define H5P_MAP_CREATE (H5OPEN H5P_CLS_MAP_CREATE_ID_g)
+#define H5P_MAP_ACCESS (H5OPEN H5P_CLS_MAP_ACCESS_ID_g)
#define H5P_STRING_CREATE (H5OPEN H5P_CLS_STRING_CREATE_ID_g)
#define H5P_ATTRIBUTE_CREATE (H5OPEN H5P_CLS_ATTRIBUTE_CREATE_ID_g)
#define H5P_ATTRIBUTE_ACCESS (H5OPEN H5P_CLS_ATTRIBUTE_ACCESS_ID_g)
#define H5P_OBJECT_COPY (H5OPEN H5P_CLS_OBJECT_COPY_ID_g)
#define H5P_LINK_CREATE (H5OPEN H5P_CLS_LINK_CREATE_ID_g)
#define H5P_LINK_ACCESS (H5OPEN H5P_CLS_LINK_ACCESS_ID_g)
+#define H5P_VOL_INITIALIZE (H5OPEN H5P_CLS_VOL_INITIALIZE_ID_g)
+#define H5P_REFERENCE_ACCESS (H5OPEN H5P_CLS_REFERENCE_ACCESS_ID_g)
/*
* The library's default property lists
@@ -82,11 +86,15 @@
#define H5P_GROUP_ACCESS_DEFAULT (H5OPEN H5P_LST_GROUP_ACCESS_ID_g)
#define H5P_DATATYPE_CREATE_DEFAULT (H5OPEN H5P_LST_DATATYPE_CREATE_ID_g)
#define H5P_DATATYPE_ACCESS_DEFAULT (H5OPEN H5P_LST_DATATYPE_ACCESS_ID_g)
+#define H5P_MAP_CREATE_DEFAULT (H5OPEN H5P_LST_MAP_CREATE_ID_g)
+#define H5P_MAP_ACCESS_DEFAULT (H5OPEN H5P_LST_MAP_ACCESS_ID_g)
#define H5P_ATTRIBUTE_CREATE_DEFAULT (H5OPEN H5P_LST_ATTRIBUTE_CREATE_ID_g)
#define H5P_ATTRIBUTE_ACCESS_DEFAULT (H5OPEN H5P_LST_ATTRIBUTE_ACCESS_ID_g)
#define H5P_OBJECT_COPY_DEFAULT (H5OPEN H5P_LST_OBJECT_COPY_ID_g)
#define H5P_LINK_CREATE_DEFAULT (H5OPEN H5P_LST_LINK_CREATE_ID_g)
#define H5P_LINK_ACCESS_DEFAULT (H5OPEN H5P_LST_LINK_ACCESS_ID_g)
+#define H5P_VOL_INITIALIZE_DEFAULT (H5OPEN H5P_LST_VOL_INITIALIZE_ID_g)
+#define H5P_REFERENCE_ACCESS_DEFAULT (H5OPEN H5P_LST_REFERENCE_ACCESS_ID_g)
/* Common creation order flags (for links in groups and attributes on objects) */
#define H5P_CRT_ORDER_TRACKED 0x0001
@@ -167,7 +175,8 @@ typedef enum H5D_mpio_no_collective_cause_t {
H5D_MPIO_NOT_SIMPLE_OR_SCALAR_DATASPACES = 0x10,
H5D_MPIO_NOT_CONTIGUOUS_OR_CHUNKED_DATASET = 0x20,
H5D_MPIO_PARALLEL_FILTERED_WRITES_DISABLED = 0x40,
- H5D_MPIO_NO_COLLECTIVE_MAX_CAUSE = 0x80
+ H5D_MPIO_ERROR_WHILE_CHECKING_COLLECTIVE_POSSIBLE = 0x80,
+ H5D_MPIO_NO_COLLECTIVE_MAX_CAUSE = 0x100
} H5D_mpio_no_collective_cause_t;
/********************/
@@ -188,12 +197,16 @@ H5_DLLVAR hid_t H5P_CLS_GROUP_CREATE_ID_g;
H5_DLLVAR hid_t H5P_CLS_GROUP_ACCESS_ID_g;
H5_DLLVAR hid_t H5P_CLS_DATATYPE_CREATE_ID_g;
H5_DLLVAR hid_t H5P_CLS_DATATYPE_ACCESS_ID_g;
+H5_DLLVAR hid_t H5P_CLS_MAP_CREATE_ID_g;
+H5_DLLVAR hid_t H5P_CLS_MAP_ACCESS_ID_g;
H5_DLLVAR hid_t H5P_CLS_STRING_CREATE_ID_g;
H5_DLLVAR hid_t H5P_CLS_ATTRIBUTE_CREATE_ID_g;
H5_DLLVAR hid_t H5P_CLS_ATTRIBUTE_ACCESS_ID_g;
H5_DLLVAR hid_t H5P_CLS_OBJECT_COPY_ID_g;
H5_DLLVAR hid_t H5P_CLS_LINK_CREATE_ID_g;
H5_DLLVAR hid_t H5P_CLS_LINK_ACCESS_ID_g;
+H5_DLLVAR hid_t H5P_CLS_VOL_INITIALIZE_ID_g;
+H5_DLLVAR hid_t H5P_CLS_REFERENCE_ACCESS_ID_g;
/* Default roperty list IDs */
/* (Internal to library, do not use! Use macros above) */
@@ -207,11 +220,15 @@ H5_DLLVAR hid_t H5P_LST_GROUP_CREATE_ID_g;
H5_DLLVAR hid_t H5P_LST_GROUP_ACCESS_ID_g;
H5_DLLVAR hid_t H5P_LST_DATATYPE_CREATE_ID_g;
H5_DLLVAR hid_t H5P_LST_DATATYPE_ACCESS_ID_g;
+H5_DLLVAR hid_t H5P_LST_MAP_CREATE_ID_g;
+H5_DLLVAR hid_t H5P_LST_MAP_ACCESS_ID_g;
H5_DLLVAR hid_t H5P_LST_ATTRIBUTE_CREATE_ID_g;
H5_DLLVAR hid_t H5P_LST_ATTRIBUTE_ACCESS_ID_g;
H5_DLLVAR hid_t H5P_LST_OBJECT_COPY_ID_g;
H5_DLLVAR hid_t H5P_LST_LINK_CREATE_ID_g;
H5_DLLVAR hid_t H5P_LST_LINK_ACCESS_ID_g;
+H5_DLLVAR hid_t H5P_LST_VOL_INITIALIZE_ID_g;
+H5_DLLVAR hid_t H5P_LST_REFERENCE_ACCESS_ID_g;
/*********************/
/* Public Prototypes */
@@ -235,7 +252,7 @@ H5_DLL herr_t H5Pinsert2(hid_t plist_id, const char *name, size_t size,
H5P_prp_compare_func_t prp_cmp, H5P_prp_close_func_t prp_close);
H5_DLL herr_t H5Pset(hid_t plist_id, const char *name, const void *value);
H5_DLL htri_t H5Pexist(hid_t plist_id, const char *name);
-H5_DLL herr_t H5Pencode(hid_t plist_id, void *buf, size_t *nalloc);
+H5_DLL herr_t H5Pencode2(hid_t plist_id, void *buf, size_t *nalloc, hid_t fapl_id);
H5_DLL hid_t H5Pdecode(const void *buf);
H5_DLL herr_t H5Pget_size(hid_t id, const char *name, size_t *size);
H5_DLL herr_t H5Pget_nprops(hid_t id, size_t *nprops);
@@ -313,6 +330,9 @@ H5_DLL herr_t H5Pset_driver(hid_t plist_id, hid_t driver_id,
const void *driver_info);
H5_DLL hid_t H5Pget_driver(hid_t plist_id);
H5_DLL const void *H5Pget_driver_info(hid_t plist_id);
+H5_DLL herr_t H5Pset_vol(hid_t plist_id, hid_t new_vol_id, const void *new_vol_info);
+H5_DLL herr_t H5Pget_vol_id(hid_t plist_id, hid_t *vol_id);
+H5_DLL herr_t H5Pget_vol_info(hid_t plist_id, void **vol_info);
H5_DLL herr_t H5Pset_family_offset(hid_t fapl_id, hsize_t offset);
H5_DLL herr_t H5Pget_family_offset(hid_t fapl_id, hsize_t *offset);
H5_DLL herr_t H5Pset_multi_type(hid_t fapl_id, H5FD_mem_t type);
@@ -365,6 +385,8 @@ H5_DLL herr_t H5Pset_all_coll_metadata_ops(hid_t plist_id, hbool_t is_collective
H5_DLL herr_t H5Pget_all_coll_metadata_ops(hid_t plist_id, hbool_t *is_collective);
H5_DLL herr_t H5Pset_coll_metadata_write(hid_t plist_id, hbool_t is_collective);
H5_DLL herr_t H5Pget_coll_metadata_write(hid_t plist_id, hbool_t *is_collective);
+H5_DLL herr_t H5Pget_mpi_params(hid_t fapl_id, MPI_Comm *comm, MPI_Info *info);
+H5_DLL herr_t H5Pset_mpi_params(hid_t fapl_id, MPI_Comm comm, MPI_Info info);
#endif /* H5_HAVE_PARALLEL */
H5_DLL herr_t H5Pset_mdc_image_config(hid_t plist_id, H5AC_cache_image_config_t *config_ptr);
H5_DLL herr_t H5Pget_mdc_image_config(hid_t plist_id, H5AC_cache_image_config_t *config_ptr /*out*/);
@@ -413,6 +435,8 @@ H5_DLL herr_t H5Pget_alloc_time(hid_t plist_id, H5D_alloc_time_t
H5_DLL herr_t H5Pset_fill_time(hid_t plist_id, H5D_fill_time_t fill_time);
H5_DLL herr_t H5Pget_fill_time(hid_t plist_id, H5D_fill_time_t
*fill_time/*out*/);
+H5_DLL herr_t H5Pget_dset_no_attrs_hint(hid_t dcpl_id, hbool_t *minimize);
+H5_DLL herr_t H5Pset_dset_no_attrs_hint(hid_t dcpl_id, hbool_t minimize);
/* Dataset access property list (DAPL) routines */
H5_DLL herr_t H5Pset_chunk_cache(hid_t dapl_id, size_t rdcc_nslots,
@@ -485,6 +509,12 @@ H5_DLL herr_t H5Pget_est_link_info(hid_t plist_id, unsigned *est_num_entries /*
H5_DLL herr_t H5Pset_link_creation_order(hid_t plist_id, unsigned crt_order_flags);
H5_DLL herr_t H5Pget_link_creation_order(hid_t plist_id, unsigned *crt_order_flags /* out */);
+/* Map access property list (MAPL) routines */
+#ifdef H5_HAVE_MAP_API
+H5_DLL herr_t H5Pset_map_iterate_hints(hid_t mapl_id, size_t key_prefetch_size, size_t key_alloc_size);
+H5_DLL herr_t H5Pget_map_iterate_hints(hid_t mapl_id, size_t *key_prefetch_size /*out*/, size_t *key_alloc_size /*out*/);
+#endif /* H5_HAVE_MAP_API */
+
/* String creation property list (STRCPL) routines */
H5_DLL herr_t H5Pset_char_encoding(hid_t plist_id, H5T_cset_t encoding);
H5_DLL herr_t H5Pget_char_encoding(hid_t plist_id, H5T_cset_t *encoding /*out*/);
@@ -534,6 +564,7 @@ H5_DLL herr_t H5Pinsert1(hid_t plist_id, const char *name, size_t size,
void *value, H5P_prp_set_func_t prp_set, H5P_prp_get_func_t prp_get,
H5P_prp_delete_func_t prp_delete, H5P_prp_copy_func_t prp_copy,
H5P_prp_close_func_t prp_close);
+H5_DLL herr_t H5Pencode1(hid_t plist_id, void *buf, size_t *nalloc);
H5_DLL H5Z_filter_t H5Pget_filter1(hid_t plist_id, unsigned filter,
unsigned int *flags/*out*/, size_t *cd_nelmts/*out*/,
unsigned cd_values[]/*out*/, size_t namelen, char name[]);
diff --git a/src/H5R.c b/src/H5R.c
index 65aa6cb..11b75ca 100644
--- a/src/H5R.c
+++ b/src/H5R.c
@@ -11,22 +11,24 @@
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/*
+ * Purpose: Reference routines.
+ */
+
/****************/
/* Module Setup */
/****************/
#include "H5Rmodule.h" /* This source code file is part of the H5R module */
-
/***********/
/* Headers */
/***********/
#include "H5private.h" /* Generic Functions */
-#include "H5ACprivate.h" /* Metadata cache */
#include "H5CXprivate.h" /* API Contexts */
#include "H5Eprivate.h" /* Error handling */
-#include "H5Gprivate.h" /* Groups */
#include "H5Iprivate.h" /* IDs */
+#include "H5MMprivate.h" /* Memory management */
#include "H5Rpkg.h" /* References */
#include "H5Sprivate.h" /* Dataspaces */
@@ -61,299 +63,825 @@
/*******************/
-/*--------------------------------------------------------------------------
- NAME
- H5Rcreate
- PURPOSE
- Creates a particular kind of reference for the user
- USAGE
- herr_t H5Rcreate(ref, loc_id, name, ref_type, space_id)
- void *ref; OUT: Reference created
- hid_t loc_id; IN: Location ID used to locate object pointed to
- const char *name; IN: Name of object at location LOC_ID of object
- pointed to
- H5R_type_t ref_type; IN: Type of reference to create
- hid_t space_id; IN: Dataspace ID with selection, used for Dataset
- Region references.
-
- RETURNS
- Non-negative on success/Negative on failure
- DESCRIPTION
- Creates a particular type of reference specified with REF_TYPE, in the
- space pointed to by REF. The LOC_ID and NAME are used to locate the object
- pointed to and the SPACE_ID is used to choose the region pointed to (for
- Dataset Region references).
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
+/*-------------------------------------------------------------------------
+ * Function: H5Rcreate_object
+ *
+ * Purpose: Creates an object reference. The LOC_ID and NAME are used to locate
+ * the object pointed to.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
herr_t
-H5Rcreate(void *ref, hid_t loc_id, const char *name, H5R_type_t ref_type, hid_t space_id)
+H5Rcreate_object(hid_t loc_id, const char *name, H5R_ref_t *ref_ptr)
{
- H5G_loc_t loc; /* File location */
- H5S_t *space = NULL; /* Pointer to dataspace containing region */
- herr_t ret_value; /* Return value */
+ H5VL_object_t *vol_obj = NULL; /* Object token of loc_id */
+ H5I_type_t obj_type; /* Object type of loc_id */
+ hid_t file_id = H5I_INVALID_HID;/* File ID */
+ H5VL_object_t *vol_obj_file = NULL; /* Object token of file_id */
+ H5VL_loc_params_t loc_params; /* Location parameters */
+ H5VL_token_t obj_token = {0}; /* Object token */
+ H5VL_file_cont_info_t cont_info = {H5VL_CONTAINER_INFO_VERSION, 0, 0, 0};
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
- H5TRACE5("e", "*xi*sRti", ref, loc_id, name, ref_type, space_id);
+ H5TRACE3("e", "i*s*Rr", loc_id, name, ref_ptr);
/* Check args */
- if (ref == NULL)
+ if(ref_ptr == NULL)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid reference pointer")
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!name || !*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name given")
- if(ref_type <= H5R_BADTYPE || ref_type >= H5R_MAXTYPE)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid reference type")
- if(ref_type != H5R_OBJECT && ref_type != H5R_DATASET_REGION)
- HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "reference type not supported")
- if(space_id == (-1) && ref_type == H5R_DATASET_REGION)
+
+ /* Get the VOL object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Get object type */
+ if((obj_type = H5I_get_type(loc_id)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Get the file for the object */
+ if((file_id = H5F_get_file_id(loc_id, obj_type, FALSE)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+
+ /* Retrieve VOL file object */
+ if(NULL == (vol_obj_file = H5VL_vol_object(file_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Get container info */
+ if(H5VL_file_get(vol_obj_file, H5VL_FILE_GET_CONT_INFO, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &cont_info) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "unable to get container info")
+
+ /* Set location parameters */
+ loc_params.type = H5VL_OBJECT_BY_NAME;
+ loc_params.loc_data.loc_by_name.name = name;
+ loc_params.obj_type = obj_type;
+
+ /* Get the object token */
+ if(H5VL_object_specific(vol_obj, &loc_params, H5VL_OBJECT_LOOKUP, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, obj_token) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "unable to retrieve object token")
+
+ /* Create the reference (do not pass filename, since file_id is attached) */
+ HDmemset(ref_ptr, 0, H5R_REF_BUF_SIZE);
+ if(H5R__create_object((const H5VL_token_t *)&obj_token, cont_info.token_size, (H5R_ref_priv_t *)ref_ptr) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCREATE, FAIL, "unable to create object reference")
+
+ /* Attach loc_id to reference and hold reference to it */
+ if(H5R__set_loc_id((H5R_ref_priv_t *)ref_ptr, file_id, TRUE) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTSET, FAIL, "unable to attach location id to reference")
+
+done:
+ if(file_id != H5I_INVALID_HID && H5I_dec_ref(file_id) < 0)
+ HDONE_ERROR(H5E_REFERENCE, H5E_CANTDEC, FAIL, "unable to decrement refcount on file")
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Rcreate_object() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Rcreate_region
+ *
+ * Purpose: Creates a region reference. The LOC_ID and NAME are used to locate
+ * the object pointed to and the SPACE_ID is used to choose the region pointed
+ * to.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Rcreate_region(hid_t loc_id, const char *name, hid_t space_id,
+ H5R_ref_t *ref_ptr)
+{
+ H5VL_object_t *vol_obj = NULL; /* Object token of loc_id */
+ H5I_type_t obj_type; /* Object type of loc_id */
+ hid_t file_id = H5I_INVALID_HID;/* File ID */
+ H5VL_object_t *vol_obj_file = NULL; /* Object token of file_id */
+ H5VL_loc_params_t loc_params; /* Location parameters */
+ H5VL_token_t obj_token = {0}; /* Object token */
+ H5VL_file_cont_info_t cont_info = {H5VL_CONTAINER_INFO_VERSION, 0, 0, 0};
+ struct H5S_t *space = NULL; /* Pointer to dataspace containing region */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE4("e", "i*si*Rr", loc_id, name, space_id, ref_ptr);
+
+ /* Check args */
+ if(ref_ptr == NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid reference pointer")
+ if(!name || !*name)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name given")
+ if((space_id == H5I_BADID) || (space_id == H5S_ALL))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "reference region dataspace id must be valid")
- if(space_id != (-1) && (NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE))))
+ if(NULL == (space = (struct H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
- /* Set up collective metadata if appropriate */
- if(H5CX_set_loc(loc_id) < 0)
- HGOTO_ERROR(H5E_REFERENCE, H5E_CANTSET, FAIL, "can't set access property list info")
+ /* Get the VOL object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Get object type */
+ if((obj_type = H5I_get_type(loc_id)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Get the file for the object */
+ if((file_id = H5F_get_file_id(loc_id, obj_type, FALSE)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+
+ /* Retrieve VOL file object */
+ if(NULL == (vol_obj_file = H5VL_vol_object(file_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Get container info */
+ if(H5VL_file_get(vol_obj_file, H5VL_FILE_GET_CONT_INFO, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &cont_info) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "unable to get container info")
+
+ /* Set location parameters */
+ loc_params.type = H5VL_OBJECT_BY_NAME;
+ loc_params.loc_data.loc_by_name.name = name;
+ loc_params.obj_type = obj_type;
+
+ /* Get the object token */
+ if(H5VL_object_specific(vol_obj, &loc_params, H5VL_OBJECT_LOOKUP, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, obj_token) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "unable to retrieve object token")
+
+ /* Create the reference (do not pass filename, since file_id is attached) */
+ HDmemset(ref_ptr, 0, H5R_REF_BUF_SIZE);
+ if(H5R__create_region((const H5VL_token_t *)&obj_token, cont_info.token_size, space, (H5R_ref_priv_t *)ref_ptr) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCREATE, FAIL, "unable to create region reference")
+
+ /* Attach loc_id to reference and hold reference to it */
+ if(H5R__set_loc_id((H5R_ref_priv_t *)ref_ptr, file_id, TRUE) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTSET, FAIL, "unable to attach location id to reference")
+
+done:
+ if(file_id != H5I_INVALID_HID && H5I_dec_ref(file_id) < 0)
+ HDONE_ERROR(H5E_REFERENCE, H5E_CANTDEC, H5I_INVALID_HID, "unable to decrement refcount on file")
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Rcreate_region() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Rcreate_attr
+ *
+ * Purpose: Creates an attribute reference. The LOC_ID, NAME and ATTR_NAME are
+ * used to locate the attribute pointed to.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Rcreate_attr(hid_t loc_id, const char *name, const char *attr_name,
+ H5R_ref_t *ref_ptr)
+{
+ H5VL_object_t *vol_obj = NULL; /* Object token of loc_id */
+ H5I_type_t obj_type; /* Object type of loc_id */
+ hid_t file_id = H5I_INVALID_HID;/* File ID */
+ H5VL_object_t *vol_obj_file = NULL; /* Object token of file_id */
+ H5VL_loc_params_t loc_params; /* Location parameters */
+ H5VL_token_t obj_token = {0}; /* Object token */
+ H5VL_file_cont_info_t cont_info = {H5VL_CONTAINER_INFO_VERSION, 0, 0, 0};
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE4("e", "i*s*s*Rr", loc_id, name, attr_name, ref_ptr);
+
+ /* Check args */
+ if(ref_ptr == NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid reference pointer")
+ if(!name || !*name)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name given")
+ if(!attr_name || !*attr_name)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no attribute name given")
+
+ /* Get the VOL object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Get object type */
+ if((obj_type = H5I_get_type(loc_id)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Get the file for the object */
+ if((file_id = H5F_get_file_id(loc_id, obj_type, FALSE)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+
+ /* Retrieve VOL file object */
+ if(NULL == (vol_obj_file = H5VL_vol_object(file_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Get container info */
+ if(H5VL_file_get(vol_obj_file, H5VL_FILE_GET_CONT_INFO, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &cont_info) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "unable to get container info")
+
+ /* Set location parameters */
+ loc_params.type = H5VL_OBJECT_BY_NAME;
+ loc_params.loc_data.loc_by_name.name = name;
+ loc_params.obj_type = obj_type;
+
+ /* Get the object token */
+ if(H5VL_object_specific(vol_obj, &loc_params, H5VL_OBJECT_LOOKUP, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, obj_token) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "unable to retrieve object token")
+
+ /* Create the reference (do not pass filename, since file_id is attached) */
+ HDmemset(ref_ptr, 0, H5R_REF_BUF_SIZE);
+ if(H5R__create_attr((const H5VL_token_t *)&obj_token, cont_info.token_size, attr_name, (H5R_ref_priv_t *)ref_ptr) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCREATE, FAIL, "unable to create attribute reference")
+
+ /* Attach loc_id to reference and hold reference to it */
+ if(H5R__set_loc_id((H5R_ref_priv_t *)ref_ptr, file_id, TRUE) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTSET, FAIL, "unable to attach location id to reference")
+
+done:
+ if(file_id != H5I_INVALID_HID && H5I_dec_ref(file_id) < 0)
+ HDONE_ERROR(H5E_REFERENCE, H5E_CANTDEC, H5I_INVALID_HID, "unable to decrement refcount on file")
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Rcreate_attr() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Rdestroy
+ *
+ * Purpose: Destroy reference and free resources allocated during H5Rcreate.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Rdestroy(H5R_ref_t *ref_ptr)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE1("e", "*Rr", ref_ptr);
+
+ /* Check args */
+ if(NULL == ref_ptr)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid reference pointer")
+
+ /* Destroy reference */
+ if(H5R__destroy((H5R_ref_priv_t *)ref_ptr) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTFREE, FAIL, "unable to destroy reference")
+
+ /* Memset back to 0 for safety */
+ HDmemset(ref_ptr, 0, H5R_REF_BUF_SIZE);
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Rdestroy() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Rget_type
+ *
+ * Purpose: Given a reference to some object, return the type of that reference.
+ *
+ * Return: Reference type/H5R_BADTYPE on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+H5R_type_t
+H5Rget_type(const H5R_ref_t *ref_ptr)
+{
+ H5R_type_t ret_value; /* Return value */
+
+ FUNC_ENTER_API(H5R_BADTYPE)
+ H5TRACE1("Rt", "*Rr", ref_ptr);
+
+ /* Check args */
+ if(NULL == ref_ptr)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5R_BADTYPE, "invalid reference pointer")
+
+ /* Get reference type */
+ ret_value = H5R__get_type((const H5R_ref_priv_t *)ref_ptr);
+ if((ret_value <= H5R_BADTYPE) || (ret_value >= H5R_MAXTYPE))
+ HGOTO_ERROR(H5E_REFERENCE, H5E_BADVALUE, H5R_BADTYPE, "invalid reference type")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Rget_type() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Requal
+ *
+ * Purpose: Compare two references
+ *
+ * Return: TRUE if equal, FALSE if unequal, FAIL if error
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5Requal(const H5R_ref_t *ref1_ptr, const H5R_ref_t *ref2_ptr)
+{
+ htri_t ret_value; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE2("t", "*Rr*Rr", ref1_ptr, ref2_ptr);
+
+ /* Check args */
+ if(!ref1_ptr || !ref2_ptr)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid reference pointer")
+
+ /* Compare references */
+ if((ret_value = H5R__equal((const H5R_ref_priv_t *)ref2_ptr, (const H5R_ref_priv_t *)ref2_ptr)) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCOMPARE, FAIL, "cannot compare references")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Requal() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Rcopy
+ *
+ * Purpose: Copy a reference
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Rcopy(const H5R_ref_t *src_ref_ptr, H5R_ref_t *dst_ref_ptr)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE2("e", "*Rr*Rr", src_ref_ptr, dst_ref_ptr);
- /* Create reference */
- if((ret_value = H5R__create(ref, &loc, name, ref_type, space)) < 0)
- HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCREATE, FAIL, "unable to create reference")
+ /* Check args */
+ if(NULL == src_ref_ptr || NULL == dst_ref_ptr)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid reference pointer")
+
+ /* Copy reference */
+ if(H5R__copy((const H5R_ref_priv_t *)src_ref_ptr, (H5R_ref_priv_t *)dst_ref_ptr) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCOPY, FAIL, "cannot copy reference")
done:
FUNC_LEAVE_API(ret_value)
-} /* end H5Rcreate() */
+} /* end H5Rcopy() */
-/*--------------------------------------------------------------------------
- NAME
- H5Rdereference2
- PURPOSE
- Opens the HDF5 object referenced.
- USAGE
- hid_t H5Rdereference2(ref)
- hid_t id; IN: Dataset reference object is in or location ID of
- object that the dataset is located within.
- hid_t oapl_id; IN: Property list of the object being referenced.
- H5R_type_t ref_type; IN: Type of reference to create
- void *ref; IN: Reference to open.
-
- RETURNS
- Valid ID on success, H5I_INVALID_HID on failure
- DESCRIPTION
- Given a reference to some object, open that object and return an ID for
- that object.
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- EXAMPLES
- REVISION LOG
- Raymond Lu
- 13 July 2011
- I added the OAPL_ID parameter for the object being referenced. It only
- supports dataset access property list currently.
---------------------------------------------------------------------------*/
+/*-------------------------------------------------------------------------
+ * Function: H5Ropen_object
+ *
+ * Purpose: Given a reference to some object, open that object and return an
+ * ID for that object.
+ *
+ * Return: Valid ID on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
hid_t
-H5Rdereference2(hid_t obj_id, hid_t oapl_id, H5R_type_t ref_type, const void *_ref)
+H5Ropen_object(const H5R_ref_t *ref_ptr, hid_t rapl_id, hid_t oapl_id)
{
- H5G_loc_t loc; /* Group location */
- H5F_t *file = NULL; /* File object */
- hid_t ret_value = H5I_INVALID_HID; /* Return value */
+ hid_t loc_id; /* Reference location ID */
+ H5VL_object_t *vol_obj = NULL; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params; /* Location parameters */
+ H5VL_token_t obj_token = {0}; /* Object token */
+ H5I_type_t opened_type; /* Opened object type */
+ void *opened_obj = NULL; /* Opened object */
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
FUNC_ENTER_API(H5I_INVALID_HID)
- H5TRACE4("i", "iiRt*x", obj_id, oapl_id, ref_type, _ref);
+ H5TRACE3("i", "*Rrii", ref_ptr, rapl_id, oapl_id);
/* Check args */
- if(H5G_loc(obj_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a location")
+ if(ref_ptr == NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "invalid reference pointer")
+ if(H5R__get_type((const H5R_ref_priv_t *)ref_ptr) <= H5R_BADTYPE
+ || H5R__get_type((const H5R_ref_priv_t *)ref_ptr) >= H5R_MAXTYPE)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "invalid reference type")
+ if(rapl_id < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a property list")
if(oapl_id < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a property list")
- if(ref_type <= H5R_BADTYPE || ref_type >= H5R_MAXTYPE)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "invalid reference type")
- if(_ref == NULL)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "invalid reference pointer")
+
+ /* Retrieve loc_id from reference */
+ if(H5I_INVALID_HID == (loc_id = H5R__get_loc_id((const H5R_ref_priv_t *)ref_ptr))) {
+ /* Attempt to re-open file and pass rapl_id as a fapl_id */
+ if((loc_id = H5R__reopen_file((H5R_ref_priv_t *)ref_ptr, rapl_id)) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTOPENFILE, H5I_INVALID_HID, "cannot re-open referenced file")
+ }
+
+ /* Get object token */
+ if(H5R__get_obj_token((const H5R_ref_priv_t *)ref_ptr, &obj_token, NULL) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, H5I_INVALID_HID, "unable to get object token")
/* Verify access property list and set up collective metadata if appropriate */
- if(H5CX_set_apl(&oapl_id, H5P_CLS_DACC, obj_id, FALSE) < 0)
- HGOTO_ERROR(H5E_REFERENCE, H5E_CANTSET, FAIL, "can't set access property list info")
+ if(H5CX_set_apl(&oapl_id, H5P_CLS_DACC, loc_id, FALSE) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info")
- /* Get the file pointer from the entry */
- file = loc.oloc->file;
+ /* Get the VOL object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier")
- /* Dereference */
- if((ret_value = H5R__dereference(file, oapl_id, ref_type, _ref)) < 0)
- HGOTO_ERROR(H5E_REFERENCE, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to dereference object")
+ /* Set location parameters */
+ loc_params.type = H5VL_OBJECT_BY_TOKEN;
+ loc_params.loc_data.loc_by_token.token = obj_token;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* Open object by token */
+ if(NULL == (opened_obj = H5VL_object_open(vol_obj, &loc_params, &opened_type, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)))
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open object by token")
+
+ /* Register object */
+ if((ret_value = H5VL_register(opened_type, opened_obj, vol_obj->connector, TRUE)) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register object handle")
done:
FUNC_LEAVE_API(ret_value)
-} /* end H5Rdereference2() */
+} /* end H5Ropen_object() */
-/*--------------------------------------------------------------------------
- NAME
- H5Rget_region
- PURPOSE
- Retrieves a dataspace with the region pointed to selected.
- USAGE
- hid_t H5Rget_region(id, ref_type, ref)
- hid_t id; IN: Dataset reference object is in or location ID of
- object that the dataset is located within.
- H5R_type_t ref_type; IN: Type of reference to get region of
- void *ref; IN: Reference to open.
-
- RETURNS
- Valid ID on success, H5I_INVALID_HID on failure
- DESCRIPTION
- Given a reference to some object, creates a copy of the dataset pointed
- to's dataspace and defines a selection in the copy which is the region
- pointed to.
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
+/*-------------------------------------------------------------------------
+ * Function: H5Ropen_region
+ *
+ * Purpose: Given a reference to some object, creates a copy of the dataset
+ * pointed to's dataspace and defines a selection in the copy which is the
+ * region pointed to.
+ *
+ * Return: Valid ID on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
hid_t
-H5Rget_region(hid_t id, H5R_type_t ref_type, const void *ref)
+H5Ropen_region(const H5R_ref_t *ref_ptr, hid_t rapl_id, hid_t oapl_id)
{
- H5G_loc_t loc; /* Object's group location */
- H5S_t *space = NULL; /* Dataspace object */
- hid_t ret_value = H5I_INVALID_HID; /* Return value */
+ hid_t loc_id; /* Reference location ID */
+ H5VL_object_t *vol_obj = NULL; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params; /* Location parameters */
+ H5VL_token_t obj_token = {0}; /* Object token */
+ H5I_type_t opened_type; /* Opened object type */
+ void *opened_obj = NULL; /* Opened object */
+ hid_t opened_obj_id = H5I_INVALID_HID; /* Opened object ID */
+ H5S_t *space = NULL; /* Dataspace pointer (copy) */
+ hid_t space_id = H5I_INVALID_HID; /* Dataspace ID */
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
FUNC_ENTER_API(H5I_INVALID_HID)
- H5TRACE3("i", "iRt*x", id, ref_type, ref);
+ H5TRACE3("i", "*Rrii", ref_ptr, rapl_id, oapl_id);
/* Check args */
- if(H5G_loc(id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a location")
- if(ref_type != H5R_DATASET_REGION)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "invalid reference type")
- if(ref == NULL)
+ if(ref_ptr == NULL)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "invalid reference pointer")
+ if((H5R__get_type((const H5R_ref_priv_t *)ref_ptr) != H5R_DATASET_REGION1)
+ && (H5R__get_type((const H5R_ref_priv_t *)ref_ptr) != H5R_DATASET_REGION2))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "invalid reference type")
+ if(rapl_id < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a property list")
+ if(oapl_id < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a property list")
+
+ /* Retrieve loc_id from reference */
+ if(H5I_INVALID_HID == (loc_id = H5R__get_loc_id((const H5R_ref_priv_t *)ref_ptr))) {
+ /* Attempt to re-open file and pass rapl_id as a fapl_id */
+ if((loc_id = H5R__reopen_file((H5R_ref_priv_t *)ref_ptr, rapl_id)) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTOPENFILE, H5I_INVALID_HID, "cannot re-open referenced file")
+ }
+
+ /* Get object token */
+ if(H5R__get_obj_token((const H5R_ref_priv_t *)ref_ptr, &obj_token, NULL) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, H5I_INVALID_HID, "unable to get object token")
+
+ /* Get the VOL object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier")
+
+ /* Set location parameters */
+ loc_params.type = H5VL_OBJECT_BY_TOKEN;
+ loc_params.loc_data.loc_by_token.token = obj_token;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* Open object by token */
+ if(NULL == (opened_obj = H5VL_object_open(vol_obj, &loc_params, &opened_type, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)))
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open object by token")
+
+ /* Register object */
+ if((opened_obj_id = H5VL_register(opened_type, opened_obj, vol_obj->connector, FALSE)) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register object handle")
+
+ /* Get VOL object object */
+ if(NULL == (opened_obj = H5VL_vol_object(opened_obj_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier")
+
+ /* Get dataspace from object */
+ if(H5VL_dataset_get(opened_obj, H5VL_DATASET_GET_SPACE, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &space_id) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, H5I_INVALID_HID, "unable to get dataspace from dataset")
+ if(NULL == (space = (struct H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a dataspace")
/* Get the dataspace with the correct region selected */
- if(NULL == (space = H5R__get_region(loc.oloc->file, ref)))
- HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, H5I_INVALID_HID, "unable to retrieve dataspace")
+ if(H5R__get_region((const H5R_ref_priv_t *)ref_ptr, space) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, H5I_INVALID_HID, "unable to get selection on dataspace")
+
+ /* Simply return space_id */
+ ret_value = space_id;
+
+done:
+ if((opened_obj_id != H5I_INVALID_HID) && (H5I_dec_ref(opened_obj_id) < 0))
+ HDONE_ERROR(H5E_REFERENCE, H5E_CLOSEERROR, H5I_INVALID_HID, "can't close object")
+ if(H5I_INVALID_HID == ret_value) /* Cleanup on failure */
+ if((space_id != H5I_INVALID_HID) && (H5I_dec_ref(space_id) < 0))
+ HDONE_ERROR(H5E_REFERENCE, H5E_CLOSEERROR, H5I_INVALID_HID, "can't close dataspace")
+
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Ropen_region() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Ropen_attr
+ *
+ * Purpose: Given a reference to some attribute, open that attribute and
+ * return an ID for that attribute.
+ *
+ * Return: Valid ID on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5Ropen_attr(const H5R_ref_t *ref_ptr, hid_t rapl_id, hid_t aapl_id)
+{
+ hid_t loc_id; /* Reference location ID */
+ H5VL_object_t *vol_obj = NULL; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params; /* Location parameters */
+ H5VL_token_t obj_token = {0}; /* Object token */
+ H5I_type_t opened_type; /* Opened object type */
+ void *opened_obj = NULL; /* Opened object */
+ hid_t opened_obj_id = H5I_INVALID_HID; /* Opened object ID */
+ void *opened_attr = NULL; /* Opened attribute */
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
+
+ FUNC_ENTER_API(H5I_INVALID_HID)
+ H5TRACE3("i", "*Rrii", ref_ptr, rapl_id, aapl_id);
+
+ /* Check args */
+ if(ref_ptr == NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "invalid reference pointer")
+ if(H5R__get_type((const H5R_ref_priv_t *)ref_ptr) != H5R_ATTR)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "invalid reference type")
+ if(rapl_id < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a property list")
+ if(aapl_id < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a property list")
+
+ /* Retrieve loc_id from reference */
+ if(H5I_INVALID_HID == (loc_id = H5R__get_loc_id((const H5R_ref_priv_t *)ref_ptr))) {
+ /* Attempt to re-open file and pass rapl_id as a fapl_id */
+ if((loc_id = H5R__reopen_file((H5R_ref_priv_t *)ref_ptr, rapl_id)) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTOPENFILE, H5I_INVALID_HID, "cannot re-open referenced file")
+ }
+
+ /* Get object token */
+ if(H5R__get_obj_token((const H5R_ref_priv_t *)ref_ptr, &obj_token, NULL) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, H5I_INVALID_HID, "unable to get object token")
+
+ /* Get the VOL object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier")
+
+ /* Set location parameters */
+ loc_params.type = H5VL_OBJECT_BY_TOKEN;
+ loc_params.loc_data.loc_by_token.token = obj_token;
+ loc_params.obj_type = H5I_get_type(loc_id);
- /* Atomize */
- if((ret_value = H5I_register(H5I_DATASPACE, space, TRUE)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register dataspace atom")
+ /* Open object by token */
+ if(NULL == (opened_obj = H5VL_object_open(vol_obj, &loc_params, &opened_type, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)))
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open object by token")
+
+ /* Register object */
+ if((opened_obj_id = H5VL_register(opened_type, opened_obj, vol_obj->connector, FALSE)) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register object handle")
+
+ /* Verify access property list and set up collective metadata if appropriate */
+ if(H5CX_set_apl(&aapl_id, H5P_CLS_AACC, loc_id, FALSE) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info")
+
+ /* Set location parameters */
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = opened_type;
+
+ /* Get VOL object object */
+ if(NULL == (opened_obj = H5VL_vol_object(opened_obj_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier")
+
+ /* Open the attribute */
+ if(NULL == (opened_attr = H5VL_attr_open(opened_obj, &loc_params, H5R_REF_ATTRNAME((const H5R_ref_priv_t *)ref_ptr), aapl_id, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open attribute: '%s'", H5R_REF_ATTRNAME((const H5R_ref_priv_t *)ref_ptr))
+
+ /* Register the attribute and get an ID for it */
+ if((ret_value = H5VL_register(H5I_ATTR, opened_attr, vol_obj->connector, TRUE)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to atomize attribute handle")
done:
+ if((opened_obj_id != H5I_INVALID_HID) && (H5I_dec_ref(opened_obj_id) < 0))
+ HDONE_ERROR(H5E_REFERENCE, H5E_CLOSEERROR, H5I_INVALID_HID, "can't close object")
+ if(H5I_INVALID_HID == ret_value) /* Cleanup on failure */
+ if(opened_attr && H5VL_attr_close(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, H5I_INVALID_HID, "can't close attribute")
+
FUNC_LEAVE_API(ret_value)
-} /* end H5Rget_region() */
+} /* end H5Ropen_attr() */
-/*--------------------------------------------------------------------------
- NAME
- H5Rget_obj_type2
- PURPOSE
- Retrieves the type of object that an object reference points to
- USAGE
- herr_t H5Rget_obj_type2(id, ref_type, ref, obj_type)
- hid_t id; IN: Dataset reference object is in or location ID of
- object that the dataset is located within.
- H5R_type_t ref_type; IN: Type of reference to query
- void *ref; IN: Reference to query.
- H5O_type_t *obj_type; OUT: Type of object reference points to
-
- RETURNS
- Non-negative on success/Negative on failure
- DESCRIPTION
- Given a reference to some object, this function retrieves the type of
- object pointed to.
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
+/*-------------------------------------------------------------------------
+ * Function: H5Rget_obj_type3
+ *
+ * Purpose: Given a reference to some object, this function returns the type
+ * of object pointed to.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
herr_t
-H5Rget_obj_type2(hid_t id, H5R_type_t ref_type, const void *ref,
- H5O_type_t *obj_type)
+H5Rget_obj_type3(const H5R_ref_t *ref_ptr, hid_t rapl_id, H5O_type_t *obj_type)
{
- H5G_loc_t loc; /* Object location */
- herr_t ret_value = SUCCEED; /* Return value */
+ hid_t loc_id; /* Reference location ID */
+ H5VL_object_t *vol_obj = NULL; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params; /* Location parameters */
+ H5VL_token_t obj_token = {0}; /* Object token */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
- H5TRACE4("e", "iRt*x*Ot", id, ref_type, ref, obj_type);
+ H5TRACE3("e", "*Rri*Ot", ref_ptr, rapl_id, obj_type);
/* Check args */
- if(H5G_loc(id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
- if(ref_type <= H5R_BADTYPE || ref_type >= H5R_MAXTYPE)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid reference type")
- if(ref == NULL)
+ if(ref_ptr == NULL)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid reference pointer")
+ if(H5R__get_type((const H5R_ref_priv_t *)ref_ptr) <= H5R_BADTYPE
+ || H5R__get_type((const H5R_ref_priv_t *)ref_ptr) >= H5R_MAXTYPE)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid reference type")
+ if(rapl_id < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a property list")
+
+ /* Retrieve loc_id from reference */
+ if(H5I_INVALID_HID == (loc_id = H5R__get_loc_id((const H5R_ref_priv_t *)ref_ptr))) {
+ /* Attempt to re-open file and pass rapl_id as a fapl_id */
+ if((loc_id = H5R__reopen_file((H5R_ref_priv_t *)ref_ptr, rapl_id)) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTOPENFILE, FAIL, "cannot re-open referenced file")
+ }
- /* Get the object type */
- if(H5R__get_obj_type(loc.oloc->file, ref_type, ref, obj_type) < 0)
- HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "unable to determine object type")
+ /* Get object token */
+ if(H5R__get_obj_token((const H5R_ref_priv_t *)ref_ptr, &obj_token, NULL) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "unable to get object token")
+
+ /* Get the VOL object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Set location parameters */
+ loc_params.type = H5VL_OBJECT_BY_TOKEN;
+ loc_params.loc_data.loc_by_token.token = obj_token;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* Retrieve object's type */
+ if(H5VL_object_get(vol_obj, &loc_params, H5VL_OBJECT_GET_TYPE, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, obj_type) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, FAIL, "can't retrieve object type")
done:
FUNC_LEAVE_API(ret_value)
-} /* end H5Rget_obj_type2() */
+} /* end H5Rget_obj_type3() */
-/*--------------------------------------------------------------------------
- NAME
- H5Rget_name
- PURPOSE
- Determines a name for the object referenced
- USAGE
- ssize_t H5Rget_name(loc_id, ref_type, ref, name, size)
- hid_t loc_id; IN: Dataset reference object is in or location ID of
- object that the dataset is located within.
- H5R_type_t ref_type; IN: Type of reference
- void *ref; IN: Reference to query.
- char *name; OUT: Buffer to place name of object referenced. If NULL
- then this call will return the size in bytes of name.
- size_t size; IN: Size of name buffer (user needs to include NULL terminator
- when passing in the size)
-
- RETURNS
- Non-negative length of the path on success, -1 on failure
- DESCRIPTION
- Given a reference to some object, determine a path to the object
- referenced in the file.
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- This may not be the only path to that object.
- EXAMPLES
- REVISION LOG
- M. Scot Breitenfeld
- 22 January 2014
- Changed the behavior for the returned value of the function when name is NULL.
- If name is NULL then size is ignored and the function returns the size
- of the name buffer (not including the NULL terminator), it still returns
- negative on failure.
---------------------------------------------------------------------------*/
+/*-------------------------------------------------------------------------
+ * Function: H5Rget_file_name
+ *
+ * Purpose: Given a reference to some object, determine a file name of the
+ * object located into.
+ *
+ * Return: Non-negative length of the path on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
ssize_t
-H5Rget_name(hid_t id, H5R_type_t ref_type, const void *_ref, char *name,
- size_t size)
+H5Rget_file_name(const H5R_ref_t *ref_ptr, char *buf, size_t size)
{
- H5G_loc_t loc; /* Group location */
- H5F_t *file; /* File object */
- ssize_t ret_value = -1; /* Return value */
+ hid_t loc_id; /* Reference location ID */
+ ssize_t ret_value; /* Return value */
FUNC_ENTER_API((-1))
- H5TRACE5("Zs", "iRt*x*sz", id, ref_type, _ref, name, size);
+ H5TRACE3("Zs", "*Rr*sz", ref_ptr, buf, size);
/* Check args */
- if(H5G_loc(id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "not a location")
- if(ref_type <= H5R_BADTYPE || ref_type >= H5R_MAXTYPE)
+ if(ref_ptr == NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, (-1), "invalid reference pointer")
+ if(H5R__get_type((const H5R_ref_priv_t *)ref_ptr) <= H5R_BADTYPE
+ || H5R__get_type((const H5R_ref_priv_t *)ref_ptr) >= H5R_MAXTYPE)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, (-1), "invalid reference type")
- if(_ref == NULL)
+
+ /* Get name */
+ if(H5I_INVALID_HID == (loc_id = H5R__get_loc_id((const H5R_ref_priv_t *)ref_ptr))) {
+ /* Un-opened external references do not have loc_id set but hold a
+ * copy of the filename */
+ if((ret_value = H5R__get_file_name((const H5R_ref_priv_t *)ref_ptr, buf, size)) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, (-1), "unable to retrieve file name")
+ } else {
+ H5VL_object_t *vol_obj = NULL; /* Object token of loc_id */
+
+ /* Retrieve VOL file object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "invalid location identifier")
+
+ if(H5VL_file_get(vol_obj, H5VL_FILE_GET_NAME, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, H5I_FILE, size, buf, &ret_value) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, (-1), "unable to get file name")
+ }
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Rget_file_name() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Rget_obj_name
+ *
+ * Purpose: Given a reference to some object, determine a path to the object
+ * referenced in the file.
+ *
+ * Return: Non-negative length of the path on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+ssize_t
+H5Rget_obj_name(const H5R_ref_t *ref_ptr, hid_t rapl_id, char *buf, size_t size)
+{
+ hid_t loc_id; /* Reference location ID */
+ H5VL_object_t *vol_obj = NULL; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params; /* Location parameters */
+ H5VL_token_t obj_token = {0}; /* Object token */
+ ssize_t ret_value; /* Return value */
+
+ FUNC_ENTER_API((-1))
+ H5TRACE4("Zs", "*Rri*sz", ref_ptr, rapl_id, buf, size);
+
+ /* Check args */
+ if(ref_ptr == NULL)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, (-1), "invalid reference pointer")
+ if(H5R__get_type((const H5R_ref_priv_t *)ref_ptr) <= H5R_BADTYPE
+ || H5R__get_type((const H5R_ref_priv_t *)ref_ptr) >= H5R_MAXTYPE)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, (-1), "invalid reference type")
+ if(rapl_id < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a property list")
- /* Get the file pointer from the entry */
- file = loc.oloc->file;
+ /* Retrieve loc_id from reference */
+ if(H5I_INVALID_HID == (loc_id = H5R__get_loc_id((const H5R_ref_priv_t *)ref_ptr))) {
+ /* Attempt to re-open file and pass rapl_id as a fapl_id */
+ if((loc_id = H5R__reopen_file((H5R_ref_priv_t *)ref_ptr, rapl_id)) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTOPENFILE, (-1), "cannot re-open referenced file")
+ }
- /* Get name */
- if((ret_value = H5R__get_name(file, id, ref_type, _ref, name, size)) < 0)
- HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, (-1), "unable to determine object path")
+ /* Get object token */
+ if((ret_value = H5R__get_obj_token((const H5R_ref_priv_t *)ref_ptr, &obj_token, NULL)) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, (-1), "unable to get object token")
+
+ /* Get the VOL object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "invalid location identifier")
+
+ /* Set location parameters */
+ loc_params.type = H5VL_OBJECT_BY_TOKEN;
+ loc_params.loc_data.loc_by_token.token = obj_token;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* Retrieve object's name */
+ if(H5VL_object_get(vol_obj, &loc_params, H5VL_OBJECT_GET_NAME, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &ret_value, buf, size) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, (-1), "can't retrieve object name")
done:
FUNC_LEAVE_API(ret_value)
-} /* end H5Rget_name() */
+} /* end H5Rget_obj_name() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Rget_attr_name
+ *
+ * Purpose: Given a reference to some attribute, determine its name.
+ *
+ * Return: Non-negative length of the path on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+ssize_t
+H5Rget_attr_name(const H5R_ref_t *ref_ptr, char *buf, size_t size)
+{
+ ssize_t ret_value; /* Return value */
+
+ FUNC_ENTER_API((-1))
+ H5TRACE3("Zs", "*Rr*sz", ref_ptr, buf, size);
+
+ /* Check args */
+ if(ref_ptr == NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, (-1), "invalid reference pointer")
+ if(H5R__get_type((const H5R_ref_priv_t *)ref_ptr) != H5R_ATTR)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, (-1), "invalid reference type")
+ /* Get attribute name */
+ if((ret_value = H5R__get_attr_name((const H5R_ref_priv_t *)ref_ptr, buf, size)) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, (-1), "unable to determine attribute name")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Rget_attr_name() */
diff --git a/src/H5RS.c b/src/H5RS.c
index 0a3fff0..ae500c5 100644
--- a/src/H5RS.c
+++ b/src/H5RS.c
@@ -137,7 +137,7 @@ done:
REVISION LOG
--------------------------------------------------------------------------*/
H5RS_str_t *
-H5RS_wrap(char *s)
+H5RS_wrap(const char *s)
{
H5RS_str_t *ret_value; /* Return value */
@@ -148,7 +148,7 @@ H5RS_wrap(char *s)
HGOTO_ERROR(H5E_RS, H5E_NOSPACE, NULL, "memory allocation failed")
/* Set the internal fields */
- ret_value->s = s;
+ ret_value->s = (char *)s;
ret_value->wrapped = 1;
ret_value->n = 1;
diff --git a/src/H5RSprivate.h b/src/H5RSprivate.h
index f69624a..1d26a18 100644
--- a/src/H5RSprivate.h
+++ b/src/H5RSprivate.h
@@ -44,7 +44,7 @@ typedef struct H5RS_str_t H5RS_str_t;
/* Private routines */
/********************/
H5_DLL H5RS_str_t *H5RS_create(const char *s);
-H5_DLL H5RS_str_t *H5RS_wrap(char *s);
+H5_DLL H5RS_str_t *H5RS_wrap(const char *s);
H5_DLL H5RS_str_t *H5RS_own(char *s);
H5_DLL herr_t H5RS_decr(H5RS_str_t *rs);
H5_DLL herr_t H5RS_incr(H5RS_str_t *rs);
diff --git a/src/H5Rdeprec.c b/src/H5Rdeprec.c
index 41765cf..b9bdffa 100644
--- a/src/H5Rdeprec.c
+++ b/src/H5Rdeprec.c
@@ -37,13 +37,15 @@
#include "H5Ppublic.h" /* Property lists */
/* Private headers needed by this file */
-#include "H5private.h" /* Generic Functions */
-#include "H5ACprivate.h" /* Metadata cache */
+#include "H5private.h" /* Generic Functions */
+#include "H5ACprivate.h" /* Metadata cache */
#include "H5CXprivate.h" /* API Contexts */
-#include "H5Eprivate.h" /* Error handling */
-#include "H5Gprivate.h" /* Groups */
-#include "H5Oprivate.h" /* Object headers */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Gprivate.h" /* Groups */
+#include "H5Iprivate.h" /* IDs */
+#include "H5Oprivate.h" /* Object headers */
#include "H5Rpkg.h" /* References */
+#include "H5Sprivate.h" /* Dataspaces */
/****************/
@@ -80,46 +82,58 @@
/* Local Variables */
/*******************/
-
#ifndef H5_NO_DEPRECATED_SYMBOLS
-
+
/*-------------------------------------------------------------------------
* Function: H5Rget_obj_type1
*
- * Purpose: Retrieves the type of the object that an object points to.
- *
- * Parameters:
- * id IN: Dataset reference object is in or location ID of
- * object that the dataset is located within
- * ref_type IN: Type of reference to query
- * ref IN: Reference to query
+ * Purpose: Retrieves the type of the object that a reference points to.
*
- * Return: Success: An object type (as defined in H5Gpublic.h)
- * Failure: H5G_UNKNOWN
+ * Return: Object type (as defined in H5Gpublic.h) on success
+ * H5G_UNKNOWN on failure
*
*-------------------------------------------------------------------------
*/
H5G_obj_t
H5Rget_obj_type1(hid_t id, H5R_type_t ref_type, const void *ref)
{
- H5G_loc_t loc; /* Object location */
- H5O_type_t obj_type; /* Object type */
- H5G_obj_t ret_value; /* Return value */
+ H5VL_object_t *vol_obj = NULL; /* Object token of loc_id */
+ H5I_type_t vol_obj_type = H5I_BADID;/* Object type of loc_id */
+ H5VL_loc_params_t loc_params; /* Location parameters */
+ H5VL_token_t obj_token = {0}; /* Object token */
+ H5O_type_t obj_type; /* Object type */
+ const unsigned char *buf = (const unsigned char *)ref; /* Reference buffer */
+ H5G_obj_t ret_value; /* Return value */
FUNC_ENTER_API(H5G_UNKNOWN)
H5TRACE3("Go", "iRt*x", id, ref_type, ref);
/* Check args */
- if (H5G_loc(id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5G_UNKNOWN, "not a location")
- if (ref_type <= H5R_BADTYPE || ref_type >= H5R_MAXTYPE)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5G_UNKNOWN, "invalid reference type")
- if (ref == NULL)
+ if(buf == NULL)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5G_UNKNOWN, "invalid reference pointer")
+ if(ref_type != H5R_OBJECT1 && ref_type != H5R_DATASET_REGION1)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5G_UNKNOWN, "invalid reference type")
+
+ /* Get the VOL object */
+ if(NULL == (vol_obj = H5VL_vol_object(id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5G_UNKNOWN, "invalid location identifier")
+
+ /* Get object type */
+ if((vol_obj_type = H5I_get_type(id)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5G_UNKNOWN, "invalid location identifier")
- /* Get the object information */
- if(H5R__get_obj_type(loc.oloc->file, ref_type, ref, &obj_type) < 0)
- HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, H5G_UNKNOWN, "unable to determine object type")
+ /* Get object token */
+ if(H5R__decode_token_compat(id, vol_obj_type, ref_type, buf, &obj_token) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, H5G_UNKNOWN, "unable to get object token")
+
+ /* Set location parameters */
+ loc_params.type = H5VL_OBJECT_BY_TOKEN;
+ loc_params.loc_data.loc_by_token.token = obj_token;
+ loc_params.obj_type = vol_obj_type;
+
+ /* Retrieve object's type */
+ if(H5VL_object_get(vol_obj, &loc_params, H5VL_OBJECT_GET_TYPE, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &obj_type) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, H5G_UNKNOWN, "can't retrieve object type")
/* Set return value */
ret_value = H5G_map_obj_type(obj_type);
@@ -132,43 +146,58 @@ done:
/*-------------------------------------------------------------------------
* Function: H5Rdereference1
*
- * Purpose: Opens the HDF5 object referenced.
+ * Purpose: Given a reference to some object, open that object and return an
+ * ID for that object.
*
- * Parameters:
- * id IN: Dataset reference object is in or location ID of
- * object that the dataset is located within
- * ref_type IN: Type of reference to create
- * ref IN: Reference to open
- *
- * Return: Success: Valid HDF5 ID
- * Failure: H5I_INVALID_HID
+ * Return: Valid ID on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
hid_t
-H5Rdereference1(hid_t obj_id, H5R_type_t ref_type, const void *_ref)
+H5Rdereference1(hid_t obj_id, H5R_type_t ref_type, const void *ref)
{
- H5G_loc_t loc; /* Group location */
- H5F_t *file = NULL; /* File object */
- hid_t ret_value = H5I_INVALID_HID; /* Return value */
+ H5VL_object_t *vol_obj = NULL; /* Object token of loc_id */
+ H5I_type_t vol_obj_type = H5I_BADID;/* Object type of loc_id */
+ H5VL_loc_params_t loc_params; /* Location parameters */
+ H5VL_token_t obj_token = {0}; /* Object token */
+ H5I_type_t opened_type; /* Opened object type */
+ void *opened_obj = NULL; /* Opened object */
+ const unsigned char *buf = (const unsigned char *)ref; /* Reference buffer */
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
FUNC_ENTER_API(H5I_INVALID_HID)
- H5TRACE3("i", "iRt*x", obj_id, ref_type, _ref);
+ H5TRACE3("i", "iRt*x", obj_id, ref_type, ref);
/* Check args */
- if (H5G_loc(obj_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a location")
- if (ref_type <= H5R_BADTYPE || ref_type >= H5R_MAXTYPE)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "invalid reference type")
- if (_ref == NULL)
+ if(buf == NULL)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "invalid reference pointer")
+ if(ref_type != H5R_OBJECT1 && ref_type != H5R_DATASET_REGION1)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "invalid reference type")
+
+ /* Get the VOL object */
+ if(NULL == (vol_obj = H5VL_vol_object(obj_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier")
+
+ /* Get object type */
+ if((vol_obj_type = H5I_get_type(obj_id)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier")
+
+ /* Get object token */
+ if(H5R__decode_token_compat(obj_id, vol_obj_type, ref_type, buf, &obj_token) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, H5I_INVALID_HID, "unable to get object token")
- /* Get the file pointer from the entry */
- file = loc.oloc->file;
+ /* Set location parameters */
+ loc_params.type = H5VL_OBJECT_BY_TOKEN;
+ loc_params.loc_data.loc_by_token.token = obj_token;
+ loc_params.obj_type = vol_obj_type;
/* Dereference */
- if((ret_value = H5R__dereference(file, H5P_DATASET_ACCESS_DEFAULT, ref_type, _ref)) < 0)
- HGOTO_ERROR(H5E_REFERENCE, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to dereference object")
+ if(NULL == (opened_obj = H5VL_object_open(vol_obj, &loc_params, &opened_type, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)))
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open object by token")
+
+ /* Register object */
+ if((ret_value = H5VL_register(opened_type, opened_obj, vol_obj->connector, TRUE)) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register object handle")
done:
FUNC_LEAVE_API(ret_value)
@@ -176,3 +205,361 @@ done:
#endif /* H5_NO_DEPRECATED_SYMBOLS */
+
+/*-------------------------------------------------------------------------
+ * Function: H5Rcreate
+ *
+ * Purpose: Creates a particular type of reference specified with REF_TYPE,
+ * in the space pointed to by REF. The LOC_ID and NAME are used to locate the
+ * object pointed to and the SPACE_ID is used to choose the region pointed to
+ * (for Dataset Region references).
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Rcreate(void *ref, hid_t loc_id, const char *name, H5R_type_t ref_type,
+ hid_t space_id)
+{
+ H5VL_object_t *vol_obj = NULL; /* Object token of loc_id */
+ H5I_type_t vol_obj_type = H5I_BADID;/* Object type of loc_id */
+ H5VL_loc_params_t loc_params; /* Location parameters */
+ H5VL_token_t obj_token = {0}; /* Object token */
+ H5VL_file_cont_info_t cont_info = {H5VL_CONTAINER_INFO_VERSION, 0, 0, 0};
+ hid_t file_id = H5I_INVALID_HID; /* File ID for region reference */
+ void *vol_obj_file = NULL;
+ unsigned char *buf = (unsigned char *)ref; /* Return reference pointer */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE5("e", "*xi*sRti", ref, loc_id, name, ref_type, space_id);
+
+ /* Check args */
+ if(buf == NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid reference pointer")
+ if(!name || !*name)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name given")
+ if(ref_type != H5R_OBJECT1 && ref_type != H5R_DATASET_REGION1)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid reference type")
+
+ /* Set up collective metadata if appropriate */
+ if(H5CX_set_loc(loc_id) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTSET, FAIL, "can't set access property list info")
+
+ /* Get the VOL object */
+ if(NULL == (vol_obj = H5VL_vol_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Get object type */
+ if((vol_obj_type = H5I_get_type(loc_id)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Set location parameters */
+ loc_params.type = H5VL_OBJECT_BY_NAME;
+ loc_params.loc_data.loc_by_name.name = name;
+ loc_params.obj_type = vol_obj_type;
+
+ /* Get the object token */
+ if(H5VL_object_specific(vol_obj, &loc_params, H5VL_OBJECT_LOOKUP, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, obj_token) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "unable to retrieve object token")
+
+ /* Get the file for the object */
+ if((file_id = H5F_get_file_id(loc_id, vol_obj_type, FALSE)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+
+ /* Retrieve VOL object */
+ if(NULL == (vol_obj_file = H5VL_vol_object(file_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Get container info */
+ if(H5VL_file_get(vol_obj_file, H5VL_FILE_GET_CONT_INFO, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &cont_info) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "unable to get container info")
+
+ /* Create reference */
+ if(ref_type == H5R_OBJECT1) {
+ size_t buf_size = H5R_OBJ_REF_BUF_SIZE;
+
+ if((ret_value = H5R__encode_token_obj_compat((const H5VL_token_t *)&obj_token, cont_info.token_size, buf, &buf_size)) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTENCODE, FAIL, "unable to encode object reference")
+ } else {
+ H5F_t *f = NULL;
+ H5S_t *space = NULL; /* Pointer to dataspace containing region */
+ size_t buf_size = H5R_DSET_REG_REF_BUF_SIZE;
+
+ /* Retrieve space */
+ if(space_id == H5I_BADID)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "reference region dataspace id must be valid")
+ if(NULL == (space = (struct H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
+
+ /* Currently restrict API usage to native VOL
+ * TODO check for terminal connector or use capability flag */
+
+ /* Retrieve file from VOL object */
+ if(NULL == (f = (H5F_t *)H5VL_object_data(vol_obj_file)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid VOL object")
+
+ /* Encode dataset region */
+ if((ret_value = H5R__encode_token_region_compat(f, (const H5VL_token_t *)&obj_token, cont_info.token_size, space, buf, &buf_size)) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTENCODE, FAIL, "unable to encode region reference")
+ }
+
+done:
+ if(file_id != H5I_INVALID_HID && H5I_dec_ref(file_id) < 0)
+ HDONE_ERROR(H5E_REFERENCE, H5E_CANTDEC, FAIL, "unable to decrement refcount on file")
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Rcreate() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Rget_obj_type2
+ *
+ * Purpose: Given a reference to some object, this function returns the type
+ * of object pointed to.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Rget_obj_type2(hid_t id, H5R_type_t ref_type, const void *ref,
+ H5O_type_t *obj_type)
+{
+ H5VL_object_t *vol_obj = NULL; /* Object token of loc_id */
+ H5I_type_t vol_obj_type = H5I_BADID;/* Object type of loc_id */
+ H5VL_loc_params_t loc_params; /* Location parameters */
+ H5VL_token_t obj_token = {0}; /* Object token */
+ const unsigned char *buf = (const unsigned char *)ref; /* Reference pointer */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE4("e", "iRt*x*Ot", id, ref_type, ref, obj_type);
+
+ /* Check args */
+ if(buf == NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid reference pointer")
+ if(ref_type != H5R_OBJECT1 && ref_type != H5R_DATASET_REGION1)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid reference type")
+
+ /* Get the VOL object */
+ if(NULL == (vol_obj = H5VL_vol_object(id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Get object type */
+ if((vol_obj_type = H5I_get_type(id)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Get object token */
+ if(H5R__decode_token_compat(id, vol_obj_type, ref_type, buf, &obj_token) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "unable to get object token")
+
+ /* Set location parameters */
+ loc_params.type = H5VL_OBJECT_BY_TOKEN;
+ loc_params.loc_data.loc_by_token.token = obj_token;
+ loc_params.obj_type = vol_obj_type;
+
+ /* Retrieve object's type */
+ if(H5VL_object_get(vol_obj, &loc_params, H5VL_OBJECT_GET_TYPE, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, obj_type) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, FAIL, "can't retrieve object type")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Rget_obj_type2() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Rdereference2
+ *
+ * Purpose: Given a reference to some object, open that object and return an
+ * ID for that object.
+ *
+ * Return: Valid ID on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5Rdereference2(hid_t obj_id, hid_t oapl_id, H5R_type_t ref_type,
+ const void *ref)
+{
+ H5VL_object_t *vol_obj = NULL; /* Object token of loc_id */
+ H5I_type_t vol_obj_type = H5I_BADID;/* Object type of loc_id */
+ H5VL_loc_params_t loc_params; /* Location parameters */
+ H5VL_token_t obj_token = {0}; /* Object token */
+ H5I_type_t opened_type; /* Opened object type */
+ void *opened_obj = NULL; /* Opened object */
+ const unsigned char *buf = (const unsigned char *)ref; /* Reference pointer */
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
+
+ FUNC_ENTER_API(H5I_INVALID_HID)
+ H5TRACE4("i", "iiRt*x", obj_id, oapl_id, ref_type, ref);
+
+ /* Check args */
+ if(oapl_id < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a property list")
+ if(buf == NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "invalid reference pointer")
+ if(ref_type != H5R_OBJECT1 && ref_type != H5R_DATASET_REGION1)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "invalid reference type")
+
+ /* Verify access property list and set up collective metadata if appropriate */
+ if(H5CX_set_apl(&oapl_id, H5P_CLS_DACC, obj_id, FALSE) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info")
+
+ /* Get the VOL object */
+ if(NULL == (vol_obj = H5VL_vol_object(obj_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid file identifier")
+
+ /* Get object type */
+ if((vol_obj_type = H5I_get_type(obj_id)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier")
+
+ /* Get object token */
+ if(H5R__decode_token_compat(obj_id, vol_obj_type, ref_type, buf, &obj_token) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, H5I_INVALID_HID, "unable to get object token")
+
+ /* Set location parameters */
+ loc_params.type = H5VL_OBJECT_BY_TOKEN;
+ loc_params.loc_data.loc_by_token.token = obj_token;
+ loc_params.obj_type = vol_obj_type;
+
+ /* Open object by token */
+ if(NULL == (opened_obj = H5VL_object_open(vol_obj, &loc_params, &opened_type, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)))
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open object by token")
+
+ /* Register object */
+ if((ret_value = H5VL_register(opened_type, opened_obj, vol_obj->connector, TRUE)) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register object handle")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Rdereference2() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Rget_region
+ *
+ * Purpose: Given a reference to some object, creates a copy of the dataset
+ * pointed to's dataspace and defines a selection in the copy which is the
+ * region pointed to.
+ *
+ * Return: Valid ID on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5Rget_region(hid_t id, H5R_type_t ref_type, const void *ref)
+{
+ H5VL_object_t *vol_obj = NULL; /* Object token of loc_id */
+ H5I_type_t vol_obj_type = H5I_BADID;/* Object type of loc_id */
+ void *vol_obj_file = NULL; /* VOL file */
+ H5VL_file_cont_info_t cont_info = {H5VL_CONTAINER_INFO_VERSION, 0, 0, 0};
+ H5F_t *f = NULL; /* Native file */
+ size_t buf_size = H5R_DSET_REG_REF_BUF_SIZE; /* Reference buffer size */
+ H5S_t *space = NULL; /* Dataspace object */
+ hid_t file_id = H5I_INVALID_HID; /* File ID for region reference */
+ const unsigned char *buf = (const unsigned char *)ref; /* Reference pointer */
+ hid_t ret_value; /* Return value */
+
+ FUNC_ENTER_API(H5I_INVALID_HID)
+ H5TRACE3("i", "iRt*x", id, ref_type, ref);
+
+ /* Check args */
+ if(buf == NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "invalid reference pointer")
+ if(ref_type != H5R_DATASET_REGION1)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "invalid reference type")
+
+ /* Get the VOL object */
+ if(NULL == (vol_obj = H5VL_vol_object(id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid file identifier")
+
+ /* Get object type */
+ if((vol_obj_type = H5I_get_type(id)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier")
+
+ /* Get the file for the object */
+ if((file_id = H5F_get_file_id(id, vol_obj_type, FALSE)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a file or file object")
+
+ /* Retrieve VOL object */
+ if(NULL == (vol_obj_file = H5VL_vol_object(file_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier")
+
+ /* Get container info */
+ if(H5VL_file_get(vol_obj_file, H5VL_FILE_GET_CONT_INFO, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &cont_info) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, H5I_INVALID_HID, "unable to get container info")
+
+ /* Retrieve file from VOL object */
+ if(NULL == (f = (H5F_t *)H5VL_object_data(vol_obj_file)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid VOL object")
+
+ /* Get the dataspace with the correct region selected */
+ if(H5R__decode_token_region_compat(f, buf, &buf_size, NULL, cont_info.token_size, &space) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, H5I_INVALID_HID, "unable to get dataspace")
+
+ /* Atomize */
+ if((ret_value = H5I_register(H5I_DATASPACE, space, TRUE)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register dataspace atom")
+
+done:
+ if(file_id != H5I_INVALID_HID && H5I_dec_ref(file_id) < 0)
+ HDONE_ERROR(H5E_REFERENCE, H5E_CANTDEC, H5I_INVALID_HID, "unable to decrement refcount on file")
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Rget_region1() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Rget_name
+ *
+ * Purpose: Given a reference to some object, determine a path to the object
+ * referenced in the file.
+ *
+ * Return: Non-negative length of the path on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+ssize_t
+H5Rget_name(hid_t id, H5R_type_t ref_type, const void *ref, char *name,
+ size_t size)
+{
+ H5VL_object_t *vol_obj = NULL; /* Object token of loc_id */
+ H5I_type_t vol_obj_type = H5I_BADID;/* Object type of loc_id */
+ H5VL_loc_params_t loc_params; /* Location parameters */
+ H5VL_token_t obj_token = {0}; /* Object token */
+ const unsigned char *buf = (const unsigned char *)ref; /* Reference pointer */
+ ssize_t ret_value = -1; /* Return value */
+
+ FUNC_ENTER_API((-1))
+ H5TRACE5("Zs", "iRt*x*sz", id, ref_type, ref, name, size);
+
+ /* Check args */
+ if(buf == NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, (-1), "invalid reference pointer")
+ if(ref_type != H5R_OBJECT1 && ref_type != H5R_DATASET_REGION1)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, (-1), "invalid reference type")
+
+ /* Get the VOL object */
+ if(NULL == (vol_obj = H5VL_vol_object(id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "invalid file identifier")
+
+ /* Get object type */
+ if((vol_obj_type = H5I_get_type(id)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "invalid location identifier")
+
+ /* Get object token */
+ if(H5R__decode_token_compat(id, vol_obj_type, ref_type, buf, &obj_token) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, (-1), "unable to get object token")
+
+ /* Set location parameters */
+ loc_params.type = H5VL_OBJECT_BY_TOKEN;
+ loc_params.loc_data.loc_by_token.token = obj_token;
+ loc_params.obj_type = vol_obj_type;
+
+ /* Retrieve object's name */
+ if(H5VL_object_get(vol_obj, &loc_params, H5VL_OBJECT_GET_NAME, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &ret_value, name, size) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, (-1), "can't retrieve object name")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Rget_name() */
diff --git a/src/H5Rint.c b/src/H5Rint.c
index 1bbe217..443a245 100644
--- a/src/H5Rint.c
+++ b/src/H5Rint.c
@@ -23,6 +23,7 @@
/***********/
#include "H5private.h" /* Generic Functions */
#include "H5ACprivate.h" /* Metadata cache */
+#include "H5CXprivate.h" /* API Contexts */
#include "H5Dprivate.h" /* Datasets */
#include "H5Eprivate.h" /* Error handling */
#include "H5Gprivate.h" /* Groups */
@@ -34,11 +35,73 @@
#include "H5Sprivate.h" /* Dataspaces */
#include "H5Tprivate.h" /* Datatypes */
-
/****************/
/* Local Macros */
/****************/
+#define H5R_MAX_STRING_LEN (1 << 16) /* Max encoded string length */
+
+/* Encode macro */
+#define H5R_ENCODE(func, val, buf, buf_size, actual, m) do {\
+ size_t __nalloc = buf_size; \
+ if(func(val, buf, &__nalloc) < 0) \
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTENCODE, FAIL, m) \
+ if(buf && buf_size >= __nalloc) { \
+ buf += __nalloc; \
+ buf_size -= __nalloc; \
+ } \
+ actual += __nalloc; \
+} while(0)
+
+#define H5R_ENCODE_VAR(func, var, size, buf, buf_size, actual, m) do { \
+ size_t __nalloc = buf_size; \
+ if(func(var, size, buf, &__nalloc) < 0) \
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTENCODE, FAIL, m) \
+ if(buf && buf_size >= __nalloc) { \
+ p += __nalloc; \
+ buf_size -= __nalloc; \
+ } \
+ actual += __nalloc; \
+} while(0)
+
+/* Decode macro */
+#define H5R_DECODE(func, val, buf, buf_size, actual, m) do {\
+ size_t __nbytes = buf_size; \
+ if(func(buf, &__nbytes, val) < 0) \
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, m) \
+ buf += __nbytes; \
+ buf_size -= __nbytes; \
+ actual += __nbytes; \
+} while(0)
+
+#define H5R_DECODE_VAR(func, var, size, buf, buf_size, actual, m) do { \
+ size_t __nbytes = buf_size; \
+ if(func(buf, &__nbytes, var, size) < 0) \
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, m) \
+ p += __nbytes; \
+ buf_size -= __nbytes; \
+ actual += __nbytes; \
+} while(0)
+
+/* Debug */
+//#define H5R_DEBUG
+#ifdef H5R_DEBUG
+#define H5R_LOG_DEBUG(...) do { \
+ HDfprintf(stdout, " # %s(): ", __func__); \
+ HDfprintf(stdout, __VA_ARGS__); \
+ HDfprintf(stdout, "\n"); \
+ HDfflush(stdout); \
+ } while (0)
+static const char *
+H5R__print_token(const H5VL_token_t token) {
+ static char string[64];
+ HDsnprintf(string, 64, "%zu", *(haddr_t *)token);
+ return string;
+}
+#else
+#define H5R_LOG_DEBUG(...) do { } while (0)
+#endif
+
/******************/
/* Local Typedefs */
/******************/
@@ -47,6 +110,13 @@
/* Local Prototypes */
/********************/
+static herr_t H5R__encode_obj_token(const H5VL_token_t *obj_token, size_t token_size, unsigned char *buf, size_t *nalloc);
+static herr_t H5R__decode_obj_token(const unsigned char *buf, size_t *nbytes, H5VL_token_t *obj_token, uint8_t *token_size);
+static herr_t H5R__encode_region(H5S_t *space, unsigned char *buf, size_t *nalloc);
+static herr_t H5R__decode_region(const unsigned char *buf, size_t *nbytes, H5S_t **space_ptr);
+static herr_t H5R__encode_string(const char *string, unsigned char *buf, size_t *nalloc);
+static herr_t H5R__decode_string(const unsigned char *buf, size_t *nbytes, char **string_ptr);
+
/*********************/
/* Package Variables */
/*********************/
@@ -62,18 +132,6 @@ hbool_t H5_PKG_INIT_VAR = FALSE;
/* Local Variables */
/*******************/
-/* Reference ID class
- *
- * NOTE: H5I_REFERENCE is not used by the library and has been deprecated
- * with a tentative removal version of 1.12.0. (DER, July 2017)
- */
-static const H5I_class_t H5I_REFERENCE_CLS[1] = {{
- H5I_REFERENCE, /* ID class value */
- 0, /* Class flags */
- 0, /* # of reserved IDs for class */
- NULL /* Callback routine for closing objects of this class */
-}};
-
/* Flag indicating "top" of interface has been initialized */
static hbool_t H5R_top_package_initialize_s = FALSE;
@@ -93,19 +151,15 @@ DESCRIPTION
herr_t
H5R__init_package(void)
{
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT
-
- /* Initialize the atom group for the file IDs */
- if (H5I_register_type(H5I_REFERENCE_CLS) < 0)
- HGOTO_ERROR(H5E_REFERENCE, H5E_CANTINIT, FAIL, "unable to initialize interface")
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
- /* Mark "top" of interface as initialized, too */
+ /* Mark "top" of interface as initialized */
H5R_top_package_initialize_s = TRUE;
-done:
- FUNC_LEAVE_NOAPI(ret_value)
+ /* Sanity check, if assert fails, H5R_REF_BUF_SIZE must be increased */
+ HDcompile_assert(sizeof(H5R_ref_priv_t) <= H5R_REF_BUF_SIZE);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5R__init_package() */
@@ -134,16 +188,10 @@ H5R_top_term_package(void)
FUNC_ENTER_NOAPI_NOINIT_NOERR
- if (H5R_top_package_initialize_s) {
- if (H5I_nmembers(H5I_REFERENCE) > 0) {
- (void)H5I_clear_type(H5I_REFERENCE, FALSE, FALSE);
- n++;
- }
-
- /* Mark closed */
- if (0 == n)
+ /* Mark closed if initialized */
+ if(H5R_top_package_initialize_s)
+ if(0 == n)
H5R_top_package_initialize_s = FALSE;
- }
FUNC_LEAVE_NOAPI(n)
} /* end H5R_top_term_package() */
@@ -176,16 +224,12 @@ H5R_term_package(void)
FUNC_ENTER_NOAPI_NOINIT_NOERR
- if (H5_PKG_INIT_VAR) {
+ if(H5_PKG_INIT_VAR) {
/* Sanity checks */
- HDassert(0 == H5I_nmembers(H5I_REFERENCE));
HDassert(FALSE == H5R_top_package_initialize_s);
- /* Destroy the reference id group */
- n += (H5I_dec_type_ref(H5I_REFERENCE) > 0);
-
/* Mark closed */
- if (0 == n)
+ if(0 == n)
H5_PKG_INIT_VAR = FALSE;
}
@@ -193,574 +237,1488 @@ H5R_term_package(void)
} /* end H5R_term_package() */
-/*--------------------------------------------------------------------------
- NAME
- H5R__create
- PURPOSE
- Creates a particular kind of reference for the user
- USAGE
- herr_t H5R__create(ref, loc, name, ref_type, space)
- void *ref; OUT: Reference created
- H5G_loc_t *loc; IN: File location used to locate object pointed to
- const char *name; IN: Name of object at location LOC_ID of object
- pointed to
- H5R_type_t ref_type; IN: Type of reference to create
- H5S_t *space; IN: Dataspace ID with selection, used for Dataset
- Region references.
+/*-------------------------------------------------------------------------
+ * Function: H5R__create_object
+ *
+ * Purpose: Creates an object reference.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5R__create_object(const H5VL_token_t *obj_token, size_t token_size,
+ H5R_ref_priv_t *ref)
+{
+ size_t encode_size;
+ herr_t ret_value = SUCCEED; /* Return value */
- RETURNS
- Non-negative on success/Negative on failure
- DESCRIPTION
- Creates a particular type of reference specified with REF_TYPE, in the
- space pointed to by REF. The LOC_ID and NAME are used to locate the object
- pointed to and the SPACE_ID is used to choose the region pointed to (for
- Dataset Region references).
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
+ FUNC_ENTER_PACKAGE
+
+ HDassert(ref);
+
+ /* Create new reference */
+ H5MM_memcpy(ref->ref.obj.token, obj_token, token_size);
+ ref->ref.obj.filename = NULL;
+ ref->loc_id = H5I_INVALID_HID;
+ ref->type = (uint8_t)H5R_OBJECT2;
+ ref->token_size = (uint8_t)token_size;
+
+ /* Cache encoding size (assume no external reference) */
+ if(H5R__encode(NULL, ref, NULL, &encode_size, 0) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTENCODE, FAIL, "unable to determine encoding size")
+ ref->encode_size = (uint32_t)encode_size;
+
+ H5R_LOG_DEBUG("Created object reference, %d, filename=%s, obj_addr=%s, encode size=%u",
+ (int)sizeof(H5R_ref_priv_t), ref->ref.obj.filename, H5R__print_token(ref->ref.obj.token),
+ ref->encode_size);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__create_object() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__create_region
+ *
+ * Purpose: Creates a region reference.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
herr_t
-H5R__create(void *_ref, H5G_loc_t *loc, const char *name, H5R_type_t ref_type, H5S_t *space)
+H5R__create_region(const H5VL_token_t *obj_token, size_t token_size,
+ H5S_t *space, H5R_ref_priv_t *ref)
{
- H5G_loc_t obj_loc; /* Group hier. location of object */
- H5G_name_t path; /* Object group hier. path */
- H5O_loc_t oloc; /* Object object location */
- hbool_t obj_found = FALSE; /* Object location found */
- herr_t ret_value = SUCCEED; /* Return value */
+ size_t encode_size;
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
- HDassert(_ref);
- HDassert(loc);
- HDassert(name);
- HDassert(ref_type > H5R_BADTYPE && ref_type < H5R_MAXTYPE);
+ HDassert(space);
+ HDassert(ref);
- /* Set up object location to fill in */
- obj_loc.oloc = &oloc;
- obj_loc.path = &path;
- H5G_loc_reset(&obj_loc);
+ /* Create new reference */
+ H5MM_memcpy(ref->ref.obj.token, obj_token, token_size);
+ ref->ref.obj.filename = NULL;
+ if(NULL == (ref->ref.reg.space = H5S_copy(space, FALSE, TRUE)))
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCOPY, FAIL, "unable to copy dataspace")
- /* Find the object */
- if(H5G_loc_find(loc, name, &obj_loc) < 0)
- HGOTO_ERROR(H5E_REFERENCE, H5E_NOTFOUND, FAIL, "object not found")
- obj_found = TRUE;
+ ref->loc_id = H5I_INVALID_HID;
+ ref->type = (uint8_t)H5R_DATASET_REGION2;
+ ref->token_size = (uint8_t)token_size;
- switch (ref_type) {
- case H5R_OBJECT:
- {
- hobj_ref_t *ref = (hobj_ref_t *)_ref; /* Get pointer to correct type of reference struct */
+ /* Cache encoding size (assume no external reference) */
+ if(H5R__encode(NULL, ref, NULL, &encode_size, 0) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTENCODE, FAIL, "unable to determine encoding size")
+ ref->encode_size = (uint32_t)encode_size;
- *ref = obj_loc.oloc->addr;
- break;
+ H5R_LOG_DEBUG("Created region reference, %d, filename=%s, obj_addr=%s, encode size=%u",
+ (int)sizeof(H5R_ref_priv_t), ref->ref.obj.filename, H5R__print_token(ref->ref.obj.token),
+ ref->encode_size);
+
+done:
+ if(ret_value < 0) {
+ if(ref->ref.reg.space) {
+ H5S_close(ref->ref.reg.space);
+ ref->ref.reg.space = NULL;
}
+ }
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5R__create_region */
- case H5R_DATASET_REGION:
- {
- H5HG_t hobjid; /* Heap object ID */
- hdset_reg_ref_t *ref = (hdset_reg_ref_t *)_ref; /* Get pointer to correct type of reference struct */
- hssize_t buf_size; /* Size of buffer needed to serialize selection */
- uint8_t *p; /* Pointer to OID to store */
- uint8_t *buf; /* Buffer to store serialized selection in */
- unsigned heapid_found; /* Flag for non-zero heap ID found */
- unsigned u; /* local index */
-
- /* Set up information for dataset region */
-
- /* Return any previous heap block to the free list if we are
- * garbage collecting
- */
- if (H5F_GC_REF(loc->oloc->file)) {
- /* Check for an existing heap ID in the reference */
- for (u = 0, heapid_found = 0, p = (uint8_t *)ref; u < H5R_DSET_REG_REF_BUF_SIZE; u++)
- if (p[u] != 0) {
- heapid_found = 1;
- break;
- }
-
- if (heapid_found != 0) {
- /* Return heap block to free list */
- }
- }
-
- /* Zero the heap ID out, may leak heap space if user is re-using
- * reference and doesn't have garbage collection turned on
- */
- HDmemset(ref, 0, H5R_DSET_REG_REF_BUF_SIZE);
-
- /* Get the amount of space required to serialize the selection */
- if ((buf_size = H5S_SELECT_SERIAL_SIZE(space)) < 0)
- HGOTO_ERROR(H5E_REFERENCE, H5E_CANTINIT, FAIL, "Invalid amount of space for serializing selection")
-
- /* Increase buffer size to allow for the dataset OID */
- buf_size += (hssize_t)sizeof(haddr_t);
-
- /* Allocate the space to store the serialized information */
- H5_CHECK_OVERFLOW(buf_size, hssize_t, size_t);
- if (NULL == (buf = (uint8_t *)H5MM_malloc((size_t)buf_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
-
- /* Serialize information for dataset OID into heap buffer */
- p = (uint8_t *)buf;
- H5F_addr_encode(loc->oloc->file, &p, obj_loc.oloc->addr);
-
- /* Serialize the selection into heap buffer */
- if (H5S_SELECT_SERIALIZE(space, &p) < 0)
- HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCOPY, FAIL, "Unable to serialize selection")
-
- /* Save the serialized buffer for later */
- H5_CHECK_OVERFLOW(buf_size, hssize_t, size_t);
- if(H5HG_insert(loc->oloc->file, (size_t)buf_size, buf, &hobjid) < 0)
- HGOTO_ERROR(H5E_REFERENCE, H5E_WRITEERROR, FAIL, "Unable to serialize selection")
-
- /* Serialize the heap ID and index for storage in the file */
- p = (uint8_t *)ref;
- H5F_addr_encode(loc->oloc->file, &p, hobjid.addr);
- UINT32ENCODE(p, hobjid.idx);
-
- /* Free the buffer we serialized data in */
- H5MM_xfree(buf);
- break;
- } /* end case H5R_DATASET_REGION */
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__create_attr
+ *
+ * Purpose: Creates an attribute reference.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5R__create_attr(const H5VL_token_t *obj_token, size_t token_size,
+ const char *attr_name, H5R_ref_priv_t *ref)
+{
+ size_t encode_size;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ HDassert(attr_name);
+ HDassert(ref);
+
+ /* Make sure that attribute name is not longer than supported encode size */
+ if(HDstrlen(attr_name) > H5R_MAX_STRING_LEN)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_ARGS, FAIL, "attribute name too long (%d > %d)", (int)HDstrlen(attr_name), H5R_MAX_STRING_LEN)
+
+ /* Create new reference */
+ H5MM_memcpy(ref->ref.obj.token, obj_token, token_size);
+ ref->ref.obj.filename = NULL;
+ if(NULL == (ref->ref.attr.name = HDstrdup(attr_name)))
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCOPY, FAIL, "Cannot copy attribute name")
+
+ ref->loc_id = H5I_INVALID_HID;
+ ref->type = (uint8_t)H5R_ATTR;
+ ref->token_size = (uint8_t)token_size;
+ /* Cache encoding size (assume no external reference) */
+ if(H5R__encode(NULL, ref, NULL, &encode_size, 0) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTENCODE, FAIL, "unable to determine encoding size")
+ ref->encode_size = (uint32_t)encode_size;
+
+ H5R_LOG_DEBUG("Created attribute reference, %d, filename=%s, obj_addr=%s, attr name=%s, encode size=%u",
+ (int)sizeof(H5R_ref_priv_t), ref->ref.obj.filename, H5R__print_token(ref->ref.obj.token),
+ ref->ref.attr.name, ref->encode_size);
+
+done:
+ if(ret_value < 0)
+ ref->ref.attr.name = H5MM_xfree(ref->ref.attr.name);
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5R__create_attr */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__destroy
+ *
+ * Purpose: Destroy reference.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5R__destroy(H5R_ref_priv_t *ref)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ HDassert(ref != NULL);
+
+ ref->ref.obj.filename = H5MM_xfree(ref->ref.obj.filename);
+
+ switch(ref->type) {
+ case H5R_OBJECT2:
+ break;
+ case H5R_DATASET_REGION2:
+ if(H5S_close(ref->ref.reg.space) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTFREE, FAIL, "Cannot close dataspace")
+ ref->ref.reg.space = NULL;
+ break;
+ case H5R_ATTR:
+ ref->ref.attr.name = H5MM_xfree(ref->ref.attr.name);
+ break;
+ case H5R_OBJECT1:
+ case H5R_DATASET_REGION1:
case H5R_BADTYPE:
case H5R_MAXTYPE:
+ HDassert("invalid reference type" && 0);
+ HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, FAIL, "internal error (invalid reference type)")
default:
HDassert("unknown reference type" && 0);
HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, FAIL, "internal error (unknown reference type)")
} /* end switch */
-done:
- if (obj_found)
- H5G_loc_free(&obj_loc);
+ /* Decrement refcount of attached loc_id */
+ if((ref->loc_id != H5I_INVALID_HID) && (H5I_dec_ref(ref->loc_id) < 0))
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDEC, FAIL, "decrementing location ID failed")
+done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5R__create() */
+} /* end H5R__destroy() */
-/*--------------------------------------------------------------------------
- NAME
- H5R__dereference
- PURPOSE
- Opens the HDF5 object referenced.
- USAGE
- hid_t H5R__dereference(ref, oapl_id, ref_type, ref)
- H5F_t *file; IN: File the object being dereferenced is within
- hid_t oapl_id; IN: Object access property list ID
- H5R_type_t ref_type; IN: Type of reference
- void *ref; IN: Reference to open.
+/*-------------------------------------------------------------------------
+ * Function: H5R__set_loc_id
+ *
+ * Purpose: Attach location ID to reference and increment location refcount.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5R__set_loc_id(H5R_ref_priv_t *ref, hid_t id, hbool_t inc_ref)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
- RETURNS
- Valid ID on success, Negative on failure
- DESCRIPTION
- Given a reference to some object, open that object and return an ID for
- that object.
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- Currently only set up to work with references to datasets
- EXAMPLES
- REVISION LOG
- Raymond Lu
- 13 July 2011
- I added the OAPL_ID parameter for the object being referenced. It only
- supports dataset access property list currently.
-
- M. Scot Breitenfeld
- 3 March 2015
- Added a check for undefined reference pointer.
---------------------------------------------------------------------------*/
+ FUNC_ENTER_PACKAGE
+
+ HDassert(ref != NULL);
+ HDassert(id != H5I_INVALID_HID);
+
+ /* If a location ID was previously assigned, decrement refcount and assign new one */
+ if((ref->loc_id != H5I_INVALID_HID) && (H5I_dec_ref(ref->loc_id) < 0))
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDEC, FAIL, "decrementing location ID failed")
+ ref->loc_id = id;
+
+ /* Prevent location ID from being freed until reference is destroyed */
+ if(inc_ref && H5I_inc_ref(ref->loc_id, FALSE) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTINC, FAIL, "incrementing location ID failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__set_loc_id() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__get_loc_id
+ *
+ * Purpose: Retrieve location ID attached to existing reference.
+ *
+ * Return: Valid ID on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
hid_t
-H5R__dereference(H5F_t *file, hid_t oapl_id, H5R_type_t ref_type, const void *_ref)
+H5R__get_loc_id(const H5R_ref_priv_t *ref)
{
- H5O_loc_t oloc; /* Object location */
- H5G_name_t path; /* Path of object */
- H5G_loc_t loc; /* Group location */
- unsigned rc; /* Reference count of object */
- H5O_type_t obj_type; /* Type of object */
hid_t ret_value = H5I_INVALID_HID; /* Return value */
+ FUNC_ENTER_PACKAGE_NOERR
+
+ HDassert(ref != NULL);
+
+ ret_value = ref->loc_id;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__get_loc_id() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__reopen_file
+ *
+ * Purpose: Re-open referenced file using file access property list.
+ *
+ * Return: Valid ID on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5R__reopen_file(H5R_ref_priv_t *ref, hid_t fapl_id)
+{
+ void *new_file = NULL;
+ H5VL_connector_prop_t connector_prop;
+ unsigned flags = H5F_ACC_RDWR; /* Must open file read-write to allow for object modifications */
+ H5P_genplist_t *plist;
+ hid_t ret_value = H5I_INVALID_HID;
+
FUNC_ENTER_PACKAGE
- HDassert(_ref);
- HDassert(ref_type > H5R_BADTYPE && ref_type < H5R_MAXTYPE);
- HDassert(file);
+ /* TODO add search path */
- /* Initialize the object location */
- H5O_loc_reset(&oloc);
- oloc.file = file;
+ /* Verify access property list and set up collective metadata if appropriate */
+ if(H5CX_set_apl(&fapl_id, H5P_CLS_FACC, H5I_INVALID_HID, TRUE) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info")
- switch (ref_type) {
- case H5R_OBJECT:
- {
- oloc.addr = *(const hobj_ref_t *)_ref; /* Only object references currently supported */
- if (!H5F_addr_defined(oloc.addr) || oloc.addr == 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "Undefined reference pointer")
- break;
- }
+ /* Get the VOL info from the fapl */
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a file access property list")
+ if(H5P_peek(plist, H5F_ACS_VOL_CONN_NAME, &connector_prop) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, H5I_INVALID_HID, "can't get VOL connector info")
+
+ /* Stash a copy of the "top-level" connector property, before any pass-through
+ * connectors modify or unwrap it.
+ */
+ if(H5CX_set_vol_connector_prop(&connector_prop) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set VOL connector info in API context")
+
+ /* Open the file */
+ if(NULL == (new_file = H5VL_file_open(&connector_prop, H5R_REF_FILENAME(ref), flags, fapl_id, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, H5I_INVALID_HID, "unable to open file")
+
+ /* Get an ID for the file */
+ if((ret_value = H5VL_register_using_vol_id(H5I_FILE, new_file, connector_prop.connector_id, TRUE)) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to atomize file handle")
- case H5R_DATASET_REGION:
- {
- H5HG_t hobjid; /* Heap object ID */
- uint8_t *buf; /* Buffer to store serialized selection in */
- const uint8_t *p; /* Pointer to OID to store */
+ /* Attach loc_id to reference */
+ if(H5R__set_loc_id((H5R_ref_priv_t *)ref, ret_value, FALSE) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTSET, H5I_INVALID_HID, "unable to attach location id to reference")
- /* Get the heap ID for the dataset region */
- p = (const uint8_t *)_ref;
- H5F_addr_decode(oloc.file, &p, &(hobjid.addr));
- UINT32DECODE(p, hobjid.idx);
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__reopen_file() */
- if (!H5F_addr_defined(hobjid.addr) || hobjid.addr == 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "Undefined reference pointer")
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__get_type
+ *
+ * Purpose: Given a reference to some object, return the type of that reference.
+ *
+ * Return: Type of the reference
+ *
+ *-------------------------------------------------------------------------
+ */
+H5R_type_t
+H5R__get_type(const H5R_ref_priv_t *ref)
+{
+ H5R_type_t ret_value = H5R_BADTYPE;
- /* Get the dataset region from the heap (allocate inside routine) */
- if(NULL == (buf = (uint8_t *)H5HG_read(oloc.file, &hobjid, NULL, NULL)))
- HGOTO_ERROR(H5E_REFERENCE, H5E_READERROR, H5I_INVALID_HID, "Unable to read dataset region information")
+ FUNC_ENTER_PACKAGE_NOERR
- /* Get the object oid for the dataset */
- p = buf;
- H5F_addr_decode(oloc.file, &p, &(oloc.addr));
+ HDassert(ref != NULL);
+ ret_value = ref->type;
- /* Free the buffer allocated in H5HG_read() */
- H5MM_xfree(buf);
- break;
- } /* end case H5R_DATASET_REGION */
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__get_type() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__equal
+ *
+ * Purpose: Compare two references
+ *
+ * Return: TRUE if equal, FALSE if unequal, FAIL if error
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5R__equal(const H5R_ref_priv_t *ref1, const H5R_ref_priv_t *ref2)
+{
+ htri_t ret_value = TRUE;
+
+ FUNC_ENTER_PACKAGE
+
+ HDassert(ref1 != NULL);
+ HDassert(ref2 != NULL);
+
+ /* Compare reference types */
+ if(ref1->type != ref2->type)
+ HGOTO_DONE(FALSE);
+
+ /* Compare object addresses */
+ if(ref1->token_size != ref2->token_size)
+ HGOTO_DONE(FALSE);
+ if(0 != HDmemcmp(ref1->ref.obj.token, ref2->ref.obj.token, ref1->token_size))
+ HGOTO_DONE(FALSE);
+
+ /* Compare filenames */
+ if((ref1->ref.obj.filename && (NULL == ref2->ref.obj.filename))
+ || ((NULL == ref1->ref.obj.filename) && ref2->ref.obj.filename))
+ HGOTO_DONE(FALSE);
+ if(ref1->ref.obj.filename && ref1->ref.obj.filename
+ && (0 != HDstrcmp(ref1->ref.obj.filename, ref2->ref.obj.filename)))
+ HGOTO_DONE(FALSE);
+
+ switch(ref1->type) {
+ case H5R_OBJECT2:
+ break;
+ case H5R_DATASET_REGION2:
+ if((ret_value = H5S_extent_equal(ref1->ref.reg.space, ref2->ref.reg.space)) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCOMPARE, FAIL, "cannot compare dataspace extents")
+ break;
+ case H5R_ATTR:
+ HDassert(ref1->ref.attr.name && ref2->ref.attr.name);
+ if(0 != HDstrcmp(ref1->ref.attr.name, ref2->ref.attr.name))
+ HGOTO_DONE(FALSE);
+ break;
+ case H5R_OBJECT1:
+ case H5R_DATASET_REGION1:
case H5R_BADTYPE:
case H5R_MAXTYPE:
+ HDassert("invalid reference type" && 0);
+ HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, FAIL, "internal error (invalid reference type)")
default:
HDassert("unknown reference type" && 0);
- HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, H5I_INVALID_HID, "internal error (unknown reference type)")
+ HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, FAIL, "internal error (unknown reference type)")
} /* end switch */
- /* Get the # of links for object, and its type
- * (To check to make certain that this object hasn't been deleted
- * since the reference was created)
- */
- if(H5O_get_rc_and_type(&oloc, &rc, &obj_type) < 0 || 0 == rc)
- HGOTO_ERROR(H5E_REFERENCE, H5E_LINKCOUNT, H5I_INVALID_HID, "dereferencing deleted object")
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__equal() */
- /* Construct a group location for opening the object */
- H5G_name_reset(&path);
- loc.oloc = &oloc;
- loc.path = &path;
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__copy
+ *
+ * Purpose: Copy a reference
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5R__copy(const H5R_ref_priv_t *src_ref, H5R_ref_priv_t *dst_ref)
+{
+ herr_t ret_value = SUCCEED;
- /* Open the object */
- switch (obj_type) {
- case H5O_TYPE_GROUP:
- {
- H5G_t *group; /* Pointer to group to open */
+ FUNC_ENTER_PACKAGE
- if(NULL == (group = H5G_open(&loc)))
- HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5I_INVALID_HID, "not found")
+ HDassert((src_ref != NULL) && (dst_ref != NULL));
- /* Create an atom for the group */
- if((ret_value = H5I_register(H5I_GROUP, group, TRUE)) < 0) {
- H5G_close(group);
- HGOTO_ERROR(H5E_SYM, H5E_CANTREGISTER, H5I_INVALID_HID, "can't register group")
- }
+ H5MM_memcpy(dst_ref->ref.obj.token, src_ref->ref.obj.token, src_ref->token_size);
+ dst_ref->encode_size = src_ref->encode_size;
+ dst_ref->type = src_ref->type;
+ dst_ref->token_size = src_ref->token_size;
+ switch(src_ref->type) {
+ case H5R_OBJECT2:
break;
- }
-
- case H5O_TYPE_NAMED_DATATYPE:
- {
- H5T_t *type; /* Pointer to datatype to open */
+ case H5R_DATASET_REGION2:
+ if(NULL == (dst_ref->ref.reg.space = H5S_copy(src_ref->ref.reg.space, FALSE, TRUE)))
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCOPY, FAIL, "unable to copy dataspace")
+ break;
+ case H5R_ATTR:
+ if(NULL == (dst_ref->ref.attr.name = HDstrdup(src_ref->ref.attr.name)))
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCOPY, FAIL, "Cannot copy attribute name")
+ break;
+ case H5R_OBJECT1:
+ case H5R_DATASET_REGION1:
+ HDassert("invalid reference type" && 0);
+ HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, FAIL, "internal error (invalid reference type)")
+ case H5R_BADTYPE:
+ case H5R_MAXTYPE:
+ default:
+ HDassert("unknown reference type" && 0);
+ HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, FAIL, "internal error (unknown reference type)")
+ } /* end switch */
- if(NULL == (type = H5T_open(&loc)))
- HGOTO_ERROR(H5E_DATATYPE, H5E_NOTFOUND, H5I_INVALID_HID, "not found")
+ /* We only need to keep a copy of the filename if we don't have the loc_id */
+ if(src_ref->loc_id == H5I_INVALID_HID) {
+ HDassert(src_ref->ref.obj.filename);
- /* Create an atom for the datatype */
- if((ret_value = H5I_register(H5I_DATATYPE, type, TRUE)) < 0) {
- H5T_close(type);
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, H5I_INVALID_HID, "can't register datatype")
- }
+ if(NULL == (dst_ref->ref.obj.filename = HDstrdup(src_ref->ref.obj.filename)))
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCOPY, FAIL, "Cannot copy filename")
+ dst_ref->loc_id = H5I_INVALID_HID;
+ } else {
+ dst_ref->ref.obj.filename = NULL;
- break;
- }
+ /* Set location ID and hold reference to it */
+ if(H5R__set_loc_id(dst_ref, src_ref->loc_id, TRUE) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTSET, FAIL, "cannot set reference location ID")
+ }
- case H5O_TYPE_DATASET:
- {
- H5D_t *dset; /* Pointer to dataset to open */
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__copy() */
- /* Open the dataset */
- if(NULL == (dset = H5D_open(&loc, oapl_id)))
- HGOTO_ERROR(H5E_DATASET, H5E_NOTFOUND, H5I_INVALID_HID, "not found")
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__get_obj_token
+ *
+ * Purpose: Given a reference to some object, get the encoded object addr.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5R__get_obj_token(const H5R_ref_priv_t *ref, H5VL_token_t *obj_token,
+ size_t *token_size)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
- /* Create an atom for the dataset */
- if((ret_value = H5I_register(H5I_DATASET, dset, TRUE)) < 0) {
- H5D_close(dset);
- HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, H5I_INVALID_HID, "can't register dataset")
- }
+ FUNC_ENTER_PACKAGE
- break;
- }
+ HDassert(ref != NULL);
+ HDassert(ref->token_size <= H5VL_MAX_TOKEN_SIZE);
- case H5O_TYPE_UNKNOWN:
- case H5O_TYPE_NTYPES:
- default:
- HGOTO_ERROR(H5E_REFERENCE, H5E_BADTYPE, H5I_INVALID_HID, "can't identify type of object referenced")
- } /* end switch */
+ if(obj_token) {
+ if(0 == ref->token_size)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCOPY, FAIL, "NULL token size")
+ H5MM_memcpy(obj_token, ref->ref.obj.token, ref->token_size);
+ }
+ if(token_size)
+ *token_size = ref->token_size;
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5R__dereference() */
+} /* end H5R__get_obj_token() */
-/*--------------------------------------------------------------------------
- NAME
- H5R__get_region
- PURPOSE
- Retrieves a dataspace with the region pointed to selected.
- USAGE
- H5S_t *H5R__get_region(file, ref)
- H5F_t *file; IN: File the object being dereferenced is within
- void *ref; IN: Reference to open.
+/*-------------------------------------------------------------------------
+ * Function: H5R__set_obj_token
+ *
+ * Purpose: Given a reference to some object, set the encoded object addr.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5R__set_obj_token(H5R_ref_priv_t *ref, const H5VL_token_t *obj_token,
+ size_t token_size)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
- RETURNS
- Pointer to the dataspace on success, NULL on failure
- DESCRIPTION
- Given a reference to some object, creates a copy of the dataset pointed
- to's dataspace and defines a selection in the copy which is the region
- pointed to.
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
-H5S_t *
-H5R__get_region(H5F_t *file, const void *_ref)
+ FUNC_ENTER_PACKAGE_NOERR
+
+ HDassert(ref != NULL);
+ HDassert(obj_token);
+ HDassert(token_size);
+ HDassert(token_size <= H5VL_MAX_TOKEN_SIZE);
+
+ H5MM_memcpy(ref->ref.obj.token, obj_token, ref->token_size);
+ ref->token_size = token_size;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__set_obj_token() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__get_region
+ *
+ * Purpose: Given a reference to some object, creates a copy of the dataset
+ * pointed to's dataspace and defines a selection in the copy which is the
+ * region pointed to.
+ *
+ * Return: Pointer to the dataspace on success/NULL on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5R__get_region(const H5R_ref_priv_t *ref, H5S_t *space)
{
- H5O_loc_t oloc; /* Object location */
- const uint8_t *p; /* Pointer to OID to store */
- H5HG_t hobjid; /* Heap object ID */
- uint8_t *buf = NULL; /* Buffer to store serialized selection in */
- H5S_t *ret_value; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
- HDassert(_ref);
- HDassert(file);
+ HDassert(ref != NULL);
+ HDassert(ref->type == H5R_DATASET_REGION2);
+ HDassert(space);
- /* Initialize the object location */
- H5O_loc_reset(&oloc);
- oloc.file = file;
+ /* Copy reference selection to destination */
+ if(H5S_select_copy(space, ref->ref.reg.space, FALSE) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCOPY, FAIL, "unable to copy selection")
- /* Get the heap ID for the dataset region */
- p = (const uint8_t *)_ref;
- H5F_addr_decode(oloc.file, &p, &(hobjid.addr));
- UINT32DECODE(p, hobjid.idx);
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__get_region() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__get_file_name
+ *
+ * Purpose: Given a reference to some object, determine a file name of the
+ * object located into.
+ *
+ * Return: Non-negative length of the path on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+ssize_t
+H5R__get_file_name(const H5R_ref_priv_t *ref, char *buf, size_t size)
+{
+ size_t copy_len;
+ ssize_t ret_value = -1; /* Return value */
- /* Get the dataset region from the heap (allocate inside routine) */
- if(NULL == (buf = (uint8_t *)H5HG_read(oloc.file, &hobjid, NULL, NULL)))
- HGOTO_ERROR(H5E_REFERENCE, H5E_READERROR, NULL, "Unable to read dataset region information")
+ FUNC_ENTER_PACKAGE
- /* Get the object oid for the dataset */
- p = buf;
- H5F_addr_decode(oloc.file, &p, &(oloc.addr));
+ /* Check args */
+ HDassert(ref != NULL);
- /* Open and copy the dataset's dataspace */
- if(NULL == (ret_value = H5S_read(&oloc)))
- HGOTO_ERROR(H5E_DATASPACE, H5E_NOTFOUND, NULL, "not found")
+ /* Return if that reference has no filename set */
+ if(!ref->ref.obj.filename)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_ARGS, (-1), "no filename available for that reference")
- /* Unserialize the selection */
- if(H5S_SELECT_DESERIALIZE(&ret_value, &p) < 0)
- HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, NULL, "can't deserialize selection")
+ /* Get the file name length */
+ copy_len = HDstrlen(ref->ref.obj.filename);
+ HDassert(copy_len <= H5R_MAX_STRING_LEN);
-done:
- /* Free the buffer allocated in H5HG_read() */
- if(buf)
- H5MM_xfree(buf);
+ /* Copy the file name */
+ if(buf) {
+ copy_len = MIN(copy_len, size - 1);
+ H5MM_memcpy(buf, ref->ref.obj.filename, copy_len);
+ buf[copy_len] = '\0';
+ }
+ ret_value = (ssize_t)(copy_len + 1);
+done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5R__get_region() */
+} /* end H5R__get_file_name() */
-/*--------------------------------------------------------------------------
- NAME
- H5R__get_obj_type
- PURPOSE
- Retrieves the type of object that an object reference points to
- USAGE
- H5O_type_t H5R__get_obj_type(file, ref_type, ref)
- H5F_t *file; IN: File the object being dereferenced is within
- H5R_type_t ref_type; IN: Type of reference to query
- void *ref; IN: Reference to query.
- H5O_type_t *obj_type; OUT: The type of the object, set on success
+/*-------------------------------------------------------------------------
+ * Function: H5R__get_attr_name
+ *
+ * Purpose: Given a reference to some attribute, determine its name.
+ *
+ * Return: Non-negative length of the path on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+ssize_t
+H5R__get_attr_name(const H5R_ref_priv_t *ref, char *buf, size_t size)
+{
+ ssize_t ret_value = -1; /* Return value */
+ size_t attr_name_len; /* Length of the attribute name */
- RETURNS
- Non-negative on success/Negative on failure
- DESCRIPTION
- Given a reference to some object, this function returns the type of object
- pointed to.
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
+ FUNC_ENTER_PACKAGE_NOERR
+
+ /* Check args */
+ HDassert(ref != NULL);
+ HDassert(ref->type == H5R_ATTR);
+
+ /* Get the attribute name length */
+ attr_name_len = HDstrlen(ref->ref.attr.name);
+ HDassert(attr_name_len <= H5R_MAX_STRING_LEN);
+
+ /* Get the attribute name */
+ if(buf) {
+ size_t copy_len = MIN(attr_name_len, size - 1);
+ H5MM_memcpy(buf, ref->ref.attr.name, copy_len);
+ buf[copy_len] = '\0';
+ }
+
+ ret_value = (ssize_t)(attr_name_len + 1);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__get_attr_name() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__encode
+ *
+ * Purpose: Private function for H5Rencode.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
herr_t
-H5R__get_obj_type(H5F_t *file, H5R_type_t ref_type, const void *_ref,
- H5O_type_t *obj_type)
+H5R__encode(const char *filename, const H5R_ref_priv_t *ref, unsigned char *buf,
+ size_t *nalloc, unsigned flags)
{
- H5O_loc_t oloc; /* Object location */
- unsigned rc; /* Reference count of object */
- herr_t ret_value = SUCCEED; /* Return value */
+ uint8_t *p = (uint8_t *)buf;
+ size_t buf_size = 0, encode_size = 0;
+ herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
- HDassert(file);
- HDassert(_ref);
+ HDassert(ref);
+ HDassert(nalloc);
+
+ /**
+ * Encoding format:
+ * | Reference type (8 bits) | Flags (8 bits) | Token (token size)
+ * | |
+ * | |----> H5R_IS_EXTERNAL: File info
+ * |
+ * |----> H5R_DATASET_REGION2: Serialized selection
+ * |
+ * |----> H5R_ATTR: Attribute name len + name
+ *
+ */
- /* Initialize the symbol table entry */
- H5O_loc_reset(&oloc);
- oloc.file = file;
+ /* Don't encode if buffer size isn't big enough or buffer is empty */
+ if(buf && *nalloc >= H5R_ENCODE_HEADER_SIZE) {
+ /* Encode the type of the reference */
+ *p++ = (uint8_t)ref->type;
+
+ /* Encode the flags */
+ *p++ = (uint8_t)flags;
+
+ buf_size = *nalloc - H5R_ENCODE_HEADER_SIZE;
+ }
+ encode_size += H5R_ENCODE_HEADER_SIZE;
+
+ /* Encode object token */
+ H5R_ENCODE_VAR(H5R__encode_obj_token, &ref->ref.obj.token, ref->token_size,
+ p, buf_size, encode_size, "Cannot encode object address");
+
+ /**
+ * TODO Encode VOL info
+ * When we have a better way of storing blobs, we should add
+ * support for referencing files in external VOLs.
+ * There are currently multiple limitations:
+ * - avoid duplicating VOL info on each reference
+ * - must query terminal VOL connector to avoid passthrough confusion
+ */
+ if(flags & H5R_IS_EXTERNAL) {
+ /* Encode file name */
+ H5R_ENCODE(H5R__encode_string, filename, p, buf_size, encode_size,
+ "Cannot encode filename");
+ }
- switch (ref_type) {
- case H5R_OBJECT:
- {
- /* Get the object oid */
- oloc.addr = *(const hobj_ref_t *)_ref; /* Only object references currently supported */
+ switch(ref->type) {
+ case H5R_OBJECT2:
break;
- }
+ case H5R_DATASET_REGION2:
+ /* Encode dataspace */
+ H5R_ENCODE(H5R__encode_region, ref->ref.reg.space, p, buf_size,
+ encode_size, "Cannot encode region");
+ break;
+ case H5R_ATTR:
+ /* Encode attribute name */
+ H5R_ENCODE(H5R__encode_string, ref->ref.attr.name, p, buf_size,
+ encode_size, "Cannot encode attribute name");
+ break;
+ case H5R_OBJECT1:
+ case H5R_DATASET_REGION1:
+ case H5R_BADTYPE:
+ case H5R_MAXTYPE:
+ HDassert("invalid reference type" && 0);
+ HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, FAIL, "internal error (invalid reference type)")
+ default:
+ HDassert("unknown reference type" && 0);
+ HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, FAIL, "internal error (unknown reference type)")
+ } /* end switch */
- case H5R_DATASET_REGION:
- {
- H5HG_t hobjid; /* Heap object ID */
- const uint8_t *p; /* Pointer to reference to decode */
- uint8_t *buf; /* Buffer to store serialized selection in */
+ *nalloc = encode_size;
- /* Get the heap ID for the dataset region */
- p = (const uint8_t *)_ref;
- H5F_addr_decode(oloc.file, &p, &(hobjid.addr));
- UINT32DECODE(p, hobjid.idx);
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__encode() */
- /* Get the dataset region from the heap (allocate inside routine) */
- if(NULL == (buf = (uint8_t *)H5HG_read(oloc.file, &hobjid, NULL, NULL)))
- HGOTO_ERROR(H5E_REFERENCE, H5E_READERROR, FAIL, "Unable to read dataset region information")
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__decode
+ *
+ * Purpose: Private function for H5Rdecode.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5R__decode(const unsigned char *buf, size_t *nbytes, H5R_ref_priv_t *ref)
+{
+ const uint8_t *p = (const uint8_t *)buf;
+ size_t buf_size = 0, decode_size = 0;
+ uint8_t flags;
+ herr_t ret_value = SUCCEED;
- /* Get the object oid for the dataset */
- p = buf;
- H5F_addr_decode(oloc.file, &p, &(oloc.addr));
+ FUNC_ENTER_PACKAGE
- /* Free the buffer allocated in H5HG_read() */
- H5MM_xfree(buf);
+ HDassert(buf);
+ HDassert(nbytes);
+ HDassert(ref);
+ buf_size = *nbytes;
- break;
- }
+ /* Don't decode if buffer size isn't big enough */
+ if(buf_size < H5R_ENCODE_HEADER_SIZE)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "Buffer size is too small")
+
+ /* Set new reference */
+ ref->type = (H5R_type_t)*p++;
+ if(ref->type <= H5R_BADTYPE || ref->type >= H5R_MAXTYPE)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid reference type")
+
+ /* Set flags */
+ flags = *p++;
+
+ buf_size -= H5R_ENCODE_HEADER_SIZE;
+ decode_size += H5R_ENCODE_HEADER_SIZE;
+
+ /* Decode object token */
+ H5R_DECODE_VAR(H5R__decode_obj_token, &ref->ref.obj.token, &ref->token_size,
+ p, buf_size, decode_size, "Cannot decode object address");
+ /* We do not need to store the filename if the reference is internal */
+ if(flags & H5R_IS_EXTERNAL) {
+ /* Decode file name */
+ H5R_DECODE(H5R__decode_string, &ref->ref.obj.filename, p, buf_size,
+ decode_size, "Cannot decode filename");
+ } else
+ ref->ref.obj.filename = NULL;
+
+ switch(ref->type) {
+ case H5R_OBJECT2:
+ break;
+ case H5R_DATASET_REGION2:
+ /* Decode dataspace */
+ H5R_DECODE(H5R__decode_region, &ref->ref.reg.space, p, buf_size,
+ decode_size, "Cannot decode region");
+ break;
+ case H5R_ATTR:
+ /* Decode attribute name */
+ H5R_DECODE(H5R__decode_string, &ref->ref.attr.name, p, buf_size,
+ decode_size, "Cannot decode attribute name");
+ break;
+ case H5R_OBJECT1:
+ case H5R_DATASET_REGION1:
case H5R_BADTYPE:
case H5R_MAXTYPE:
+ HDassert("invalid reference type" && 0);
+ HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, FAIL, "internal error (invalid reference type)")
default:
HDassert("unknown reference type" && 0);
HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, FAIL, "internal error (unknown reference type)")
} /* end switch */
- /* Get the # of links for object, and its type */
- /* (To check to make certain that this object hasn't been deleted since the reference was created) */
- if(H5O_get_rc_and_type(&oloc, &rc, obj_type) < 0 || 0 == rc)
- HGOTO_ERROR(H5E_REFERENCE, H5E_LINKCOUNT, FAIL, "dereferencing deleted object")
+ /* Set loc ID to invalid */
+ ref->loc_id = H5I_INVALID_HID;
+
+ /* Set encoding size */
+ ref->encode_size = decode_size;
+
+ H5R_LOG_DEBUG("Decoded reference, filename=%s, obj_addr=%s, encode size=%u",
+ ref->ref.obj.filename, H5R__print_token(ref->ref.obj.token),
+ ref->encode_size);
+
+ *nbytes = decode_size;
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5R__get_obj_type() */
+} /* end H5R__decode() */
-/*--------------------------------------------------------------------------
- NAME
- H5R__get_name
- PURPOSE
- Internal routine to determine a name for the object referenced
- USAGE
- ssize_t H5R__get_name(f, ref_type, ref, name, size)
- H5F_t *f; IN: Pointer to the file that the reference is pointing
- into
- hid_t lapl_id; IN: LAPL to use for operation
- hid_t id; IN: Location ID given for reference
- H5R_type_t ref_type; IN: Type of reference
- void *_ref; IN: Reference to query.
- char *name; OUT: Buffer to place name of object referenced
- size_t size; IN: Size of name buffer
+/*-------------------------------------------------------------------------
+ * Function: H5R__encode_obj_token
+ *
+ * Purpose: Encode an object address.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5R__encode_obj_token(const H5VL_token_t *obj_token, size_t token_size,
+ unsigned char *buf, size_t *nalloc)
+{
+ herr_t ret_value = SUCCEED;
- RETURNS
- Non-negative length of the path on success, -1 on failure
- DESCRIPTION
- Given a reference to some object, determine a path to the object
- referenced in the file.
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- This may not be the only path to that object.
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
-ssize_t
-H5R__get_name(H5F_t *f, hid_t id, H5R_type_t ref_type, const void *_ref,
- char *name, size_t size)
+ FUNC_ENTER_STATIC_NOERR
+
+ HDassert(nalloc);
+
+ /* Don't encode if buffer size isn't big enough or buffer is empty */
+ if(buf && *nalloc >= token_size) {
+ uint8_t *p = (uint8_t *)buf;
+
+ /* Encode token size */
+ *p++ = (uint8_t)(token_size & 0xff);
+
+ /* Encode token */
+ H5MM_memcpy(p, obj_token, token_size);
+ }
+ *nalloc = token_size + H5_SIZEOF_UINT8_T;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__encode_obj_token() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__decode_obj_token
+ *
+ * Purpose: Decode an object address.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5R__decode_obj_token(const unsigned char *buf, size_t *nbytes,
+ H5VL_token_t *obj_token, uint8_t *token_size)
{
- hid_t file_id = H5I_INVALID_HID; /* ID for file that the reference is in */
- H5O_loc_t oloc; /* Object location describing object for reference */
- ssize_t ret_value = -1; /* Return value */
+ const uint8_t *p = (const uint8_t *)buf;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ HDassert(buf);
+ HDassert(nbytes);
+ HDassert(obj_token);
+ HDassert(token_size);
+
+ /* Don't decode if buffer size isn't big enough */
+ if(*nbytes < H5_SIZEOF_UINT8_T)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "Buffer size is too small")
+
+ /* Get token size */
+ *token_size = *p++;
+ if(*token_size > sizeof(H5VL_token_t))
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "Invalid token size (%u)", *token_size)
+
+ /* Decode token */
+ H5MM_memcpy(obj_token, p, *token_size);
+
+ *nbytes = *token_size + H5_SIZEOF_UINT8_T;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__decode_obj_token() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__encode_region
+ *
+ * Purpose: Encode a selection.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5R__encode_region(H5S_t *space, unsigned char *buf, size_t *nalloc)
+{
+ uint8_t *p = NULL; /* Pointer to data to store */
+ hssize_t buf_size = 0;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ HDassert(space);
+ HDassert(nalloc);
+
+ /* Get the amount of space required to serialize the selection */
+ if((buf_size = H5S_SELECT_SERIAL_SIZE(space)) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTENCODE, FAIL, "Cannot determine amount of space needed for serializing selection")
+
+ /* Don't encode if buffer size isn't big enough or buffer is empty */
+ if(buf && *nalloc >= ((size_t)buf_size + 2 * H5_SIZEOF_UINT32_T)) {
+ p = (uint8_t *)buf;
+ int rank;
+
+ /* Encode the size for safety check */
+ UINT32ENCODE(p, (uint32_t)buf_size);
+
+ /* Encode the extent rank */
+ if((rank = H5S_get_simple_extent_ndims(space)) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "can't get extent rank for selection")
+ UINT32ENCODE(p, (uint32_t)rank);
+
+ /* Serialize the selection */
+ if(H5S_SELECT_SERIALIZE(space, (unsigned char **)&p) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTENCODE, FAIL, "can't serialize selection")
+ }
+ *nalloc = (size_t)buf_size + 2 * H5_SIZEOF_UINT32_T;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__encode_region() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__decode_region
+ *
+ * Purpose: Decode a selection.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5R__decode_region(const unsigned char *buf, size_t *nbytes, H5S_t **space_ptr)
+{
+ const uint8_t *p = (const uint8_t *)buf;
+ size_t buf_size = 0;
+ unsigned rank;
+ H5S_t *space;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ HDassert(buf);
+ HDassert(nbytes);
+ HDassert(space_ptr);
+
+ /* Don't decode if buffer size isn't big enough */
+ if(*nbytes < (2 * H5_SIZEOF_UINT32_T))
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "Buffer size is too small")
+
+ /* Decode the selection size */
+ UINT32DECODE(p, buf_size);
+ buf_size += H5_SIZEOF_UINT32_T;
+
+ /* Decode the extent rank */
+ UINT32DECODE(p, rank);
+ buf_size += H5_SIZEOF_UINT32_T;
+
+ /* Don't decode if buffer size isn't big enough */
+ if(*nbytes < buf_size)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "Buffer size is too small")
+
+ /* Deserialize the selection (dataspaces need the extent rank information) */
+ if(NULL == (space = H5S_create(H5S_SIMPLE)))
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "Buffer size is too small")
+ if(H5S_set_extent_simple(space, rank, NULL, NULL) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTSET, FAIL, "can't set extent rank for selection")
+ if(H5S_SELECT_DESERIALIZE(&space, &p) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "can't deserialize selection")
+
+ *nbytes = buf_size;
+ *space_ptr = space;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__decode_region() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__encode_string
+ *
+ * Purpose: Encode a string.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5R__encode_string(const char *string, unsigned char *buf, size_t *nalloc)
+{
+ size_t string_len, buf_size;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ HDassert(string);
+ HDassert(nalloc);
+
+ /* Get the amount of space required to serialize the string */
+ string_len = HDstrlen(string);
+ if(string_len > H5R_MAX_STRING_LEN)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_ARGS, FAIL, "string too long")
+
+ /* Compute buffer size, allow for the attribute name length and object address */
+ buf_size = string_len + sizeof(uint16_t);
+
+ if(buf && *nalloc >= buf_size) {
+ uint8_t *p = (uint8_t *)buf;
+ /* Serialize information for string length into the buffer */
+ UINT16ENCODE(p, string_len);
+ /* Copy the string into the buffer */
+ H5MM_memcpy(p, string, string_len);
+ }
+ *nalloc = buf_size;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__encode_string() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__decode_string
+ *
+ * Purpose: Decode a string.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5R__decode_string(const unsigned char *buf, size_t *nbytes, char **string_ptr)
+{
+ const uint8_t *p = (const uint8_t *)buf;
+ size_t string_len;
+ char *string = NULL;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ HDassert(buf);
+ HDassert(nbytes);
+ HDassert(string_ptr);
+
+ /* Don't decode if buffer size isn't big enough */
+ if(*nbytes < sizeof(uint16_t))
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "Buffer size is too small")
+
+ /* Get the string length */
+ UINT16DECODE(p, string_len);
+ HDassert(string_len <= H5R_MAX_STRING_LEN);
+
+ /* Allocate the string */
+ if(NULL == (string = H5MM_malloc(string_len + 1)))
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTALLOC, FAIL, "Cannot allocate string")
+
+ /* Copy the string */
+ H5MM_memcpy(string, p, string_len);
+ string[string_len] = '\0';
+
+ *string_ptr = string;
+ *nbytes = sizeof(uint16_t) + string_len;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__decode_string() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__encode_heap
+ *
+ * Purpose: Encode data and insert into heap (native only).
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5R__encode_heap(H5F_t *f, unsigned char *buf, size_t *nalloc,
+ const unsigned char *data, size_t data_size)
+{
+ size_t buf_size;
+ herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
- /* Check args */
HDassert(f);
- HDassert(_ref);
+ HDassert(nalloc);
- /* Initialize the object location */
- H5O_loc_reset(&oloc);
- oloc.file = f;
+ buf_size = H5HG_HEAP_ID_SIZE(f);
+ if(buf && *nalloc >= buf_size) {
+ H5HG_t hobjid;
+ uint8_t *p = (uint8_t *)buf;
- /* Get address for reference */
- switch (ref_type) {
- case H5R_OBJECT:
- {
- oloc.addr = *(const hobj_ref_t *)_ref;
- break;
- }
+ /* Write the reference information to disk (allocates space also) */
+ if(H5HG_insert(f, data_size, (void *)data, &hobjid) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_WRITEERROR, FAIL, "Unable to write reference information")
+
+ /* Encode the heap information */
+ H5F_addr_encode(f, &p, hobjid.addr);
+ UINT32ENCODE(p, hobjid.idx);
+ }
+ *nalloc = buf_size;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__encode_heap() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__decode_heap
+ *
+ * Purpose: Decode data inserted into heap (native only).
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5R__decode_heap(H5F_t *f, const unsigned char *buf, size_t *nbytes,
+ unsigned char **data_ptr, size_t *data_size)
+{
+ const uint8_t *p = (const uint8_t *)buf;
+ H5HG_t hobjid;
+ size_t buf_size;
+ herr_t ret_value = SUCCEED;
- case H5R_DATASET_REGION:
- {
- H5HG_t hobjid; /* Heap object ID */
- uint8_t *buf; /* Buffer to store serialized selection in */
- const uint8_t *p; /* Pointer to OID to store */
+ FUNC_ENTER_PACKAGE
- /* Get the heap ID for the dataset region */
- p = (const uint8_t *)_ref;
- H5F_addr_decode(oloc.file, &p, &(hobjid.addr));
- UINT32DECODE(p, hobjid.idx);
+ HDassert(f);
+ HDassert(buf);
+ HDassert(nbytes);
+ HDassert(data_ptr);
+
+ buf_size = H5HG_HEAP_ID_SIZE(f);
+ /* Don't decode if buffer size isn't big enough */
+ if(*nbytes < buf_size)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "Buffer size is too small")
+
+ /* Get the heap information */
+ H5F_addr_decode(f, &p, &(hobjid.addr));
+ if(!H5F_addr_defined(hobjid.addr) || hobjid.addr == 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Undefined reference pointer")
+ UINT32DECODE(p, hobjid.idx);
- /* Get the dataset region from the heap (allocate inside routine) */
- if ((buf = (uint8_t *)H5HG_read(oloc.file, &hobjid, NULL, NULL)) == NULL)
- HGOTO_ERROR(H5E_REFERENCE, H5E_READERROR, (-1), "Unable to read dataset region information")
+ /* Read the information from disk */
+ if(NULL == (*data_ptr = (unsigned char *)H5HG_read(f, &hobjid, (void *)*data_ptr, data_size)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_READERROR, FAIL, "Unable to read reference data")
- /* Get the object oid for the dataset */
- p = buf;
- H5F_addr_decode(oloc.file, &p, &(oloc.addr));
+ *nbytes = buf_size;
- /* Free the buffer allocated in H5HG_read() */
- H5MM_xfree(buf);
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__decode_heap() */
- break;
- }
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__free_heap
+ *
+ * Purpose: Remove data previously inserted into heap (native only).
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5R__free_heap(H5F_t *f, const unsigned char *buf, size_t nbytes)
+{
+ H5HG_t hobjid;
+ const uint8_t *p = (const uint8_t *)buf;
+ size_t buf_size;
+ herr_t ret_value = SUCCEED;
- case H5R_BADTYPE:
- case H5R_MAXTYPE:
- default:
- HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, (-1), "internal error (unknown reference type)")
- } /* end switch */
+ FUNC_ENTER_PACKAGE
+
+ HDassert(f);
+ HDassert(buf);
+
+ buf_size = H5HG_HEAP_ID_SIZE(f);
+ /* Don't decode if buffer size isn't big enough */
+ if(nbytes < buf_size)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "Buffer size is too small")
+
+ /* Get the heap information */
+ H5F_addr_decode(f, &p, &(hobjid.addr));
+ if(!H5F_addr_defined(hobjid.addr) || hobjid.addr == 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Undefined reference pointer")
+ UINT32DECODE(p, hobjid.idx);
+
+ /* Free heap object */
+ if(hobjid.addr > 0) {
+ /* Free heap object */
+ if(H5HG_remove(f, &hobjid) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_WRITEERROR, FAIL, "Unable to remove heap object")
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__free_heap() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__decode_token_compat
+ *
+ * Purpose: Decode an object token. (native only)
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5R__decode_token_compat(hid_t id, H5I_type_t type, H5R_type_t ref_type,
+ const unsigned char *buf, H5VL_token_t *obj_token)
+{
+ hid_t file_id = H5I_INVALID_HID; /* File ID for region reference */
+ void *vol_obj_file = NULL;
+ H5VL_file_cont_info_t cont_info = {H5VL_CONTAINER_INFO_VERSION, 0, 0, 0};
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_PACKAGE
+
+ /* Get the file for the object */
+ if((file_id = H5F_get_file_id(id, type, FALSE)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+
+ /* Retrieve VOL object */
+ if(NULL == (vol_obj_file = H5VL_vol_object(file_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Get container info */
+ if(H5VL_file_get(vol_obj_file, H5VL_FILE_GET_CONT_INFO, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &cont_info) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "unable to get container info")
+
+ if(ref_type == H5R_OBJECT1) {
+ size_t buf_size = H5R_OBJ_REF_BUF_SIZE;
+
+ /* Get object address */
+ if(H5R__decode_token_obj_compat(buf, &buf_size, obj_token, cont_info.token_size) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "unable to get object token")
+ } else {
+ size_t buf_size = H5R_DSET_REG_REF_BUF_SIZE;
+ H5F_t *f = NULL;
+
+ /* Retrieve file from VOL object */
+ if(NULL == (f = (H5F_t *)H5VL_object_data(vol_obj_file)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid VOL object")
+
+ /* Get object address */
+ if(H5R__decode_token_region_compat(f, buf, &buf_size, obj_token, cont_info.token_size, NULL) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "unable to get object address")
+ }
+
+done:
+ if(file_id != H5I_INVALID_HID && H5I_dec_ref(file_id) < 0)
+ HDONE_ERROR(H5E_REFERENCE, H5E_CANTDEC, FAIL, "unable to decrement refcount on file")
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__decode_token_compat() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__encode_token_obj_compat
+ *
+ * Purpose: Encode an object token. (native only)
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5R__encode_token_obj_compat(const H5VL_token_t *obj_token, size_t token_size,
+ unsigned char *buf, size_t *nalloc)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_PACKAGE_NOERR
+
+ HDassert(obj_token);
+ HDassert(token_size);
+ HDassert(nalloc);
+
+ /* Don't encode if buffer size isn't big enough or buffer is empty */
+ if(buf && *nalloc >= token_size)
+ H5MM_memcpy(buf, obj_token, token_size);
+
+ *nalloc = token_size;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__encode_token_obj_compat() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__decode_token_obj_compat
+ *
+ * Purpose: Decode an object token. (native only)
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5R__decode_token_obj_compat(const unsigned char *buf, size_t *nbytes,
+ H5VL_token_t *obj_token, size_t token_size)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_PACKAGE
+
+ HDassert(buf);
+ HDassert(nbytes);
+ HDassert(obj_token);
+ HDassert(token_size);
+
+ /* Don't decode if buffer size isn't big enough */
+ if(*nbytes < token_size)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "Buffer size is too small")
- /* Retrieve file ID for name search */
- if ((file_id = H5F_get_id(f, FALSE)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, (-1), "can't get file ID")
+ H5MM_memcpy(obj_token, buf, token_size);
- /* Get name, length, etc. */
- if ((ret_value = H5G_get_name_by_addr(file_id, &oloc, name, size)) < 0)
- HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, (-1), "can't determine name")
+ *nbytes = token_size;
done:
- /* Close file ID used for search */
- if (file_id > 0 && H5I_dec_ref(file_id) < 0)
- HDONE_ERROR(H5E_REFERENCE, H5E_CANTDEC, (-1), "can't decrement ref count of temp ID")
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5R__decode_token_obj_compat() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__encode_token_region_compat
+ *
+ * Purpose: Encode dataset selection and insert data into heap (native only).
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5R__encode_token_region_compat(H5F_t *f, const H5VL_token_t *obj_token,
+ size_t token_size, H5S_t *space, unsigned char *buf, size_t *nalloc)
+{
+ size_t buf_size;
+ unsigned char *data = NULL;
+ herr_t ret_value = SUCCEED;
+ FUNC_ENTER_PACKAGE
+
+ HDassert(f);
+ HDassert(obj_token);
+ HDassert(token_size);
+ HDassert(space);
+ HDassert(nalloc);
+
+ /* Get required buffer size */
+ if(H5R__encode_heap(f, NULL, &buf_size, NULL, (size_t)0) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ if(buf && *nalloc >= buf_size) {
+ ssize_t data_size;
+ uint8_t *p;
+
+ /* Pass the correct encoding version for the selection depending on the
+ * file libver bounds, this is later retrieved in H5S hyper encode */
+ H5CX_set_libver_bounds(f);
+
+ /* Zero the heap ID out, may leak heap space if user is re-using
+ * reference and doesn't have garbage collection turned on
+ */
+ HDmemset(buf, 0, buf_size);
+
+ /* Get the amount of space required to serialize the selection */
+ if((data_size = H5S_SELECT_SERIAL_SIZE(space)) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTINIT, FAIL, "Invalid amount of space for serializing selection")
+
+ /* Increase buffer size to allow for the dataset token */
+ data_size += (hssize_t)token_size;
+
+ /* Allocate the space to store the serialized information */
+ H5_CHECK_OVERFLOW(data_size, hssize_t, size_t);
+ if(NULL == (data = (uint8_t *)H5MM_malloc((size_t)data_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /* Serialize information for dataset OID into heap buffer */
+ p = (uint8_t *)data;
+ H5MM_memcpy(p, obj_token, token_size);
+ p += token_size;
+
+ /* Serialize the selection into heap buffer */
+ if(H5S_SELECT_SERIALIZE(space, &p) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCOPY, FAIL, "Unable to serialize selection")
+
+ /* Write to heap */
+ if(H5R__encode_heap(f, buf, nalloc, data, (size_t)data_size) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+ }
+ *nalloc = buf_size;
+
+done:
+ H5MM_free(data);
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5R__get_name() */
+} /* H5R__encode_token_region_compat() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__decode_token_region_compat
+ *
+ * Purpose: Decode dataset selection from data inserted into heap (native only).
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5R__decode_token_region_compat(H5F_t *f, const unsigned char *buf,
+ size_t *nbytes, H5VL_token_t *obj_token, size_t token_size,
+ H5S_t **space_ptr)
+{
+ unsigned char *data = NULL;
+ H5VL_token_t token = { 0 };
+ size_t data_size;
+ const uint8_t *p;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_PACKAGE
+
+ HDassert(f);
+ HDassert(buf);
+ HDassert(nbytes);
+ HDassert(token_size);
+
+ /* Read from heap */
+ if(H5R__decode_heap(f, buf, nbytes, &data, &data_size) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Get object address */
+ p = (const uint8_t *)data;
+ H5MM_memcpy(token, p, token_size);
+ p += token_size;
+
+ if(space_ptr) {
+ H5O_loc_t oloc; /* Object location */
+ H5S_t *space = NULL;
+ const uint8_t *q = token;
+
+ /* Initialize the object location */
+ H5O_loc_reset(&oloc);
+ oloc.file = f;
+ H5F_addr_decode(f, &q, &oloc.addr);
+
+ /* Open and copy the dataset's dataspace */
+ if(NULL == (space = H5S_read(&oloc)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_NOTFOUND, FAIL, "not found")
+
+ /* Unserialize the selection */
+ if(H5S_SELECT_DESERIALIZE(&space, &p) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "can't deserialize selection")
+
+ *space_ptr = space;
+ }
+ if(obj_token)
+ H5MM_memcpy(obj_token, token, token_size);
+
+done:
+ H5MM_free(data);
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__decode_token_region_compat() */
diff --git a/src/H5Rpkg.h b/src/H5Rpkg.h
index 504d2af..19f3115 100644
--- a/src/H5Rpkg.h
+++ b/src/H5Rpkg.h
@@ -36,11 +36,51 @@
/* Package Private Macros */
/**************************/
+/* Encode flags */
+#define H5R_IS_EXTERNAL 0x1 /* Set when encoding reference to external file */
+
+/* Macros for convenience */
+#define H5R_REF_FILENAME(x) ((x)->ref.obj.filename)
+#define H5R_REF_ATTRNAME(x) ((x)->ref.attr.name)
+
+/* Header size */
+#define H5R_ENCODE_HEADER_SIZE (2 * H5_SIZEOF_UINT8_T)
/****************************/
/* Package Private Typedefs */
/****************************/
+/* Object reference */
+typedef struct H5R_ref_priv_obj_t {
+ H5VL_token_t token; /* Object token */
+ char *filename; /* File name */
+} H5R_ref_priv_obj_t;
+
+/* Region reference */
+typedef struct H5R_ref_priv_reg_t {
+ H5R_ref_priv_obj_t obj; /* Object reference */
+ H5S_t *space; /* Selection */
+} H5R_ref_priv_reg_t;
+
+/* Attribute reference */
+typedef struct H5R_ref_priv_attr_t {
+ H5R_ref_priv_obj_t obj; /* Object reference */
+ char *name; /* Attribute name */
+} H5R_ref_priv_attr_t;
+
+/* Generic reference type (keep it cache aligned) */
+typedef struct H5R_ref_priv_t {
+ union {
+ H5R_ref_priv_obj_t obj;/* Object reference */
+ H5R_ref_priv_reg_t reg;/* Region reference */
+ H5R_ref_priv_attr_t attr;/* Attribute Reference */
+ } ref;
+ hid_t loc_id; /* Cached location identifier */
+ uint32_t encode_size; /* Cached encoding size */
+ int8_t type; /* Reference type */
+ uint8_t token_size; /* Cached token size */
+ char unused[18]; /* Unused */
+} H5R_ref_priv_t;
/*****************************/
/* Package Private Variables */
@@ -50,11 +90,41 @@
/******************************/
/* Package Private Prototypes */
/******************************/
-H5_DLL herr_t H5R__create(void *ref, H5G_loc_t *loc, const char *name, H5R_type_t ref_type, H5S_t *space);
-H5_DLL hid_t H5R__dereference(H5F_t *file, hid_t dapl_id, H5R_type_t ref_type, const void *_ref);
-H5_DLL H5S_t *H5R__get_region(H5F_t *file, const void *_ref);
-H5_DLL herr_t H5R__get_obj_type(H5F_t *file, H5R_type_t ref_type, const void *_ref, H5O_type_t *obj_type);
-H5_DLL ssize_t H5R__get_name(H5F_t *file, hid_t id, H5R_type_t ref_type, const void *_ref, char *name, size_t size);
+H5_DLL herr_t H5R__create_object(const H5VL_token_t *obj_token, size_t token_size, H5R_ref_priv_t *ref);
+H5_DLL herr_t H5R__create_region(const H5VL_token_t *obj_token, size_t token_size, H5S_t *space, H5R_ref_priv_t *ref);
+H5_DLL herr_t H5R__create_attr(const H5VL_token_t *obj_token, size_t token_size, const char *attr_name, H5R_ref_priv_t *ref);
+H5_DLL herr_t H5R__destroy(H5R_ref_priv_t *ref);
+
+H5_DLL herr_t H5R__set_loc_id(H5R_ref_priv_t *ref, hid_t id, hbool_t inc_ref);
+H5_DLL hid_t H5R__get_loc_id(const H5R_ref_priv_t *ref);
+H5_DLL hid_t H5R__reopen_file(H5R_ref_priv_t *ref, hid_t fapl_id);
+
+H5_DLL H5R_type_t H5R__get_type(const H5R_ref_priv_t *ref);
+H5_DLL htri_t H5R__equal(const H5R_ref_priv_t *ref1, const H5R_ref_priv_t *ref2);
+H5_DLL herr_t H5R__copy(const H5R_ref_priv_t *src_ref, H5R_ref_priv_t *dst_ref);
+
+H5_DLL herr_t H5R__get_obj_token(const H5R_ref_priv_t *ref, H5VL_token_t *obj_token, size_t *token_size);
+H5_DLL herr_t H5R__set_obj_token(H5R_ref_priv_t *ref, const H5VL_token_t *obj_token, size_t token_size);
+H5_DLL herr_t H5R__get_region(const H5R_ref_priv_t *ref, H5S_t *space);
+
+H5_DLL ssize_t H5R__get_file_name(const H5R_ref_priv_t *ref, char *buf, size_t size);
+H5_DLL ssize_t H5R__get_attr_name(const H5R_ref_priv_t *ref, char *buf, size_t size);
+
+H5_DLL herr_t H5R__encode(const char *filename, const H5R_ref_priv_t *ref, unsigned char *buf, size_t *nalloc, unsigned flags);
+H5_DLL herr_t H5R__decode(const unsigned char *buf, size_t *nbytes, H5R_ref_priv_t *ref);
+
+/* Native HDF5 specific routines */
+H5_DLL herr_t H5R__encode_heap(H5F_t *f, unsigned char *buf, size_t *nalloc, const unsigned char *data, size_t data_size);
+H5_DLL herr_t H5R__decode_heap(H5F_t *f, const unsigned char *buf, size_t *nbytes, unsigned char **data_ptr, size_t *data_size);
+H5_DLL herr_t H5R__free_heap(H5F_t *f, const unsigned char *buf, size_t nbytes);
+
+H5_DLL herr_t H5R__decode_token_compat(hid_t id, H5I_type_t type, H5R_type_t ref_type, const unsigned char *buf, H5VL_token_t *obj_token);
+
+H5_DLL herr_t H5R__encode_token_obj_compat(const H5VL_token_t *obj_token, size_t token_size, unsigned char *buf, size_t *nalloc);
+H5_DLL herr_t H5R__decode_token_obj_compat(const unsigned char *buf, size_t *nbytes, H5VL_token_t *obj_token, size_t token_size);
+
+H5_DLL herr_t H5R__encode_token_region_compat(H5F_t *f, const H5VL_token_t *obj_token, size_t token_size, H5S_t *space, unsigned char *buf, size_t *nalloc);
+H5_DLL herr_t H5R__decode_token_region_compat(H5F_t *f, const unsigned char *buf, size_t *nbytes, H5VL_token_t *obj_token, size_t token_size, H5S_t **space_ptr);
#endif /* _H5Rpkg_H */
diff --git a/src/H5Rprivate.h b/src/H5Rprivate.h
index 1bf2e92..6afec47 100644
--- a/src/H5Rprivate.h
+++ b/src/H5Rprivate.h
@@ -25,6 +25,8 @@
/* Library Private Macros */
/**************************/
+#define H5R_ENCODE_VERSION 0x1 /* Version for encoding references */
+
/****************************/
/* Library Private Typedefs */
@@ -41,4 +43,3 @@
/******************************/
#endif /* _H5Rprivate_H */
-
diff --git a/src/H5Rpublic.h b/src/H5Rpublic.h
index 598bafd..ce54ac4 100644
--- a/src/H5Rpublic.h
+++ b/src/H5Rpublic.h
@@ -26,47 +26,64 @@
/* Public Macros */
/*****************/
-/* Note! Be careful with the sizes of the references because they should really
- * depend on the run-time values in the file. Unfortunately, the arrays need
- * to be defined at compile-time, so we have to go with the worst case sizes
- * for them. -QAK
- */
+/* Deprecated reference buffer sizes that are kept for backward compatibility */
#define H5R_OBJ_REF_BUF_SIZE sizeof(haddr_t)
+#define H5R_DSET_REG_REF_BUF_SIZE (sizeof(haddr_t) + 4)
-/* 4 is used instead of sizeof(int) to permit portability between the Crays
- * and other machines (the heap ID is always encoded as an int32 anyway).
+/* Default reference buffer size.
+ * Note! Be careful with the sizes of the references because they should really
+ * depend on the run-time values in the file.
*/
-#define H5R_DSET_REG_REF_BUF_SIZE (sizeof(haddr_t) + 4)
+#define H5R_REF_BUF_SIZE (64)
/*******************/
/* Public Typedefs */
/*******************/
-/* Reference types */
-typedef enum H5R_type_t {
- H5R_BADTYPE = (-1), /* Invalid Reference Type */
- H5R_OBJECT, /* Object reference */
- H5R_DATASET_REGION, /* Dataset Region Reference */
- H5R_MAXTYPE /* Highest type (Invalid as true type) */
+/*
+ * Reference types allowed.
+ * DO NOT CHANGE THE ORDER or VALUES as reference type values are encoded into
+ * the datatype message header.
+ */
+typedef enum {
+ H5R_BADTYPE = (-1), /* Invalid reference type */
+ H5R_OBJECT1 = 0, /* Backward compatibility (object) */
+ H5R_DATASET_REGION1 = 1, /* Backward compatibility (region) */
+ H5R_OBJECT2 = 2, /* Object reference */
+ H5R_DATASET_REGION2 = 3, /* Region reference */
+ H5R_ATTR = 4, /* Attribute Reference */
+ H5R_MAXTYPE = 5 /* Highest type (invalid) */
} H5R_type_t;
-/* Object reference structure for user's code
- * This needs to be large enough to store largest haddr_t on a worst case
- * machine (8 bytes currently).
+/* Deprecated types are kept for backward compatibility with previous versions */
+
+/**
+ * Deprecated object reference type that is used with deprecated reference APIs.
+ * Note! This type can only be used with the "native" HDF5 VOL connector.
*/
typedef haddr_t hobj_ref_t;
-/* Dataset Region reference structure for user's code
+/**
+ * Dataset region reference type that is used with deprecated reference APIs.
* (Buffer to store heap ID and index)
* This needs to be large enough to store largest haddr_t in a worst case
- * machine (8 bytes currently) plus an int
+ * machine (8 bytes currently) plus an int.
+ * Note! This type can only be used with the "native" HDF5 VOL connector.
*/
typedef unsigned char hdset_reg_ref_t[H5R_DSET_REG_REF_BUF_SIZE];
+/**
+ * Opaque reference type. The same reference type is used for object,
+ * dataset region and attribute references. This is the type that
+ * should always be used with the current reference API.
+ */
+typedef unsigned char H5R_ref_t[H5R_REF_BUF_SIZE];
+
/********************/
/* Public Variables */
/********************/
+
/*********************/
/* Public Prototypes */
/*********************/
@@ -75,30 +92,57 @@ typedef unsigned char hdset_reg_ref_t[H5R_DSET_REG_REF_BUF_SIZE];
extern "C" {
#endif
-H5_DLL herr_t H5Rcreate(void *ref, hid_t loc_id, const char *name,
- H5R_type_t ref_type, hid_t space_id);
-H5_DLL hid_t H5Rdereference2(hid_t obj_id, hid_t oapl_id, H5R_type_t ref_type, const void *ref);
-H5_DLL hid_t H5Rget_region(hid_t dataset, H5R_type_t ref_type, const void *ref);
-H5_DLL herr_t H5Rget_obj_type2(hid_t id, H5R_type_t ref_type, const void *_ref,
- H5O_type_t *obj_type);
-H5_DLL ssize_t H5Rget_name(hid_t loc_id, H5R_type_t ref_type, const void *ref,
- char *name /*out*/, size_t size);
+/* Constructors */
+H5_DLL herr_t H5Rcreate_object(hid_t loc_id, const char *name, H5R_ref_t *ref_ptr);
+H5_DLL herr_t H5Rcreate_region(hid_t loc_id, const char *name, hid_t space_id, H5R_ref_t *ref_ptr);
+H5_DLL herr_t H5Rcreate_attr(hid_t loc_id, const char *name, const char *attr_name, H5R_ref_t *ref_ptr);
+H5_DLL herr_t H5Rdestroy(H5R_ref_t *ref_ptr);
+
+/* Info */
+H5_DLL H5R_type_t H5Rget_type(const H5R_ref_t *ref_ptr);
+H5_DLL htri_t H5Requal(const H5R_ref_t *ref1_ptr, const H5R_ref_t *ref2_ptr);
+H5_DLL herr_t H5Rcopy(const H5R_ref_t *src_ref_ptr, H5R_ref_t *dst_ref_ptr);
+
+/* Dereference */
+H5_DLL hid_t H5Ropen_object(const H5R_ref_t *ref_ptr, hid_t rapl_id, hid_t oapl_id);
+H5_DLL hid_t H5Ropen_region(const H5R_ref_t *ref_ptr, hid_t rapl_id, hid_t oapl_id);
+H5_DLL hid_t H5Ropen_attr(const H5R_ref_t *ref_ptr, hid_t rapl_id, hid_t aapl_id);
+
+/* Get type */
+H5_DLL herr_t H5Rget_obj_type3(const H5R_ref_t *ref_ptr, hid_t rapl_id, H5O_type_t *obj_type);
+
+/* Get name */
+H5_DLL ssize_t H5Rget_file_name(const H5R_ref_t *ref_ptr, char *buf, size_t size);
+H5_DLL ssize_t H5Rget_obj_name(const H5R_ref_t *ref_ptr, hid_t rapl_id, char *buf, size_t size);
+H5_DLL ssize_t H5Rget_attr_name(const H5R_ref_t *ref_ptr, char *buf, size_t size);
/* Symbols defined for compatibility with previous versions of the HDF5 API.
*
- * Use of these symbols is deprecated.
+ * Use of these symbols is or will be deprecated.
*/
-#ifndef H5_NO_DEPRECATED_SYMBOLS
+
+/* Macros */
+
+/* Versions for compatibility */
+#define H5R_OBJECT H5R_OBJECT1
+#define H5R_DATASET_REGION H5R_DATASET_REGION1
/* Function prototypes */
-H5_DLL H5G_obj_t H5Rget_obj_type1(hid_t id, H5R_type_t ref_type, const void *_ref);
+#ifndef H5_NO_DEPRECATED_SYMBOLS
+
+H5_DLL H5G_obj_t H5Rget_obj_type1(hid_t id, H5R_type_t ref_type, const void *ref);
H5_DLL hid_t H5Rdereference1(hid_t obj_id, H5R_type_t ref_type, const void *ref);
#endif /* H5_NO_DEPRECATED_SYMBOLS */
+H5_DLL herr_t H5Rcreate(void *ref, hid_t loc_id, const char *name, H5R_type_t ref_type, hid_t space_id);
+H5_DLL herr_t H5Rget_obj_type2(hid_t id, H5R_type_t ref_type, const void *ref, H5O_type_t *obj_type);
+H5_DLL hid_t H5Rdereference2(hid_t obj_id, hid_t oapl_id, H5R_type_t ref_type, const void *ref);
+H5_DLL hid_t H5Rget_region(hid_t dataset, H5R_type_t ref_type, const void *ref);
+H5_DLL ssize_t H5Rget_name(hid_t loc_id, H5R_type_t ref_type, const void *ref, char *name, size_t size);
+
#ifdef __cplusplus
}
#endif
#endif /* _H5Rpublic_H */
-
diff --git a/src/H5S.c b/src/H5S.c
index 4c11268..ddfd064 100644
--- a/src/H5S.c
+++ b/src/H5S.c
@@ -21,13 +21,15 @@
/***********/
/* Headers */
/***********/
-#include "H5private.h" /* Generic Functions */
-#include "H5Eprivate.h" /* Error handling */
-#include "H5Fprivate.h" /* Files */
-#include "H5FLprivate.h" /* Free lists */
-#include "H5Iprivate.h" /* IDs */
-#include "H5Oprivate.h" /* Object headers */
-#include "H5Spkg.h" /* Dataspaces */
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5CXprivate.h" /* API Contexts */
+#include "H5Fprivate.h" /* Files */
+#include "H5FLprivate.h" /* Free lists */
+#include "H5Iprivate.h" /* IDs */
+#include "H5MMprivate.h" /* Memory management */
+#include "H5Oprivate.h" /* Object headers */
+#include "H5Spkg.h" /* Dataspaces */
/****************/
@@ -46,7 +48,12 @@
/********************/
/* Local Prototypes */
/********************/
-static htri_t H5S_is_simple(const H5S_t *sdim);
+static htri_t H5S__is_simple(const H5S_t *sdim);
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
/*********************/
@@ -60,18 +67,11 @@ hbool_t H5_PKG_INIT_VAR = FALSE;
const unsigned H5O_sdspace_ver_bounds[] = {
H5O_SDSPACE_VERSION_1, /* H5F_LIBVER_EARLIEST */
H5O_SDSPACE_VERSION_2, /* H5F_LIBVER_V18 */
+ H5O_SDSPACE_VERSION_2, /* H5F_LIBVER_V110 */
+ H5O_SDSPACE_VERSION_2, /* H5F_LIBVER_V112 */
H5O_SDSPACE_VERSION_LATEST /* H5F_LIBVER_LATEST */
};
-/*****************************/
-/* Library Private Variables */
-/*****************************/
-
-
-/*******************/
-/* Local Variables */
-/*******************/
-
/* Declare a free list to manage the H5S_extent_t struct */
H5FL_DEFINE(H5S_extent_t);
@@ -81,12 +81,25 @@ H5FL_DEFINE(H5S_t);
/* Declare a free list to manage the array's of hsize_t's */
H5FL_ARR_DEFINE(hsize_t, H5S_MAX_RANK);
+
+/*******************/
+/* Local Variables */
+/*******************/
+
/* Dataspace ID class */
static const H5I_class_t H5I_DATASPACE_CLS[1] = {{
- H5I_DATASPACE, /* ID class value */
- 0, /* Class flags */
- 2, /* # of reserved IDs for class */
- (H5I_free_t)H5S_close /* Callback routine for closing objects of this class */
+ H5I_DATASPACE, /* ID class value */
+ 0, /* Class flags */
+ 2, /* # of reserved IDs for class */
+ (H5I_free_t)H5S_close /* Callback routine for closing objects of this class */
+}};
+
+/* Dataspace selection iterator ID class */
+static const H5I_class_t H5I_SPACE_SEL_ITER_CLS[1] = {{
+ H5I_SPACE_SEL_ITER, /* ID class value */
+ 0, /* Class flags */
+ 0, /* # of reserved IDs for class */
+ (H5I_free_t)H5S_sel_iter_close /* Callback routine for closing objects of this class */
}};
@@ -94,7 +107,7 @@ static const H5I_class_t H5I_DATASPACE_CLS[1] = {{
static hbool_t H5S_top_package_initialize_s = FALSE;
-
+
/*--------------------------------------------------------------------------
NAME
H5S__init_package -- Initialize interface-specific information
@@ -112,9 +125,13 @@ H5S__init_package(void)
FUNC_ENTER_PACKAGE
- /* Initialize the atom group for the file IDs */
+ /* Initialize the atom group for the dataspace IDs */
if(H5I_register_type(H5I_DATASPACE_CLS) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize interface")
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize dataspace ID class")
+
+ /* Initialize the atom group for the dataspace selction iterator IDs */
+ if(H5I_register_type(H5I_SPACE_SEL_ITER_CLS) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize dataspace selection iterator ID class")
/* Mark "top" of interface as initialized, too */
H5S_top_package_initialize_s = TRUE;
@@ -123,7 +140,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S__init_package() */
-
+
/*--------------------------------------------------------------------------
NAME
H5S_top_term_package
@@ -145,17 +162,22 @@ done:
int
H5S_top_term_package(void)
{
- int n = 0;
+ int n = 0;
FUNC_ENTER_NOAPI_NOINIT_NOERR
if(H5S_top_package_initialize_s) {
- if(H5I_nmembers(H5I_DATASPACE) > 0) {
- (void)H5I_clear_type(H5I_DATASPACE, FALSE, FALSE);
+ if(H5I_nmembers(H5I_DATASPACE) > 0) {
+ (void)H5I_clear_type(H5I_DATASPACE, FALSE, FALSE);
+ n++; /*H5I*/
+ } /* end if */
+
+ if(H5I_nmembers(H5I_SPACE_SEL_ITER) > 0) {
+ (void)H5I_clear_type(H5I_SPACE_SEL_ITER, FALSE, FALSE);
n++; /*H5I*/
- } /* end if */
+ } /* end if */
- /* Mark "top" of interface as closed */
+ /* Mark "top" of interface as closed */
if(0 == n)
H5S_top_package_initialize_s = FALSE;
} /* end if */
@@ -163,7 +185,7 @@ H5S_top_term_package(void)
FUNC_LEAVE_NOAPI(n)
} /* end H5S_top_term_package() */
-
+
/*--------------------------------------------------------------------------
NAME
H5S_term_package
@@ -187,19 +209,23 @@ H5S_top_term_package(void)
int
H5S_term_package(void)
{
- int n = 0;
+ int n = 0;
FUNC_ENTER_NOAPI_NOINIT_NOERR
if(H5_PKG_INIT_VAR) {
/* Sanity checks */
HDassert(0 == H5I_nmembers(H5I_DATASPACE));
+ HDassert(0 == H5I_nmembers(H5I_SPACE_SEL_ITER));
HDassert(FALSE == H5S_top_package_initialize_s);
/* Destroy the dataspace object id group */
n += (H5I_dec_type_ref(H5I_DATASPACE) > 0);
- /* Mark interface as closed */
+ /* Destroy the dataspace selection iterator object id group */
+ n += (H5I_dec_type_ref(H5I_SPACE_SEL_ITER) > 0);
+
+ /* Mark interface as closed */
if(0 == n)
H5_PKG_INIT_VAR = FALSE;
} /* end if */
@@ -208,7 +234,7 @@ H5S_term_package(void)
} /* end H5S_term_package() */
-
+
/*--------------------------------------------------------------------------
NAME
H5S_get_validiated_dataspace
@@ -237,29 +263,28 @@ H5S_get_validated_dataspace(hid_t space_id, const H5S_t **space)
HDassert(space);
- if (space_id < 0)
+ /* Check for invalid ID */
+ if(space_id < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid space_id (ID cannot be a negative number)")
-
- if (H5S_ALL == space_id) {
- /* No special dataspace struct for H5S_ALL */
+
+ /* No special dataspace struct for H5S_ALL */
+ if(H5S_ALL == space_id)
*space = NULL;
- }
else {
/* Get the dataspace pointer */
- if (NULL == (*space = (const H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
+ if(NULL == (*space = (const H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "space_id is not a dataspace ID")
/* Check for valid selection */
- if (H5S_SELECT_VALID(*space) != TRUE)
+ if(H5S_SELECT_VALID(*space) != TRUE)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "selection + offset not within extent")
- }
+ } /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)
-
} /* end H5S_get_validated_dataspace() */
-
+
/*--------------------------------------------------------------------------
NAME
H5S_create
@@ -330,15 +355,14 @@ H5S_create(H5S_class_t type)
ret_value = new_ds;
done:
- if(ret_value == NULL) {
+ if(ret_value == NULL)
if(new_ds && H5S_close(new_ds) < 0)
HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, NULL, "unable to release dataspace")
- } /* end if */
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_create() */
-
+
/*--------------------------------------------------------------------------
NAME
H5Screate
@@ -360,7 +384,7 @@ done:
hid_t
H5Screate(H5S_class_t type)
{
- H5S_t *new_ds=NULL; /* New dataspace structure */
+ H5S_t *new_ds = NULL; /* New dataspace structure */
hid_t ret_value; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -374,39 +398,34 @@ H5Screate(H5S_class_t type)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "unable to create dataspace")
/* Atomize */
- if((ret_value = H5I_register (H5I_DATASPACE, new_ds, TRUE)) < 0)
+ if((ret_value = H5I_register(H5I_DATASPACE, new_ds, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace atom")
done:
- if(ret_value < 0) {
+ if(ret_value < 0)
if(new_ds && H5S_close(new_ds) < 0)
HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace")
- } /* end if */
FUNC_LEAVE_API(ret_value)
} /* end H5Screate() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5S_extent_release
+ * Function: H5S__extent_release
*
- * Purpose: Releases all memory associated with a dataspace extent.
+ * Purpose: Releases all memory associated with a dataspace extent.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Quincey Koziol
- * Thursday, July 23, 1998
- *
- * Modifications:
+ * Programmer: Quincey Koziol
+ * Thursday, July 23, 1998
*
*-------------------------------------------------------------------------
*/
herr_t
-H5S_extent_release(H5S_extent_t *extent)
+H5S__extent_release(H5S_extent_t *extent)
{
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(FAIL)
+ FUNC_ENTER_PACKAGE_NOERR
HDassert(extent);
@@ -418,20 +437,19 @@ H5S_extent_release(H5S_extent_t *extent)
extent->max = H5FL_ARR_FREE(hsize_t, extent->max);
} /* end if */
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5S_extent_release() */
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5S__extent_release() */
+
-
/*-------------------------------------------------------------------------
- * Function: H5S_close
+ * Function: H5S_close
*
- * Purpose: Releases all memory associated with a dataspace.
+ * Purpose: Releases all memory associated with a dataspace.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Robb Matzke
- * Tuesday, December 9, 1997
+ * Programmer: Robb Matzke
+ * Tuesday, December 9, 1997
*
*-------------------------------------------------------------------------
*/
@@ -446,33 +464,33 @@ H5S_close(H5S_t *ds)
/* Release selection (this should come before the extent release) */
if(H5S_SELECT_RELEASE(ds) < 0)
- HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace selection")
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace selection")
/* Release extent */
- if(H5S_extent_release(&ds->extent) < 0)
- HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace extent")
-
- /* Release the main structure */
- ds = H5FL_FREE(H5S_t, ds);
+ if(H5S__extent_release(&ds->extent) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace extent")
done:
+ /* Release the main structure.
+ * Always do this to ensure that we don't leak memory when calling this
+ * function on partially constructed dataspaces (which will fail one or
+ * both of the above calls)
+ */
+ H5FL_FREE(H5S_t, ds);
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_close() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5Sclose
+ * Function: H5Sclose
*
- * Purpose: Release access to a dataspace object.
+ * Purpose: Release access to a dataspace object.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Errors:
- *
- * Programmer: Robb Matzke
- * Tuesday, December 9, 1997
- *
- * Modifications:
+ * Programmer: Robb Matzke
+ * Tuesday, December 9, 1997
*
*-------------------------------------------------------------------------
*/
@@ -485,7 +503,7 @@ H5Sclose(hid_t space_id)
H5TRACE1("e", "i", space_id);
/* Check args */
- if (NULL == H5I_object_verify(space_id,H5I_DATASPACE))
+ if(NULL == H5I_object_verify(space_id, H5I_DATASPACE))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
/* When the reference count reaches zero the resources are freed */
@@ -496,29 +514,26 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Sclose() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5Scopy
- *
- * Purpose: Copies a dataspace.
- *
- * Return: Success: ID of the new dataspace
+ * Function: H5Scopy
*
- * Failure: Negative
+ * Purpose: Copies a dataspace.
*
- * Programmer: Robb Matzke
- * Friday, January 30, 1998
+ * Return: Success: ID of the new dataspace
+ * Failure: Negative
*
- * Modifications:
+ * Programmer: Robb Matzke
+ * Friday, January 30, 1998
*
*-------------------------------------------------------------------------
*/
hid_t
H5Scopy(hid_t space_id)
{
- H5S_t *src;
- H5S_t *dst = NULL;
- hid_t ret_value;
+ H5S_t *src;
+ H5S_t *dst = NULL;
+ hid_t ret_value;
FUNC_ENTER_API(FAIL)
H5TRACE1("i", "i", space_id);
@@ -536,35 +551,32 @@ H5Scopy(hid_t space_id)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace atom")
done:
- if(ret_value < 0) {
+ if(ret_value < 0)
if(dst && H5S_close(dst) < 0)
HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace")
- } /* end if */
FUNC_LEAVE_API(ret_value)
} /* end H5Scopy() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5Sextent_copy
- *
- * Purpose: Copies a dataspace extent.
+ * Function: H5Sextent_copy
*
- * Return: Non-negative on success/Negative on failure
+ * Purpose: Copies a dataspace extent.
*
- * Programmer: Quincey Koziol
- * Thursday, July 23, 1998
+ * Return: Non-negative on success/Negative on failure
*
- * Modifications:
+ * Programmer: Quincey Koziol
+ * Thursday, July 23, 1998
*
*-------------------------------------------------------------------------
*/
herr_t
H5Sextent_copy(hid_t dst_id,hid_t src_id)
{
- H5S_t *src;
- H5S_t *dst;
- herr_t ret_value = SUCCEED;
+ H5S_t *src;
+ H5S_t *dst;
+ herr_t ret_value = SUCCEED;
FUNC_ENTER_API(FAIL)
H5TRACE2("e", "ii", dst_id, src_id);
@@ -583,7 +595,7 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Sextent_copy() */
-
+
/*-------------------------------------------------------------------------
* Function: H5S_extent_copy
*
@@ -594,8 +606,6 @@ done:
* Programmer: Neil Fortner
* Monday, February 23, 2015
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
herr_t
@@ -609,7 +619,7 @@ H5S_extent_copy(H5S_t *dst, const H5S_t *src)
HDassert(src);
/* Copy extent */
- if(H5S_extent_copy_real(&(dst->extent), &(src->extent), TRUE) < 0)
+ if(H5S__extent_copy_real(&(dst->extent), &(src->extent), TRUE) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy extent")
/* If the selection is 'all', update the number of elements selected in the
@@ -622,31 +632,29 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_extent_copy() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5S_extent_copy_real
+ * Function: H5S__extent_copy_real
*
- * Purpose: Copies a dataspace extent
+ * Purpose: Copies a dataspace extent
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Quincey Koziol
- * Wednesday, June 3, 1998
- *
- * Modifications:
+ * Programmer: Quincey Koziol
+ * Wednesday, June 3, 1998
*
*-------------------------------------------------------------------------
*/
herr_t
-H5S_extent_copy_real(H5S_extent_t *dst, const H5S_extent_t *src, hbool_t copy_max)
+H5S__extent_copy_real(H5S_extent_t *dst, const H5S_extent_t *src, hbool_t copy_max)
{
unsigned u;
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(FAIL)
+ FUNC_ENTER_PACKAGE
/* Release destination extent before we copy over it */
- if(H5S_extent_release(dst) < 0)
+ if(H5S__extent_release(dst) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace extent")
/* Copy the regular fields */
@@ -691,34 +699,31 @@ H5S_extent_copy_real(H5S_extent_t *dst, const H5S_extent_t *src, hbool_t copy_ma
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5S_extent_copy_real() */
+} /* end H5S__extent_copy_real() */
+
-
/*-------------------------------------------------------------------------
- * Function: H5S_copy
+ * Function: H5S_copy
*
- * Purpose: Copies a dataspace, by copying the extent and selection through
+ * Purpose: Copies a dataspace, by copying the extent and selection through
* H5S_extent_copy and H5S_select_copy. If the SHARE_SELECTION flag
* is set, then the selection can be shared between the source and
* destination dataspaces. (This should only occur in situations
* where the destination dataspace will immediately change to a new
* selection)
*
- * Return: Success: A pointer to a new copy of SRC
- *
- * Failure: NULL
+ * Return: Success: A pointer to a new copy of SRC
+ * Failure: NULL
*
- * Programmer: Robb Matzke
- * Thursday, December 4, 1997
- *
- * Modifications:
+ * Programmer: Robb Matzke
+ * Thursday, December 4, 1997
*
*-------------------------------------------------------------------------
*/
H5S_t *
H5S_copy(const H5S_t *src, hbool_t share_selection, hbool_t copy_max)
{
- H5S_t *dst = NULL;
+ H5S_t *dst = NULL;
H5S_t *ret_value = NULL; /* Return value */
FUNC_ENTER_NOAPI(NULL)
@@ -727,7 +732,7 @@ H5S_copy(const H5S_t *src, hbool_t share_selection, hbool_t copy_max)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* Copy the source dataspace's extent */
- if(H5S_extent_copy_real(&(dst->extent), &(src->extent), copy_max) < 0)
+ if(H5S__extent_copy_real(&(dst->extent), &(src->extent), copy_max) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, NULL, "can't copy extent")
/* Copy the source dataspace's selection */
@@ -745,26 +750,22 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_copy() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5S_get_simple_extent_npoints
- *
- * Purpose: Determines how many data points a dataset extent has.
+ * Function: H5S_get_simple_extent_npoints
*
- * Return: Success: Number of data points in the dataset extent.
+ * Purpose: Determines how many data points a dataset extent has.
*
- * Failure: negative
+ * Return: Success: Number of data points in the dataset extent.
+ * Failure: negative
*
- * Programmer: Robb Matzke
- * Tuesday, December 9, 1997
+ * Programmer: Robb Matzke
+ * Tuesday, December 9, 1997
*
* Note: This routine participates in the "Inlining C function pointers"
* pattern, don't call it directly, use the appropriate macro
* defined in H5Sprivate.h.
*
- * Modifications:
- * Changed Name - QAK 7/7/98
- *
*-------------------------------------------------------------------------
*/
hssize_t
@@ -784,29 +785,25 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_get_simple_extent_npoints() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5Sget_simple_extent_npoints
- *
- * Purpose: Determines how many data points a dataset extent has.
+ * Function: H5Sget_simple_extent_npoints
*
- * Return: Success: Number of data points in the dataset.
+ * Purpose: Determines how many data points a dataset extent has.
*
- * Failure: negative
+ * Return: Success: Number of data points in the dataset.
+ * Failure: negative
*
- * Programmer: Robb Matzke
- * Tuesday, December 9, 1997
- *
- * Modifications:
- * Changed Name - QAK 7/7/98
+ * Programmer: Robb Matzke
+ * Tuesday, December 9, 1997
*
*-------------------------------------------------------------------------
*/
hssize_t
H5Sget_simple_extent_npoints(hid_t space_id)
{
- H5S_t *ds;
- hssize_t ret_value;
+ H5S_t *ds;
+ hssize_t ret_value;
FUNC_ENTER_API(FAIL)
H5TRACE1("Hs", "i", space_id);
@@ -821,40 +818,37 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Sget_simple_extent_npoints() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5S_get_npoints_max
- *
- * Purpose: Determines the maximum number of data points a dataspace may
- * have. If the `max' array is null then the maximum number of
- * data points is the same as the current number of data points
- * without regard to the hyperslab. If any element of the `max'
- * array is zero then the maximum possible size is returned.
+ * Function: H5S_get_npoints_max
*
- * Return: Success: Maximum number of data points the dataspace
- * may have.
+ * Purpose: Determines the maximum number of data points a dataspace may
+ * have. If the `max' array is null then the maximum number of
+ * data points is the same as the current number of data points
+ * without regard to the hyperslab. If any element of the `max'
+ * array is zero then the maximum possible size is returned.
*
- * Failure: 0
+ * Return: Success: Maximum number of data points the dataspace
+ * may have.
+ * Failure: 0
*
- * Programmer: Robb Matzke
- * Tuesday, December 9, 1997
- *
- * Modifications:
+ * Programmer: Robb Matzke
+ * Tuesday, December 9, 1997
*
*-------------------------------------------------------------------------
*/
hsize_t
H5S_get_npoints_max(const H5S_t *ds)
{
- unsigned u;
- hsize_t ret_value = 0; /* Return value */
+ unsigned u;
+ hsize_t ret_value = 0; /* Return value */
FUNC_ENTER_NOAPI(0)
/* check args */
HDassert(ds);
- switch (H5S_GET_EXTENT_TYPE(ds)) {
+ switch(H5S_GET_EXTENT_TYPE(ds)) {
case H5S_NULL:
ret_value = 0;
break;
@@ -864,54 +858,50 @@ H5S_get_npoints_max(const H5S_t *ds)
break;
case H5S_SIMPLE:
- if (ds->extent.max) {
- for (ret_value=1, u=0; u<ds->extent.rank; u++) {
- if (H5S_UNLIMITED==ds->extent.max[u]) {
+ if(ds->extent.max) {
+ for(ret_value = 1, u = 0; u < ds->extent.rank; u++) {
+ if(H5S_UNLIMITED == ds->extent.max[u]) {
ret_value = HSIZET_MAX;
break;
- }
+ } /* end if */
else
ret_value *= ds->extent.max[u];
- }
- }
- else {
- for (ret_value=1, u=0; u<ds->extent.rank; u++)
+ } /* end for */
+ } /* end if */
+ else
+ for(ret_value = 1, u = 0; u < ds->extent.rank; u++)
ret_value *= ds->extent.size[u];
- }
break;
case H5S_NO_CLASS:
default:
HDassert("unknown dataspace class" && 0);
HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, 0, "internal error (unknown dataspace class)")
- }
+ } /* end switch */
done:
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5S_get_npoints_max() */
+
-
/*-------------------------------------------------------------------------
- * Function: H5Sget_simple_extent_ndims
- *
- * Purpose: Determines the dimensionality of a dataspace.
+ * Function: H5Sget_simple_extent_ndims
*
- * Return: Success: The number of dimensions in a dataspace.
+ * Purpose: Determines the dimensionality of a dataspace.
*
- * Failure: Negative
+ * Return: Success: The number of dimensions in a dataspace.
+ * Failure: Negative
*
- * Programmer: Robb Matzke
- * Thursday, December 11, 1997
- *
- * Modifications:
+ * Programmer: Robb Matzke
+ * Thursday, December 11, 1997
*
*-------------------------------------------------------------------------
*/
int
H5Sget_simple_extent_ndims(hid_t space_id)
{
- H5S_t *ds;
- int ret_value;
+ H5S_t *ds;
+ int ret_value; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE1("Is", "i", space_id);
@@ -926,32 +916,29 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Sget_simple_extent_ndims() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5S_get_simple_extent_ndims
- *
- * Purpose: Returns the number of dimensions in a dataspace.
+ * Function: H5S_get_simple_extent_ndims
*
- * Return: Success: Non-negative number of dimensions. Zero
- * implies a scalar.
+ * Purpose: Returns the number of dimensions in a dataspace.
*
- * Failure: Negative
+ * Return: Success: Non-negative number of dimensions. Zero
+ * implies a scalar.
+ * Failure: Negative
*
- * Programmer: Robb Matzke
- * Thursday, December 11, 1997
+ * Programmer: Robb Matzke
+ * Thursday, December 11, 1997
*
* Note: This routine participates in the "Inlining C function pointers"
* pattern, don't call it directly, use the appropriate macro
* defined in H5Sprivate.h.
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
int
H5S_get_simple_extent_ndims(const H5S_t *ds)
{
- int ret_value = -1; /* Return value */
+ int ret_value = -1; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
@@ -975,69 +962,62 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_get_simple_extent_ndims() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5Sget_simple_extent_dims
+ * Function: H5Sget_simple_extent_dims
*
- * Purpose: Returns the size and maximum sizes in each dimension of
- * a dataspace DS through the DIMS and MAXDIMS arguments.
+ * Purpose: Returns the size and maximum sizes in each dimension of
+ * a dataspace DS through the DIMS and MAXDIMS arguments.
*
- * Return: Success: Number of dimensions, the same value as
- * returned by H5Sget_simple_extent_ndims().
+ * Return: Success: Number of dimensions, the same value as
+ * returned by H5Sget_simple_extent_ndims().
+ * Failure: Negative
*
- * Failure: Negative
- *
- * Programmer: Robb Matzke
- * Thursday, December 11, 1997
- *
- * Modifications:
- * June 18, 1998 Albert Cheng
- * Added maxdims argument. Removed dims argument check
- * since it can still return ndims even if both dims and
- * maxdims are NULLs.
+ * Programmer: Robb Matzke
+ * Thursday, December 11, 1997
*
*-------------------------------------------------------------------------
*/
int
H5Sget_simple_extent_dims(hid_t space_id, hsize_t dims[]/*out*/,
- hsize_t maxdims[]/*out*/)
+ hsize_t maxdims[]/*out*/)
{
- H5S_t *ds;
- int ret_value;
+ H5S_t *ds;
+ int ret_value; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE3("Is", "ixx", space_id, dims, maxdims);
/* Check args */
- if (NULL == (ds = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
+ if(NULL == (ds = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
ret_value = H5S_get_simple_extent_dims(ds, dims, maxdims);
done:
FUNC_LEAVE_API(ret_value)
-}
+} /* end H5Sget_simple_extent_dims() */
+
-
/*-------------------------------------------------------------------------
- * Function: H5S_extent_get_dims
+ * Function: H5S_extent_get_dims
*
- * Purpose: Returns the size in each dimension of a dataspace. This
- * function may not be meaningful for all types of dataspaces.
+ * Purpose: Returns the size in each dimension of a dataspace. This
+ * function may not be meaningful for all types of dataspaces.
*
- * Return: Success: Number of dimensions. Zero implies scalar.
- * Failure: Negative
+ * Return: Success: Number of dimensions. Zero implies scalar.
+ * Failure: Negative
*
- * Programmer: Quincey Koziol
- * Tuesday, June 30, 2009
+ * Programmer: Quincey Koziol
+ * Tuesday, June 30, 2009
*
*-------------------------------------------------------------------------
*/
int
H5S_extent_get_dims(const H5S_extent_t *ext, hsize_t dims[], hsize_t max_dims[])
{
- int i; /* Local index variable */
- int ret_value = -1; /* Return value */
+ int i; /* Local index variable */
+ int ret_value = -1; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
@@ -1074,28 +1054,25 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_extent_get_dims() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5S_get_simple_extent_dims
- *
- * Purpose: Returns the size in each dimension of a dataspace. This
- * function may not be meaningful for all types of dataspaces.
+ * Function: H5S_get_simple_extent_dims
*
- * Return: Success: Number of dimensions. Zero implies scalar.
+ * Purpose: Returns the size in each dimension of a dataspace. This
+ * function may not be meaningful for all types of dataspaces.
*
- * Failure: Negative
+ * Return: Success: Number of dimensions. Zero implies scalar.
+ * Failure: Negative
*
- * Programmer: Robb Matzke
- * Thursday, December 11, 1997
- *
- * Modifications:
+ * Programmer: Robb Matzke
+ * Thursday, December 11, 1997
*
*-------------------------------------------------------------------------
*/
int
H5S_get_simple_extent_dims(const H5S_t *ds, hsize_t dims[], hsize_t max_dims[])
{
- int ret_value = -1; /* Return value */
+ int ret_value = -1; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
@@ -1110,17 +1087,17 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_get_simple_extent_dims() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5S_write
+ * Function: H5S_write
*
- * Purpose: Updates a dataspace by writing a message to an object
- * header.
+ * Purpose: Updates a dataspace by writing a message to an object
+ * header.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Robb Matzke
- * Tuesday, December 9, 1997
+ * Programmer: Robb Matzke
+ * Tuesday, December 9, 1997
*
*-------------------------------------------------------------------------
*/
@@ -1144,24 +1121,17 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_write() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5S_append
- *
- * Purpose: Updates a dataspace by adding a message to an object
- * header.
- *
- * Return: Non-negative on success/Negative on failure
+ * Function: H5S_append
*
- * Programmer: Quincey Koziol
- * Tuesday, December 31, 2002
+ * Purpose: Updates a dataspace by adding a message to an object
+ * header.
*
- * Modifications:
+ * Return: Non-negative on success/Negative on failure
*
- * John Mainzer, 6/6/05
- * Updated function to use the new dirtied parameter of
- * H5AC_unprotect() instead of manipulating the is_dirty
- * field of the cache info.
+ * Programmer: Quincey Koziol
+ * Tuesday, December 31, 2002
*
*-------------------------------------------------------------------------
*/
@@ -1185,25 +1155,24 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_append() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5S_read
- *
- * Purpose: Reads the dataspace from an object header.
+ * Function: H5S_read
*
- * Return: Success: Pointer to a new dataspace.
+ * Purpose: Reads the dataspace from an object header.
*
- * Failure: NULL
+ * Return: Success: Pointer to a new dataspace.
+ * Failure: NULL
*
- * Programmer: Robb Matzke
- * Tuesday, December 9, 1997
+ * Programmer: Robb Matzke
+ * Tuesday, December 9, 1997
*
*-------------------------------------------------------------------------
*/
H5S_t *
H5S_read(const H5O_loc_t *loc)
{
- H5S_t *ds = NULL; /* Dataspace to return */
+ H5S_t *ds = NULL; /* Dataspace to return */
H5S_t *ret_value = NULL; /* Return value */
FUNC_ENTER_NOAPI(NULL)
@@ -1225,47 +1194,46 @@ H5S_read(const H5O_loc_t *loc)
ret_value = ds;
done:
- if(ret_value == NULL) {
+ if(ret_value == NULL)
if(ds != NULL)
ds = H5FL_FREE(H5S_t, ds);
- } /* end if */
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_read() */
-
+
/*--------------------------------------------------------------------------
NAME
- H5S_is_simple
+ H5S__is_simple
PURPOSE
Check if a dataspace is simple (internal)
USAGE
- htri_t H5S_is_simple(sdim)
- H5S_t *sdim; IN: Pointer to dataspace object to query
+ htri_t H5S__is_simple(sdim)
+ H5S_t *sdim; IN: Pointer to dataspace object to query
RETURNS
TRUE/FALSE/FAIL
DESCRIPTION
- This function determines the if a dataspace is "simple". ie. if it
+ This function determines the if a dataspace is "simple". ie. if it
has orthogonal, evenly spaced dimensions.
--------------------------------------------------------------------------*/
static htri_t
-H5S_is_simple(const H5S_t *sdim)
+H5S__is_simple(const H5S_t *sdim)
{
htri_t ret_value = FAIL; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
/* Check args and all the boring stuff. */
HDassert(sdim);
/* H5S_NULL shouldn't be simple dataspace */
ret_value = (H5S_GET_EXTENT_TYPE(sdim) == H5S_SIMPLE ||
- H5S_GET_EXTENT_TYPE(sdim) == H5S_SCALAR) ? TRUE : FALSE;
+ H5S_GET_EXTENT_TYPE(sdim) == H5S_SCALAR) ? TRUE : FALSE;
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5S_is_simple() */
+} /* end H5S__is_simple() */
+
-
/*--------------------------------------------------------------------------
NAME
H5Sis_simple
@@ -1273,33 +1241,33 @@ H5S_is_simple(const H5S_t *sdim)
Check if a dataspace is simple
USAGE
htri_t H5Sis_simple(space_id)
- hid_t space_id; IN: ID of dataspace object to query
+ hid_t space_id; IN: ID of dataspace object to query
RETURNS
TRUE/FALSE/FAIL
DESCRIPTION
- This function determines the if a dataspace is "simple". ie. if it
+ This function determines the if a dataspace is "simple". ie. if it
has orthogonal, evenly spaced dimensions.
--------------------------------------------------------------------------*/
htri_t
H5Sis_simple(hid_t space_id)
{
- H5S_t *space; /* dataspace to modify */
- htri_t ret_value;
+ H5S_t *space; /* Dataspace to check */
+ htri_t ret_value; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE1("t", "i", space_id);
/* Check args and all the boring stuff. */
- if ((space = (H5S_t *)H5I_object_verify(space_id,H5I_DATASPACE)) == NULL)
- HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "not a dataspace")
+ if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "not a dataspace")
- ret_value = H5S_is_simple(space);
+ ret_value = H5S__is_simple(space);
- done:
+done:
FUNC_LEAVE_API(ret_value)
-}
+} /* end H5Sis_simple() */
+
-
/*--------------------------------------------------------------------------
NAME
H5Sset_extent_simple
@@ -1307,11 +1275,11 @@ H5Sis_simple(hid_t space_id)
Sets the size of a simple dataspace
USAGE
herr_t H5Sset_extent_simple(space_id, rank, dims, max)
- hid_t space_id; IN: Dataspace object to query
- int rank; IN: # of dimensions for the dataspace
+ hid_t space_id; IN: Dataspace object to query
+ int rank; IN: # of dimensions for the dataspace
const size_t *dims; IN: Size of each dimension for the dataspace
- const size_t *max; IN: Maximum size of each dimension for the
- dataspace
+ const size_t *max; IN: Maximum size of each dimension for the
+ dataspace
RETURNS
Non-negative on success/Negative on failure
DESCRIPTION
@@ -1325,94 +1293,79 @@ H5Sis_simple(hid_t space_id)
Currently, only the first dimension in the array (the slowest) may be
unlimited in size.
- MODIFICATION
- A null dataspace cannot be created from simple space with this function.
-
- Christian Chilan 01/17/2007
- Verifies that each element of DIMS is not equal to H5S_UNLIMITED.
-
- Raymond Lu 03/30/2011
- We allow 0 dimension size for non-unlimited dimension starting from 1.8.7
- release.
--------------------------------------------------------------------------*/
herr_t
H5Sset_extent_simple(hid_t space_id, int rank, const hsize_t dims[/*rank*/],
- const hsize_t max[/*rank*/])
+ const hsize_t max[/*rank*/])
{
- H5S_t *space; /* dataspace to modify */
- int u; /* local counting variable */
- herr_t ret_value=SUCCEED; /* Return value */
+ H5S_t *space; /* Dataspace to modify */
+ int u; /* Local counting variable */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE4("e", "iIs*[a1]h*[a1]h", space_id, rank, dims, max);
/* Check args */
- if ((space = (H5S_t *)H5I_object_verify(space_id,H5I_DATASPACE)) == NULL)
+ if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "not a dataspace")
- if (rank > 0 && dims == NULL)
+ if(rank > 0 && dims == NULL)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no dimensions specified")
- if (rank<0 || rank>H5S_MAX_RANK)
+ if(rank < 0 || rank > H5S_MAX_RANK)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid rank")
- if (dims) {
- for (u=0; u<rank; u++) {
- if (H5S_UNLIMITED==dims[u])
+ if(dims)
+ for(u = 0; u < rank; u++)
+ if(H5S_UNLIMITED == dims[u])
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "current dimension must have a specific size, not H5S_UNLIMITED")
- }
- }
- if (max!=NULL) {
- if(dims==NULL)
+ if(max != NULL) {
+ if(dims == NULL)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "maximum dimension specified, but no current dimensions specified")
- for (u=0; u<rank; u++) {
- if (max[u]!=H5S_UNLIMITED && max[u]<dims[u])
+ for(u = 0; u < rank; u++)
+ if(max[u] != H5S_UNLIMITED && max[u] < dims[u])
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid maximum dimension size")
- }
- }
+ } /* end if */
/* Do it */
- if (H5S_set_extent_simple(space, (unsigned)rank, dims, max)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to set simple extent")
+ if(H5S_set_extent_simple(space, (unsigned)rank, dims, max) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to set simple extent")
done:
FUNC_LEAVE_API(ret_value)
-}
+} /* end H5Sset_extent_simple() */
+
-
/*-------------------------------------------------------------------------
- * Function: H5S_set_extent_simple
+ * Function: H5S_set_extent_simple
*
- * Purpose: This is where the real work happens for
- * H5Sset_extent_simple().
+ * Purpose: This is where the real work happens for
+ * H5Sset_extent_simple().
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Robb Matzke (copied from H5Sset_extent_simple)
+ * Programmer: Robb Matzke
* Wednesday, July 8, 1998
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
herr_t
H5S_set_extent_simple(H5S_t *space, unsigned rank, const hsize_t *dims,
- const hsize_t *max)
+ const hsize_t *max)
{
unsigned u; /* Local index variable */
- herr_t ret_value = SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
/* Check args */
HDassert(rank <= H5S_MAX_RANK);
- HDassert(0 == rank || dims);
/* shift out of the previous state to a "simple" dataspace. */
- if(H5S_extent_release(&space->extent) < 0)
+ if(H5S__extent_release(&space->extent) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "failed to release previous dataspace extent")
- if(rank == 0) { /* scalar variable */
+ if(rank == 0) { /* scalar variable */
space->extent.type = H5S_SCALAR;
space->extent.nelem = 1;
- space->extent.rank = 0; /* set to scalar rank */
+ space->extent.rank = 0; /* set to scalar rank */
} /* end if */
else {
hsize_t nelem; /* Number of elements in extent */
@@ -1424,21 +1377,20 @@ H5S_set_extent_simple(H5S_t *space, unsigned rank, const hsize_t *dims,
space->extent.size = (hsize_t *)H5FL_ARR_MALLOC(hsize_t, (size_t)rank);
/* Copy the dimensions & compute the number of elements in the extent */
- for(u = 0, nelem = 1; u < space->extent.rank; u++) {
+ for(u = 0, nelem = 1; dims && (u < space->extent.rank); u++) {
space->extent.size[u] = dims[u];
nelem *= dims[u];
} /* end for */
space->extent.nelem = nelem;
- /* Copy the maximum dimensions if specified. Otherwise, the maximal dimensions are the
+ /* Copy the maximum dimensions if specified. Otherwise, the maximal dimensions are the
* same as the dimension */
space->extent.max = (hsize_t *)H5FL_ARR_MALLOC(hsize_t, (size_t)rank);
- if(max != NULL) {
- HDmemcpy(space->extent.max, max, sizeof(hsize_t) * rank);
- } else {
- for(u = 0; u < space->extent.rank; u++)
+ if(max != NULL)
+ H5MM_memcpy(space->extent.max, max, sizeof(hsize_t) * rank);
+ else
+ for(u = 0; dims && (u < space->extent.rank); u++)
space->extent.max[u] = dims[u];
- }
} /* end else */
/* Selection related cleanup */
@@ -1454,42 +1406,36 @@ H5S_set_extent_simple(H5S_t *space, unsigned rank, const hsize_t *dims,
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_set_extent_simple() */
+} /* end H5S_set_extent_simple() */
+
-
/*-------------------------------------------------------------------------
- * Function: H5Screate_simple
- *
- * Purpose: Creates a new simple dataspace object and opens it for
- * access. The DIMS argument is the size of the simple dataset
- * and the MAXDIMS argument is the upper limit on the size of
- * the dataset. MAXDIMS may be the null pointer in which case
- * the upper limit is the same as DIMS. If an element of
- * MAXDIMS is H5S_UNLIMITED then the corresponding dimension is
- * unlimited, otherwise no element of MAXDIMS should be smaller
- * than the corresponding element of DIMS.
- *
- * Return: Success: The ID for the new simple dataspace object.
+ * Function: H5Screate_simple
*
- * Failure: Negative
+ * Purpose: Creates a new simple dataspace object and opens it for
+ * access. The DIMS argument is the size of the simple dataset
+ * and the MAXDIMS argument is the upper limit on the size of
+ * the dataset. MAXDIMS may be the null pointer in which case
+ * the upper limit is the same as DIMS. If an element of
+ * MAXDIMS is H5S_UNLIMITED then the corresponding dimension is
+ * unlimited, otherwise no element of MAXDIMS should be smaller
+ * than the corresponding element of DIMS.
*
- * Programmer: Quincey Koziol
- * Tuesday, January 27, 1998
+ * Return: Success: The ID for the new simple dataspace object.
+ * Failure: Negative
*
- * Modification:
- * Raymond Lu 03/30/2011
- * We allow 0-dimension for non-unlimited dimension starting
- * from 1.8.7 release.
+ * Programmer: Quincey Koziol
+ * Tuesday, January 27, 1998
*
*-------------------------------------------------------------------------
*/
hid_t
H5Screate_simple(int rank, const hsize_t dims[/*rank*/],
- const hsize_t maxdims[/*rank*/])
+ const hsize_t maxdims[/*rank*/])
{
- H5S_t *space = NULL;
- int i;
- hid_t ret_value;
+ H5S_t *space = NULL;
+ int i;
+ hid_t ret_value; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE3("i", "Is*[a0]h*[a0]h", rank, dims, maxdims);
@@ -1515,7 +1461,7 @@ H5Screate_simple(int rank, const hsize_t dims[/*rank*/],
} /* end for */
/* Create the space and set the extent */
- if(NULL == (space = H5S_create_simple((unsigned)rank,dims,maxdims)))
+ if(NULL == (space = H5S_create_simple((unsigned)rank, dims, maxdims)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't create simple dataspace")
/* Atomize */
@@ -1523,106 +1469,103 @@ H5Screate_simple(int rank, const hsize_t dims[/*rank*/],
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace ID")
done:
- if(ret_value < 0) {
+ if(ret_value < 0)
if(space && H5S_close(space) < 0)
HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace")
- } /* end if */
FUNC_LEAVE_API(ret_value)
} /* end H5Screate_simple() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5S_create_simple
+ * Function: H5S_create_simple
*
- * Purpose: Internal function to create simple dataspace
+ * Purpose: Internal function to create simple dataspace
*
- * Return: Success: The ID for the new simple dataspace object.
- * Failure: Negative
+ * Return: Success: The ID for the new simple dataspace object.
+ * Failure: Negative
*
- * Errors:
- *
- * Programmer: Quincey Koziol
- * Thursday, April 3, 2003
- *
- * Modifications:
- * Extracted from H5Screate_simple
- * Quincey Koziol, Thursday, April 3, 2003
+ * Programmer: Quincey Koziol
+ * Thursday, April 3, 2003
*
*-------------------------------------------------------------------------
*/
H5S_t *
H5S_create_simple(unsigned rank, const hsize_t dims[/*rank*/],
- const hsize_t maxdims[/*rank*/])
+ const hsize_t maxdims[/*rank*/])
{
H5S_t *ret_value = NULL; /* Return value */
FUNC_ENTER_NOAPI(NULL)
/* Check arguments */
- HDassert(rank <=H5S_MAX_RANK);
+ HDassert(rank <= H5S_MAX_RANK);
/* Create the space and set the extent */
- if(NULL==(ret_value=H5S_create(H5S_SIMPLE)))
+ if(NULL == (ret_value = H5S_create(H5S_SIMPLE)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, NULL, "can't create simple dataspace")
- if(H5S_set_extent_simple(ret_value,rank,dims,maxdims)<0)
+ if(H5S_set_extent_simple(ret_value, rank, dims, maxdims) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, NULL, "can't set dimensions")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_create_simple() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5Sencode
+ * Function: H5Sencode2
*
- * Purpose: Given a dataspace ID, converts the object description
+ * Purpose: Given a dataspace ID, converts the object description
* (including selection) into binary in a buffer.
+ * The selection will be encoded according to the file
+ * format setting in fapl.
*
- * Return: Success: non-negative
- *
- * Failure: negative
+ * Return: Success: non-negative
+ * Failure: negative
*
- * Programmer: Raymond Lu
+ * Programmer: Raymond Lu
* slu@ncsa.uiuc.edu
* July 14, 2004
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
herr_t
-H5Sencode(hid_t obj_id, void *buf, size_t *nalloc)
+H5Sencode2(hid_t obj_id, void *buf, size_t *nalloc, hid_t fapl_id)
{
H5S_t *dspace;
herr_t ret_value=SUCCEED;
FUNC_ENTER_API(FAIL)
- H5TRACE3("e", "i*x*z", obj_id, buf, nalloc);
+ H5TRACE4("e", "i*x*zi", obj_id, buf, nalloc, fapl_id);
/* Check argument and retrieve object */
- if (NULL == (dspace = (H5S_t *)H5I_object_verify(obj_id, H5I_DATASPACE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
+ if(NULL == (dspace = (H5S_t *)H5I_object_verify(obj_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
- if(H5S_encode(dspace, (unsigned char **)&buf, nalloc)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTENCODE, FAIL, "can't encode dataspace")
+ /* Verify access property list and set up collective metadata if appropriate */
+ if(H5CX_set_apl(&fapl_id, H5P_CLS_FACC, H5I_INVALID_HID, TRUE) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info")
+
+
+ if(H5S_encode(dspace, (unsigned char **)&buf, nalloc) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTENCODE, FAIL, "can't encode dataspace")
done:
FUNC_LEAVE_API(ret_value)
-}
+} /* H5Sencode2() */
+
-
/*-------------------------------------------------------------------------
- * Function: H5S_encode
+ * Function: H5S_encode
*
- * Purpose: Private function for H5Sencode. Converts an object
+ * Purpose: Private function for H5Sencode. Converts an object
* description for dataspace and its selection into binary
* in a buffer.
*
- * Return: Success: non-negative
- * Failure: negative
+ * Return: Success: non-negative
+ * Failure: negative
*
- * Programmer: Raymond Lu
+ * Programmer: Raymond Lu
* slu@ncsa.uiuc.edu
* July 14, 2004
*
@@ -1641,15 +1584,15 @@ H5S_encode(H5S_t *obj, unsigned char **p, size_t *nalloc)
/* Allocate "fake" file structure */
if(NULL == (f = H5F_fake_alloc((uint8_t)0)))
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate fake file struct")
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate fake file struct")
/* Find out the size of buffer needed for extent */
if((extent_size = H5O_msg_raw_size(f, H5O_SDSPACE_ID, TRUE, obj)) == 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADSIZE, FAIL, "can't find dataspace size")
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADSIZE, FAIL, "can't find dataspace size")
/* Find out the size of buffer needed for selection */
if((sselect_size = H5S_SELECT_SERIAL_SIZE(obj)) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADSIZE, FAIL, "can't find dataspace selection size")
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADSIZE, FAIL, "can't find dataspace selection size")
H5_CHECKED_ASSIGN(select_size, size_t, sselect_size, hssize_t);
/* Verify the size of buffer. If it's not big enough, simply return the
@@ -1690,18 +1633,17 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_encode() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5Sdecode
+ * Function: H5Sdecode
*
- * Purpose: Decode a binary object description of dataspace and
+ * Purpose: Decode a binary object description of dataspace and
* return a new object handle.
*
- * Return: Success: dataspace ID(non-negative)
- *
- * Failure: negative
+ * Return: Success: dataspace ID(non-negative)
+ * Failure: negative
*
- * Programmer: Raymond Lu
+ * Programmer: Raymond Lu
* slu@ncsa.uiuc.edu
* July 14, 2004
*
@@ -1717,31 +1659,30 @@ H5Sdecode(const void *buf)
H5TRACE1("i", "*x", buf);
if(buf == NULL)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "empty buffer")
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "empty buffer")
if((ds = H5S_decode((const unsigned char **)&buf)) == NULL)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDECODE, FAIL, "can't decode object")
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDECODE, FAIL, "can't decode object")
/* Register the type and return the ID */
if((ret_value = H5I_register(H5I_DATASPACE, ds, TRUE)) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTREGISTER, FAIL, "unable to register dataspace")
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTREGISTER, FAIL, "unable to register dataspace")
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Sdecode() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5S_decode
+ * Function: H5S_decode
*
- * Purpose: Private function for H5Sdecode. Reconstructs a binary
+ * Purpose: Private function for H5Sdecode. Reconstructs a binary
* description of dataspace and returns a new object handle.
*
- * Return: Success: dataspace ID(non-negative)
- *
- * Failure: negative
+ * Return: Success: dataspace ID(non-negative)
+ * Failure: negative
*
- * Programmer: Raymond Lu
+ * Programmer: Raymond Lu
* slu@ncsa.uiuc.edu
* July 14, 2004
*
@@ -1762,18 +1703,18 @@ H5S_decode(const unsigned char **p)
/* Decode the type of the information */
if(*pp++ != H5O_SDSPACE_ID)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADMESG, NULL, "not an encoded dataspace")
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADMESG, NULL, "not an encoded dataspace")
/* Decode the version of the dataspace information */
if(*pp++ != H5S_ENCODE_VERSION)
- HGOTO_ERROR(H5E_DATASPACE, H5E_VERSION, NULL, "unknown version of encoded dataspace")
+ HGOTO_ERROR(H5E_DATASPACE, H5E_VERSION, NULL, "unknown version of encoded dataspace")
/* Decode the "size of size" information */
sizeof_size = *pp++;
/* Allocate "fake" file structure */
if(NULL == (f = H5F_fake_alloc(sizeof_size)))
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, NULL, "can't allocate fake file struct")
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, NULL, "can't allocate fake file struct")
/* Decode size of extent information */
UINT32DECODE(pp, extent_size);
@@ -1785,11 +1726,11 @@ H5S_decode(const unsigned char **p)
pp += extent_size;
/* Copy the extent into dataspace structure */
- if((ds = H5FL_CALLOC(H5S_t))==NULL)
+ if(NULL == (ds = H5FL_CALLOC(H5S_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for dataspace conversion path table")
- if(H5O_msg_copy(H5O_SDSPACE_ID, extent, &(ds->extent)) == NULL)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, NULL, "can't copy object")
- if(H5S_extent_release(extent) < 0)
+ if(NULL == H5O_msg_copy(H5O_SDSPACE_ID, extent, &(ds->extent)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, NULL, "can't copy object")
+ if(H5S__extent_release(extent) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTDELETE, NULL, "can't release previous dataspace")
extent = H5FL_FREE(H5S_extent_t, extent);
@@ -1813,83 +1754,73 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_decode() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5S_get_simple_extent_type
- *
- * Purpose: Internal function for retrieving the type of extent for a dataspace object
- *
- * Return: Success: The class of the dataspace object
+ * Function: H5S_get_simple_extent_type
*
- * Failure: N5S_NO_CLASS
+ * Purpose: Internal function for retrieving the type of extent for a dataspace object
*
- * Errors:
+ * Return: Success: The class of the dataspace object
+ * Failure: N5S_NO_CLASS
*
- * Programmer: Quincey Koziol
- * Thursday, September 28, 2000
+ * Programmer: Quincey Koziol
+ * Thursday, September 28, 2000
*
* Note: This routine participates in the "Inlining C function pointers"
* pattern, don't call it directly, use the appropriate macro
* defined in H5Sprivate.h.
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
H5S_class_t
H5S_get_simple_extent_type(const H5S_t *space)
{
- H5S_class_t ret_value = H5S_NO_CLASS; /* Return value */
+ H5S_class_t ret_value = H5S_NO_CLASS; /* Return value */
FUNC_ENTER_NOAPI(H5S_NO_CLASS)
HDassert(space);
- ret_value=H5S_GET_EXTENT_TYPE(space);
+ ret_value = H5S_GET_EXTENT_TYPE(space);
done:
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5S_get_simple_extent_type() */
+
-
/*-------------------------------------------------------------------------
- * Function: H5Sget_simple_extent_type
- *
- * Purpose: Retrieves the type of extent for a dataspace object
- *
- * Return: Success: The class of the dataspace object
- *
- * Failure: N5S_NO_CLASS
+ * Function: H5Sget_simple_extent_type
*
- * Errors:
+ * Purpose: Retrieves the type of extent for a dataspace object
*
- * Programmer: Quincey Koziol
- * Thursday, July 23, 1998
+ * Return: Success: The class of the dataspace object
+ * Failure: N5S_NO_CLASS
*
- * Modifications:
+ * Programmer: Quincey Koziol
+ * Thursday, July 23, 1998
*
*-------------------------------------------------------------------------
*/
H5S_class_t
H5Sget_simple_extent_type(hid_t sid)
{
- H5S_t *space;
- H5S_class_t ret_value;
+ H5S_t *space;
+ H5S_class_t ret_value; /* Return value */
FUNC_ENTER_API(H5S_NO_CLASS)
H5TRACE1("Sc", "i", sid);
/* Check arguments */
- if (NULL == (space = (H5S_t *)H5I_object_verify(sid, H5I_DATASPACE)))
+ if(NULL == (space = (H5S_t *)H5I_object_verify(sid, H5I_DATASPACE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5S_NO_CLASS, "not a dataspace")
- ret_value=H5S_GET_EXTENT_TYPE(space);
+ ret_value = H5S_GET_EXTENT_TYPE(space);
done:
FUNC_LEAVE_API(ret_value)
-}
+} /* end H5Sget_simple_extent_type() */
+
-
/*--------------------------------------------------------------------------
NAME
H5Sset_extent_none
@@ -1897,80 +1828,37 @@ done:
Resets the extent of a dataspace back to "none"
USAGE
herr_t H5Sset_extent_none(space_id)
- hid_t space_id; IN: Dataspace object to reset
+ hid_t space_id; IN: Dataspace object to reset
RETURNS
Non-negative on success/Negative on failure
DESCRIPTION
- This function resets the type of a dataspace back to "none" with no
+ This function resets the type of a dataspace back to "none" with no
extent information stored for the dataspace.
--------------------------------------------------------------------------*/
herr_t
H5Sset_extent_none(hid_t space_id)
{
- H5S_t *space; /* dataspace to modify */
- herr_t ret_value=SUCCEED; /* Return value */
+ H5S_t *space; /* Dataspace to modify */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE1("e", "i", space_id);
/* Check args */
- if (NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
+ if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "not a dataspace")
/* Clear the previous extent from the dataspace */
- if(H5S_extent_release(&space->extent)<0)
+ if(H5S__extent_release(&space->extent) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTDELETE, FAIL, "can't release previous dataspace")
- space->extent.type=H5S_NO_CLASS;
+ space->extent.type = H5S_NO_CLASS;
done:
FUNC_LEAVE_API(ret_value)
-} /* end H5Sset_extent_none() */
+} /* end H5Sset_extent_none() */
-
-/*--------------------------------------------------------------------------
- NAME
- H5Soffset_simple
- PURPOSE
- Changes the offset of a selection within a simple dataspace extent
- USAGE
- herr_t H5Soffset_simple(space_id, offset)
- hid_t space_id; IN: Dataspace object to reset
- const hssize_t *offset; IN: Offset to position the selection at
- RETURNS
- Non-negative on success/Negative on failure
- DESCRIPTION
- This function creates an offset for the selection within an extent, allowing
- the same shaped selection to be moved to different locations within a
- dataspace without requiring it to be re-defined.
---------------------------------------------------------------------------*/
-herr_t
-H5Soffset_simple(hid_t space_id, const hssize_t *offset)
-{
- H5S_t *space; /* dataspace to modify */
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_API(FAIL)
- H5TRACE2("e", "i*Hs", space_id, offset);
-
- /* Check args */
- if (NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
- HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "not a dataspace")
- if (space->extent.rank==0 || (H5S_GET_EXTENT_TYPE(space)==H5S_SCALAR
- || H5S_GET_EXTENT_TYPE(space)==H5S_NULL))
- HGOTO_ERROR(H5E_ATOM, H5E_UNSUPPORTED, FAIL, "can't set offset on scalar or null dataspace")
- if (offset == NULL)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no offset specified")
- /* Set the selection offset */
- if(H5S_select_offset(space,offset)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't set offset")
-
-done:
- FUNC_LEAVE_API(ret_value)
-} /* end H5Soffset_simple() */
-
-
/*-------------------------------------------------------------------------
* Function: H5S_set_extent
*
@@ -1997,7 +1885,7 @@ H5S_set_extent(H5S_t *space, const hsize_t *size)
HDassert(size);
/* Verify that the dimensions being changed are allowed to change */
- for(u = 0; u < space->extent.rank; u++) {
+ for(u = 0; u < space->extent.rank; u++)
if(space->extent.size[u] != size[u]) {
/* Check for invalid dimension size modification */
if(space->extent.max && H5S_UNLIMITED != space->extent.max[u] &&
@@ -2007,7 +1895,6 @@ H5S_set_extent(H5S_t *space, const hsize_t *size)
/* Indicate that dimension size can be modified */
ret_value = TRUE;
} /* end if */
- } /* end for */
/* Update dimension size(s) */
if(ret_value)
@@ -2018,7 +1905,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_set_extent() */
-
+
/*-------------------------------------------------------------------------
* Function: H5S_has_extent
*
@@ -2034,7 +1921,7 @@ done:
*
*-------------------------------------------------------------------------
*/
-hbool_t
+H5_ATTR_PURE hbool_t
H5S_has_extent(const H5S_t *ds)
{
hbool_t ret_value = FALSE; /* Return value */
@@ -2051,7 +1938,7 @@ H5S_has_extent(const H5S_t *ds)
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_has_extent() */
-
+
/*-------------------------------------------------------------------------
* Function: H5S_set_extent_real
*
@@ -2098,26 +1985,25 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_set_extent_real() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5Sextent_equal
+ * Function: H5Sextent_equal
*
- * Purpose: Determines if two dataspace extents are equal.
+ * Purpose: Determines if two dataspace extents are equal.
*
- * Return: Success: TRUE if equal, FALSE if unequal
+ * Return: Success: TRUE if equal, FALSE if unequal
+ * Failure: Negative
*
- * Failure: Negative
- *
- * Programmer: Quincey Koziol
- * Monday, October 24, 2005
+ * Programmer: Quincey Koziol
+ * Monday, October 24, 2005
*
*-------------------------------------------------------------------------
*/
htri_t
H5Sextent_equal(hid_t space1_id, hid_t space2_id)
{
- const H5S_t *ds1, *ds2; /* Dataspaces to compare */
- htri_t ret_value;
+ const H5S_t *ds1, *ds2; /* Dataspaces to compare */
+ htri_t ret_value; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE2("t", "ii", space1_id, space2_id);
@@ -2125,17 +2011,17 @@ H5Sextent_equal(hid_t space1_id, hid_t space2_id)
/* check args */
if(NULL == (ds1 = (const H5S_t *)H5I_object_verify(space1_id, H5I_DATASPACE)) ||
NULL == (ds2 = (const H5S_t *)H5I_object_verify(space2_id, H5I_DATASPACE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
/* Check dataspaces for extent's equality */
if((ret_value = H5S_extent_equal(ds1, ds2)) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOMPARE, FAIL, "dataspace comparison failed")
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOMPARE, FAIL, "dataspace comparison failed")
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Sextent_equal() */
-
+
/*--------------------------------------------------------------------------
NAME
H5S_extent_equal
@@ -2143,13 +2029,13 @@ done:
Check if two dataspaces have equal extents
USAGE
htri_t H5S_extent_equal(ds1, ds2)
- H5S_t *ds1, *ds2; IN: Dataspace objects to compare
+ H5S_t *ds1, *ds2; IN: Dataspace objects to compare
RETURNS
TRUE if equal, FALSE if unequal on succeess/Negative on failure
DESCRIPTION
- Compare two dataspaces if their extents are identical.
+ Compare two dataspaces if their extents are identical.
--------------------------------------------------------------------------*/
-htri_t
+H5_ATTR_PURE htri_t
H5S_extent_equal(const H5S_t *ds1, const H5S_t *ds2)
{
unsigned u; /* Local index variable */
@@ -2196,21 +2082,21 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_extent_equal() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5S_extent_nelem
+ * Function: H5S_extent_nelem
*
- * Purpose: Determines how many elements a dataset extent describes.
+ * Purpose: Determines how many elements a dataset extent describes.
*
- * Return: Success: Number of data points in the dataset extent.
- * Failure: negative
+ * Return: Success: Number of data points in the dataset extent.
+ * Failure: negative
*
- * Programmer: Quincey Koziol
- * Thursday, November 30, 2006
+ * Programmer: Quincey Koziol
+ * Thursday, November 30, 2006
*
*-------------------------------------------------------------------------
*/
-hsize_t
+H5_ATTR_PURE hsize_t
H5S_extent_nelem(const H5S_extent_t *ext)
{
FUNC_ENTER_NOAPI_NOINIT_NOERR
@@ -2222,7 +2108,7 @@ H5S_extent_nelem(const H5S_extent_t *ext)
FUNC_LEAVE_NOAPI(ext->nelem)
} /* end H5S_extent_nelem() */
-
+
/*-------------------------------------------------------------------------
* Function: H5S_set_version
*
@@ -2258,6 +2144,5 @@ H5S_set_version(H5F_t *f, H5S_t *ds)
done:
FUNC_LEAVE_NOAPI(ret_value)
-
} /* end H5S_set_version() */
diff --git a/src/H5SL.c b/src/H5SL.c
index c0934ca..5f00fb8 100644
--- a/src/H5SL.c
+++ b/src/H5SL.c
@@ -240,7 +240,7 @@
/* Allocate space for new forward pointers */ \
if(NULL == (_tmp = (H5SL_node_t **)H5FL_FAC_MALLOC(H5SL_fac_g[X->log_nalloc]))) \
HGOTO_ERROR(H5E_SLIST, H5E_CANTALLOC, ERR, "memory allocation failed") \
- HDmemcpy((void *)_tmp, (const void *)X->forward, (LVL + 1) * sizeof(H5SL_node_t *)); \
+ H5MM_memcpy((void *)_tmp, (const void *)X->forward, (LVL + 1) * sizeof(H5SL_node_t *)); \
X->forward = (H5SL_node_t **)H5FL_FAC_FREE(H5SL_fac_g[X->log_nalloc-1], (void *)X->forward); \
X->forward = _tmp; \
} /* end if */ \
@@ -262,7 +262,7 @@
/* Allocate space for new forward pointers */ \
if(NULL == (_tmp = (H5SL_node_t **)H5FL_FAC_MALLOC(H5SL_fac_g[X->log_nalloc]))) \
HGOTO_ERROR(H5E_SLIST, H5E_NOSPACE, NULL, "memory allocation failed") \
- HDmemcpy((void *)_tmp, (const void *)X->forward, (LVL) * sizeof(H5SL_node_t *)); \
+ H5MM_memcpy((void *)_tmp, (const void *)X->forward, (LVL) * sizeof(H5SL_node_t *)); \
X->forward = (H5SL_node_t **)H5FL_FAC_FREE(H5SL_fac_g[X->log_nalloc+1], (void *)X->forward); \
X->forward = _tmp; \
} /* end if */ \
diff --git a/src/H5SM.c b/src/H5SM.c
index 0fa3489..290e575 100644
--- a/src/H5SM.c
+++ b/src/H5SM.c
@@ -274,6 +274,7 @@ H5SM__type_to_flag(unsigned type_id, unsigned *type_flag)
case H5O_FILL_ID:
type_id = H5O_FILL_NEW_ID;
/* Fall through... */
+ H5_ATTR_FALLTHROUGH
case H5O_SDSPACE_ID:
case H5O_DTYPE_ID:
@@ -2318,7 +2319,7 @@ H5SM__read_iter_op(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/, unsigned sequence,
HGOTO_ERROR(H5E_SOHM, H5E_NOSPACE, H5_ITER_ERROR, "memory allocation failed")
/* Copy the encoded message into the buffer to return */
- HDmemcpy(udata->encoding_buf, mesg->raw, udata->buf_size);
+ H5MM_memcpy(udata->encoding_buf, mesg->raw, udata->buf_size);
/* Found the message we were looking for */
ret_value = H5_ITER_STOP;
@@ -2356,7 +2357,7 @@ H5SM__read_mesg_fh_cb(const void *obj, size_t obj_len, void *_udata)
HGOTO_ERROR(H5E_SOHM, H5E_NOSPACE, FAIL, "memory allocation failed")
/* Copy the message from the heap */
- HDmemcpy(udata->encoding_buf, obj, obj_len);
+ H5MM_memcpy(udata->encoding_buf, obj, obj_len);
udata->buf_size = obj_len;
done:
diff --git a/src/H5SMbtree2.c b/src/H5SMbtree2.c
index f0c4963..7f6c804 100644
--- a/src/H5SMbtree2.c
+++ b/src/H5SMbtree2.c
@@ -24,6 +24,7 @@
/***********/
#include "H5private.h" /* Generic Functions */
#include "H5Eprivate.h" /* Error handling */
+#include "H5MMprivate.h" /* Memory management */
#include "H5Opkg.h" /* Object Headers */
#include "H5SMpkg.h" /* Shared object header messages */
@@ -248,7 +249,7 @@ H5SM_bt2_convert_to_list_op(const void * record, void *op_data)
/* Insert this message at the end of the list */
HDassert(list->messages[mesg_idx].location == H5SM_NO_LOC);
HDassert(message->location != H5SM_NO_LOC);
- HDmemcpy(&(list->messages[mesg_idx]), message, sizeof(H5SM_sohm_t));
+ H5MM_memcpy(&(list->messages[mesg_idx]), message, sizeof(H5SM_sohm_t));
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5SM_bt2_convert_to_list_op() */
diff --git a/src/H5SMcache.c b/src/H5SMcache.c
index f0b469a..49ce2b4 100644
--- a/src/H5SMcache.c
+++ b/src/H5SMcache.c
@@ -388,7 +388,7 @@ H5SM__cache_table_serialize(const H5F_t *f, void *_image, size_t len,
HDassert(H5F_SOHM_VERS(f) == HDF5_SHAREDHEADER_VERSION);
/* Encode magic number */
- HDmemcpy(image, H5SM_TABLE_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ H5MM_memcpy(image, H5SM_TABLE_MAGIC, (size_t)H5_SIZEOF_MAGIC);
image += H5_SIZEOF_MAGIC;
/* Encode each index header */
@@ -710,7 +710,7 @@ H5SM__cache_list_serialize(const H5F_t *f, void *_image, size_t len,
HDassert(list->header->list_size == len);
/* Encode magic number */
- HDmemcpy(image, H5SM_LIST_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ H5MM_memcpy(image, H5SM_LIST_MAGIC, (size_t)H5_SIZEOF_MAGIC);
image += H5_SIZEOF_MAGIC;
/* serialize messages from the messages array */
diff --git a/src/H5SMmessage.c b/src/H5SMmessage.c
index ad84b24..0cca6bb 100644
--- a/src/H5SMmessage.c
+++ b/src/H5SMmessage.c
@@ -24,6 +24,7 @@
/***********/
#include "H5private.h" /* Generic Functions */
#include "H5Eprivate.h" /* Error handling */
+#include "H5MMprivate.h" /* Memory management */
#include "H5Opkg.h" /* Object Headers */
#include "H5SMpkg.h" /* Shared object header messages */
@@ -302,7 +303,7 @@ H5SM__message_encode(uint8_t *raw, const void *_nrecord, void *_ctx)
if(message->location == H5SM_IN_HEAP) {
UINT32ENCODE(raw, message->u.heap_loc.ref_count);
- HDmemcpy(raw, message->u.heap_loc.fheap_id.id, (size_t)H5O_FHEAP_ID_LEN);
+ H5MM_memcpy(raw, message->u.heap_loc.fheap_id.id, (size_t)H5O_FHEAP_ID_LEN);
} /* end if */
else {
HDassert(message->location == H5SM_IN_OH);
@@ -343,7 +344,7 @@ H5SM__message_decode(const uint8_t *raw, void *_nrecord, void *_ctx)
if(message->location == H5SM_IN_HEAP) {
UINT32DECODE(raw, message->u.heap_loc.ref_count);
- HDmemcpy(message->u.heap_loc.fheap_id.id, raw, (size_t)H5O_FHEAP_ID_LEN);
+ H5MM_memcpy(message->u.heap_loc.fheap_id.id, raw, (size_t)H5O_FHEAP_ID_LEN);
} /* end if */
else {
HDassert(message->location == H5SM_IN_OH);
diff --git a/src/H5ST.c b/src/H5ST.c
index dd5b63c..3a1020b 100644
--- a/src/H5ST.c
+++ b/src/H5ST.c
@@ -743,19 +743,19 @@ H5ST__dump_internal(H5ST_ptr_t p)
FUNC_ENTER_STATIC_NOERR
if(p) {
- printf("p=%p\n", (void *)p);
- printf("\tp->up=%p\n", (void *)p->up);
- printf("\tp->parent=%p\n", (void *)p->parent);
- printf("\tp->lokid=%p\n", (void *)p->lokid);
- printf("\tp->hikid=%p\n", (void *)p->hikid);
- printf("\tp->eqkid=%p\n", (void *)p->eqkid);
- printf("\tp->splitchar=%c\n", p->splitchar);
+ HDprintf("p=%p\n", (void *)p);
+ HDprintf("\tp->up=%p\n", (void *)p->up);
+ HDprintf("\tp->parent=%p\n", (void *)p->parent);
+ HDprintf("\tp->lokid=%p\n", (void *)p->lokid);
+ HDprintf("\tp->hikid=%p\n", (void *)p->hikid);
+ HDprintf("\tp->eqkid=%p\n", (void *)p->eqkid);
+ HDprintf("\tp->splitchar=%c\n", p->splitchar);
H5ST__dump_internal(p->lokid);
if(p->splitchar)
H5ST__dump_internal(p->eqkid);
else
- printf("%s\n", (char *)p->eqkid);
+ HDprintf("%s\n", (char *)p->eqkid);
H5ST__dump_internal(p->hikid);
} /* end if */
diff --git a/src/H5Sall.c b/src/H5Sall.c
index 3b77b98..9d0a65a 100644
--- a/src/H5Sall.c
+++ b/src/H5Sall.c
@@ -18,38 +18,57 @@
* Purpose: "All" selection dataspace I/O functions.
*/
+/****************/
+/* Module Setup */
+/****************/
+
#include "H5Smodule.h" /* This source code file is part of the H5S module */
-#include "H5private.h" /* Generic Functions */
-#include "H5Eprivate.h" /* Error handling */
-#include "H5Iprivate.h" /* ID Functions */
-#include "H5Spkg.h" /* Dataspace functions */
-#include "H5VMprivate.h" /* Vector functions */
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Iprivate.h" /* ID Functions */
+#include "H5Spkg.h" /* Dataspace functions */
+#include "H5VMprivate.h" /* Vector functions */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
-/* Static function prototypes */
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
/* Selection callbacks */
static herr_t H5S__all_copy(H5S_t *dst, const H5S_t *src, hbool_t share_selection);
-static herr_t H5S__all_get_seq_list(const H5S_t *space, unsigned flags,
- H5S_sel_iter_t *iter, size_t maxseq, size_t maxbytes,
- size_t *nseq, size_t *nbytes, hsize_t *off, size_t *len);
static herr_t H5S__all_release(H5S_t *space);
static htri_t H5S__all_is_valid(const H5S_t *space);
static hssize_t H5S__all_serial_size(const H5S_t *space);
static herr_t H5S__all_serialize(const H5S_t *space, uint8_t **p);
-static herr_t H5S__all_deserialize(H5S_t *space, uint32_t version, uint8_t flags,
- const uint8_t **p);
+static herr_t H5S__all_deserialize(H5S_t **space, const uint8_t **p);
static herr_t H5S__all_bounds(const H5S_t *space, hsize_t *start, hsize_t *end);
static herr_t H5S__all_offset(const H5S_t *space, hsize_t *off);
static int H5S__all_unlim_dim(const H5S_t *space);
static htri_t H5S__all_is_contiguous(const H5S_t *space);
static htri_t H5S__all_is_single(const H5S_t *space);
static htri_t H5S__all_is_regular(const H5S_t *space);
+static htri_t H5S__all_shape_same(const H5S_t *space1, const H5S_t *space2);
+static htri_t H5S__all_intersect_block(const H5S_t *space, const hsize_t *start,
+ const hsize_t *end);
static herr_t H5S__all_adjust_u(H5S_t *space, const hsize_t *offset);
static herr_t H5S__all_project_scalar(const H5S_t *space, hsize_t *offset);
static herr_t H5S__all_project_simple(const H5S_t *space, H5S_t *new_space, hsize_t *offset);
-static herr_t H5S__all_iter_init(H5S_sel_iter_t *iter, const H5S_t *space);
+static herr_t H5S__all_iter_init(const H5S_t *space, H5S_sel_iter_t *iter);
/* Selection iteration callbacks */
static herr_t H5S__all_iter_coords(const H5S_sel_iter_t *iter, hsize_t *coords);
@@ -58,15 +77,26 @@ static hsize_t H5S__all_iter_nelmts(const H5S_sel_iter_t *iter);
static htri_t H5S__all_iter_has_next_block(const H5S_sel_iter_t *iter);
static herr_t H5S__all_iter_next(H5S_sel_iter_t *sel_iter, size_t nelem);
static herr_t H5S__all_iter_next_block(H5S_sel_iter_t *sel_iter);
+static herr_t H5S__all_iter_get_seq_list(H5S_sel_iter_t *iter, size_t maxseq,
+ size_t maxbytes, size_t *nseq, size_t *nbytes, hsize_t *off, size_t *len);
static herr_t H5S__all_iter_release(H5S_sel_iter_t *sel_iter);
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
/* Selection properties for "all" selections */
const H5S_select_class_t H5S_sel_all[1] = {{
H5S_SEL_ALL,
/* Methods on selection */
H5S__all_copy,
- H5S__all_get_seq_list,
H5S__all_release,
H5S__all_is_valid,
H5S__all_serial_size,
@@ -79,12 +109,19 @@ const H5S_select_class_t H5S_sel_all[1] = {{
H5S__all_is_contiguous,
H5S__all_is_single,
H5S__all_is_regular,
+ H5S__all_shape_same,
+ H5S__all_intersect_block,
H5S__all_adjust_u,
H5S__all_project_scalar,
H5S__all_project_simple,
H5S__all_iter_init,
}};
+
+/*******************/
+/* Local Variables */
+/*******************/
+
/* Iteration properties for "all" selections */
static const H5S_sel_iter_class_t H5S_sel_iter_all[1] = {{
H5S_SEL_ALL,
@@ -96,16 +133,18 @@ static const H5S_sel_iter_class_t H5S_sel_iter_all[1] = {{
H5S__all_iter_has_next_block,
H5S__all_iter_next,
H5S__all_iter_next_block,
+ H5S__all_iter_get_seq_list,
H5S__all_iter_release,
}};
+
/*-------------------------------------------------------------------------
* Function: H5S__all_iter_init
*
* Purpose: Initializes iteration information for "all" selection.
*
- * Return: non-negative on success, negative on failure.
+ * Return: Non-negative on success, negative on failure.
*
* Programmer: Quincey Koziol
* Tuesday, June 16, 1998
@@ -113,7 +152,7 @@ static const H5S_sel_iter_class_t H5S_sel_iter_all[1] = {{
*-------------------------------------------------------------------------
*/
static herr_t
-H5S__all_iter_init(H5S_sel_iter_t *iter, const H5S_t *space)
+H5S__all_iter_init(const H5S_t H5_ATTR_UNUSED *space, H5S_sel_iter_t *iter)
{
FUNC_ENTER_STATIC_NOERR
@@ -121,9 +160,6 @@ H5S__all_iter_init(H5S_sel_iter_t *iter, const H5S_t *space)
HDassert(space && H5S_SEL_ALL == H5S_GET_SELECT_TYPE(space));
HDassert(iter);
- /* Initialize the number of elements to iterate over */
- iter->elmt_left = H5S_GET_SELECT_NPOINTS(space);
-
/* Start at the upper left location */
iter->u.all.elmt_offset = 0;
iter->u.all.byte_offset = 0;
@@ -132,7 +168,7 @@ H5S__all_iter_init(H5S_sel_iter_t *iter, const H5S_t *space)
iter->type = H5S_sel_iter_all;
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5S__all_iter_init() */
+} /* end H5S__all_iter_init() */
/*-------------------------------------------------------------------------
@@ -141,7 +177,7 @@ H5S__all_iter_init(H5S_sel_iter_t *iter, const H5S_t *space)
* Purpose: Retrieve the current coordinates of iterator for current
* selection
*
- * Return: non-negative on success, negative on failure
+ * Return: Non-negative on success, negative on failure
*
* Programmer: Quincey Koziol
* Tuesday, April 22, 2003
@@ -165,7 +201,7 @@ H5S__all_iter_coords(const H5S_sel_iter_t *iter, hsize_t *coords)
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S__all_iter_coords() */
+} /* end H5S__all_iter_coords() */
/*-------------------------------------------------------------------------
@@ -174,7 +210,7 @@ done:
* Purpose: Retrieve the current block of iterator for current
* selection
*
- * Return: non-negative on success, negative on failure
+ * Return: Non-negative on success, negative on failure
*
* Programmer: Quincey Koziol
* Monday, June 2, 2003
@@ -204,7 +240,7 @@ H5S__all_iter_block(const H5S_sel_iter_t *iter, hsize_t *start, hsize_t *end)
} /* end for */
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5S__all_iter_block() */
+} /* end H5S__all_iter_block() */
/*-------------------------------------------------------------------------
@@ -212,7 +248,7 @@ H5S__all_iter_block(const H5S_sel_iter_t *iter, hsize_t *start, hsize_t *end)
*
* Purpose: Return number of elements left to process in iterator
*
- * Return: non-negative number of elements on success, zero on failure
+ * Return: Non-negative number of elements on success, zero on failure
*
* Programmer: Quincey Koziol
* Tuesday, June 16, 1998
@@ -228,7 +264,7 @@ H5S__all_iter_nelmts(const H5S_sel_iter_t *iter)
HDassert(iter);
FUNC_LEAVE_NOAPI(iter->elmt_left)
-} /* H5S__all_iter_nelmts() */
+} /* end H5S__all_iter_nelmts() */
/*--------------------------------------------------------------------------
@@ -257,7 +293,7 @@ H5S__all_iter_has_next_block(const H5S_sel_iter_t H5_ATTR_UNUSED *iter)
HDassert(iter);
FUNC_LEAVE_NOAPI(FALSE)
-} /* H5S__all_iter_has_next_block() */
+} /* end H5S__all_iter_has_next_block() */
/*--------------------------------------------------------------------------
@@ -292,7 +328,7 @@ H5S__all_iter_next(H5S_sel_iter_t *iter, size_t nelem)
iter->u.all.byte_offset += (nelem * iter->elmt_size);
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5S__all_iter_next() */
+} /* end H5S__all_iter_next() */
/*--------------------------------------------------------------------------
@@ -321,7 +357,77 @@ H5S__all_iter_next_block(H5S_sel_iter_t H5_ATTR_UNUSED *iter)
HDassert(iter);
FUNC_LEAVE_NOAPI(FAIL)
-} /* H5S__all_iter_next_block() */
+} /* end H5S__all_iter_next_block() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S__all_iter_get_seq_list
+ PURPOSE
+ Create a list of offsets & lengths for a selection
+ USAGE
+ herr_t H5S__all_iter_get_seq_list(iter,maxseq,maxelem,nseq,nelem,off,len)
+ H5S_sel_iter_t *iter; IN/OUT: Selection iterator describing last
+ position of interest in selection.
+ size_t maxseq; IN: Maximum number of sequences to generate
+ size_t maxelem; IN: Maximum number of elements to include in the
+ generated sequences
+ size_t *nseq; OUT: Actual number of sequences generated
+ size_t *nelem; OUT: Actual number of elements in sequences generated
+ hsize_t *off; OUT: Array of offsets
+ size_t *len; OUT: Array of lengths
+ RETURNS
+ Non-negative on success/Negative on failure.
+ DESCRIPTION
+ Use the selection in the dataspace to generate a list of byte offsets and
+ lengths for the region(s) selected. Start/Restart from the position in the
+ ITER parameter. The number of sequences generated is limited by the MAXSEQ
+ parameter and the number of sequences actually generated is stored in the
+ NSEQ parameter.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static herr_t
+H5S__all_iter_get_seq_list(H5S_sel_iter_t *iter, size_t H5_ATTR_UNUSED maxseq,
+ size_t maxelem, size_t *nseq, size_t *nelem, hsize_t *off, size_t *len)
+{
+ size_t elem_used; /* The number of elements used */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Check args */
+ HDassert(iter);
+ HDassert(maxseq > 0);
+ HDassert(maxelem > 0);
+ HDassert(nseq);
+ HDassert(nelem);
+ HDassert(off);
+ HDassert(len);
+
+ /* Determine the actual number of elements to use */
+ H5_CHECK_OVERFLOW(iter->elmt_left, hsize_t, size_t);
+ elem_used = MIN(maxelem, (size_t)iter->elmt_left);
+ HDassert(elem_used > 0);
+
+ /* Compute the offset in the dataset */
+ off[0] = iter->u.all.byte_offset;
+ len[0] = elem_used * iter->elmt_size;
+
+ /* Should only need one sequence for 'all' selections */
+ *nseq = 1;
+
+ /* Set the number of elements used */
+ *nelem = elem_used;
+
+ /* Update the iterator */
+ iter->elmt_left -= elem_used;
+ iter->u.all.elmt_offset += elem_used;
+ iter->u.all.byte_offset += len[0];
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5S__all_iter_get_seq_list() */
/*--------------------------------------------------------------------------
@@ -350,7 +456,7 @@ H5S__all_iter_release(H5S_sel_iter_t H5_ATTR_UNUSED * iter)
HDassert(iter);
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5S__all_iter_release() */
+} /* end H5S__all_iter_release() */
/*--------------------------------------------------------------------------
@@ -382,7 +488,7 @@ H5S__all_release(H5S_t *space)
space->select.num_elem = 0;
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5S__all_release() */
+} /* end H5S__all_release() */
/*--------------------------------------------------------------------------
@@ -391,9 +497,10 @@ H5S__all_release(H5S_t *space)
PURPOSE
Copy a selection from one dataspace to another
USAGE
- herr_t H5S__all_copy(dst, src)
+ herr_t H5S__all_copy(dst, src, share_selection)
H5S_t *dst; OUT: Pointer to the destination dataspace
H5S_t *src; IN: Pointer to the source dataspace
+ hbool_t; IN: Whether to share the selection between the dataspaces
RETURNS
Non-negative on success/Negative on failure
DESCRIPTION
@@ -519,7 +626,7 @@ H5S__all_serialize(const H5S_t *space, uint8_t **p)
/* Store the preamble information */
UINT32ENCODE(pp, (uint32_t)H5S_GET_SELECT_TYPE(space)); /* Store the type of selection */
- UINT32ENCODE(pp, (uint32_t)1); /* Store the version number */
+ UINT32ENCODE(pp, (uint32_t)H5S_ALL_VERSION_1); /* Store the version number */
UINT32ENCODE(pp, (uint32_t)0); /* Store the un-used padding */
UINT32ENCODE(pp, (uint32_t)0); /* Store the additional information length */
@@ -527,7 +634,7 @@ H5S__all_serialize(const H5S_t *space, uint8_t **p)
*p = pp;
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5S__all_serialize() */
+} /* end H5S__all_serialize() */
/*--------------------------------------------------------------------------
@@ -537,10 +644,8 @@ H5S__all_serialize(const H5S_t *space, uint8_t **p)
Deserialize the current selection from a user-provided buffer.
USAGE
herr_t H5S_all_deserialize(space, p)
- H5S_t *space; IN/OUT: Dataspace pointer to place
+ H5S_t **space; IN/OUT: Dataspace pointer to place
selection into
- uint32_t version IN: Selection version
- uint8_t flags IN: Selection flags
uint8 **p; OUT: Pointer to buffer holding serialized
selection. Will be advanced to end of
serialized selection.
@@ -555,24 +660,53 @@ H5S__all_serialize(const H5S_t *space, uint8_t **p)
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S__all_deserialize(H5S_t *space, uint32_t H5_ATTR_UNUSED version, uint8_t H5_ATTR_UNUSED flags,
- const uint8_t H5_ATTR_UNUSED **p)
+H5S__all_deserialize(H5S_t **space, const uint8_t **p)
{
+ uint32_t version; /* Version number */
+ H5S_t *tmp_space = NULL; /* Pointer to actual dataspace to use,
+ either *space or a newly allocated one */
herr_t ret_value = SUCCEED; /* return value */
FUNC_ENTER_STATIC
- HDassert(space);
HDassert(p);
HDassert(*p);
+ /* As part of the efforts to push all selection-type specific coding
+ to the callbacks, the coding for the allocation of a null dataspace
+ is moved from H5S_select_deserialize() in H5Sselect.c.
+ This is needed for decoding virtual layout in H5O__layout_decode() */
+
+ /* Allocate space if not provided */
+ if(!*space) {
+ if(NULL == (tmp_space = H5S_create(H5S_SIMPLE)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't create dataspace")
+ } /* end if */
+ else
+ tmp_space = *space;
+
+ /* Decode version */
+ UINT32DECODE(*p, version);
+
+ /* Skip over the remainder of the header */
+ *p += 8;
+
/* Change to "all" selection */
- if(H5S_select_all(space, TRUE) < 0)
+ if(H5S_select_all(tmp_space, TRUE) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection")
+ /* Return space to the caller if allocated */
+ if(!*space)
+ *space = tmp_space;
+
done:
+ /* Free temporary space if not passed to caller (only happens on error) */
+ if(!*space && tmp_space)
+ if(H5S_close(tmp_space) < 0)
+ HDONE_ERROR(H5E_DATASPACE, H5E_CANTFREE, FAIL, "can't close dataspace")
+
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S__all_deserialize() */
+} /* end H5S__all_deserialize() */
/*--------------------------------------------------------------------------
@@ -622,7 +756,7 @@ H5S__all_bounds(const H5S_t *space, hsize_t *start, hsize_t *end)
} /* end for */
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5S__all_bounds() */
+} /* end H5S__all_bounds() */
/*--------------------------------------------------------------------------
@@ -657,7 +791,7 @@ H5S__all_offset(const H5S_t H5_ATTR_UNUSED *space, hsize_t *offset)
*offset = 0;
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5S__all_offset() */
+} /* end H5S__all_offset() */
/*--------------------------------------------------------------------------
@@ -716,7 +850,7 @@ H5S__all_is_contiguous(const H5S_t H5_ATTR_UNUSED *space)
HDassert(space);
FUNC_LEAVE_NOAPI(TRUE)
-} /* H5S__all_is_contiguous() */
+} /* end H5S__all_is_contiguous() */
/*--------------------------------------------------------------------------
@@ -745,7 +879,7 @@ H5S__all_is_single(const H5S_t H5_ATTR_UNUSED *space)
HDassert(space);
FUNC_LEAVE_NOAPI(TRUE)
-} /* H5S__all_is_single() */
+} /* end H5S__all_is_single() */
/*--------------------------------------------------------------------------
@@ -776,7 +910,106 @@ H5S__all_is_regular(const H5S_t H5_ATTR_UNUSED *space)
HDassert(space);
FUNC_LEAVE_NOAPI(TRUE)
-} /* H5S__all_is_regular() */
+} /* end H5S__all_is_regular() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S__all_shape_same
+ PURPOSE
+ Check if a two "all" selections are the same shape
+ USAGE
+ htri_t H5S__all_shape_same(space1, space2)
+ const H5S_t *space1; IN: First dataspace to check
+ const H5S_t *space2; IN: Second dataspace to check
+ RETURNS
+ TRUE / FALSE / FAIL
+ DESCRIPTION
+ Checks to see if the current selection in each dataspace are the same
+ shape.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static htri_t
+H5S__all_shape_same(const H5S_t *space1, const H5S_t *space2)
+{
+ int space1_dim; /* Current dimension in first dataspace */
+ int space2_dim; /* Current dimension in second dataspace */
+ htri_t ret_value = TRUE; /* Return value */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Check args */
+ HDassert(space1);
+ HDassert(space2);
+
+ /* Initialize dataspace dims */
+ space1_dim = (int)space1->extent.rank - 1;
+ space2_dim = (int)space2->extent.rank - 1;
+
+ /* Recall that space1_rank >= space2_rank.
+ *
+ * In the following while loop, we test to see if space1 and space2
+ * have identical size in all dimensions they have in common.
+ */
+ while(space2_dim >= 0) {
+ if(space1->extent.size[space1_dim] != space2->extent.size[space2_dim])
+ HGOTO_DONE(FALSE)
+
+ space1_dim--;
+ space2_dim--;
+ } /* end while */
+
+ /* Since we are selecting the entire space, we must also verify that space1
+ * has size 1 in all dimensions that it does not share with space2.
+ */
+ while(space1_dim >= 0) {
+ if(space1->extent.size[space1_dim] != 1)
+ HGOTO_DONE(FALSE)
+
+ space1_dim--;
+ } /* end while */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S__all_shape_same() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S__all_intersect_block
+ PURPOSE
+ Detect intersections of selection with block
+ USAGE
+ htri_t H5S__all_intersect_block(space, start, end)
+ const H5S_t *space; IN: Dataspace with selection to use
+ const hsize_t *start; IN: Starting coordinate for block
+ const hsize_t *end; IN: Ending coordinate for block
+ RETURNS
+ Non-negative TRUE / FALSE on success, negative on failure
+ DESCRIPTION
+ Quickly detect intersections with a block
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+htri_t
+H5S__all_intersect_block(const H5S_t H5_ATTR_UNUSED *space,
+ const hsize_t H5_ATTR_UNUSED *start, const hsize_t H5_ATTR_UNUSED *end)
+{
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Sanity check */
+ HDassert(space);
+ HDassert(H5S_SEL_ALL == H5S_GET_SELECT_TYPE(space));
+ HDassert(start);
+ HDassert(end);
+
+ FUNC_LEAVE_NOAPI(TRUE)
+} /* end H5S__all_intersect_block() */
/*--------------------------------------------------------------------------
@@ -807,7 +1040,7 @@ H5S__all_adjust_u(H5S_t H5_ATTR_UNUSED *space, const hsize_t H5_ATTR_UNUSED *off
HDassert(offset);
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5S__all_adjust_u() */
+} /* end H5S__all_adjust_u() */
/*-------------------------------------------------------------------------
@@ -816,7 +1049,7 @@ H5S__all_adjust_u(H5S_t H5_ATTR_UNUSED *space, const hsize_t H5_ATTR_UNUSED *off
* Purpose: Projects a single element 'all' selection into a scalar
* dataspace
*
- * Return: non-negative on success, negative on failure.
+ * Return: Non-negative on success, negative on failure.
*
* Programmer: Quincey Koziol
* Sunday, July 18, 2010
@@ -836,7 +1069,7 @@ H5S__all_project_scalar(const H5S_t H5_ATTR_UNUSED *space, hsize_t *offset)
*offset = 0;
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5S__all_project_scalar() */
+} /* end H5S__all_project_scalar() */
/*-------------------------------------------------------------------------
@@ -845,7 +1078,7 @@ H5S__all_project_scalar(const H5S_t H5_ATTR_UNUSED *space, hsize_t *offset)
* Purpose: Projects an 'all' selection onto/into a simple dataspace
* of a different rank
*
- * Return: non-negative on success, negative on failure.
+ * Return: Non-negative on success, negative on failure.
*
* Programmer: Quincey Koziol
* Sunday, July 18, 2010
@@ -853,7 +1086,8 @@ H5S__all_project_scalar(const H5S_t H5_ATTR_UNUSED *space, hsize_t *offset)
*-------------------------------------------------------------------------
*/
static herr_t
-H5S__all_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *offset)
+H5S__all_project_simple(const H5S_t H5_ATTR_UNUSED *base_space,
+ H5S_t *new_space, hsize_t H5_ATTR_UNUSED *offset)
{
herr_t ret_value = SUCCEED; /* Return value */
@@ -870,7 +1104,7 @@ H5S__all_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *offs
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S__all_project_simple() */
+} /* end H5S__all_project_simple() */
/*--------------------------------------------------------------------------
@@ -914,7 +1148,7 @@ H5S_select_all(H5S_t *space, hbool_t rel_prev)
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_select_all() */
+} /* end H5S_select_all() */
/*--------------------------------------------------------------------------
@@ -953,79 +1187,5 @@ H5Sselect_all(hid_t spaceid)
done:
FUNC_LEAVE_API(ret_value)
-} /* H5Sselect_all() */
-
-
-/*--------------------------------------------------------------------------
- NAME
- H5S__all_get_seq_list
- PURPOSE
- Create a list of offsets & lengths for a selection
- USAGE
- herr_t H5S__all_get_seq_list(space,flags,iter,maxseq,maxelem,nseq,nelem,off,len)
- H5S_t *space; IN: Dataspace containing selection to use.
- unsigned flags; IN: Flags for extra information about operation
- H5S_sel_iter_t *iter; IN/OUT: Selection iterator describing last
- position of interest in selection.
- size_t maxseq; IN: Maximum number of sequences to generate
- size_t maxelem; IN: Maximum number of elements to include in the
- generated sequences
- size_t *nseq; OUT: Actual number of sequences generated
- size_t *nelem; OUT: Actual number of elements in sequences generated
- hsize_t *off; OUT: Array of offsets
- size_t *len; OUT: Array of lengths
- RETURNS
- Non-negative on success/Negative on failure.
- DESCRIPTION
- Use the selection in the dataspace to generate a list of byte offsets and
- lengths for the region(s) selected. Start/Restart from the position in the
- ITER parameter. The number of sequences generated is limited by the MAXSEQ
- parameter and the number of sequences actually generated is stored in the
- NSEQ parameter.
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
-static herr_t
-H5S__all_get_seq_list(const H5S_t H5_ATTR_UNUSED *space, unsigned H5_ATTR_UNUSED flags, H5S_sel_iter_t *iter,
- size_t H5_ATTR_UNUSED maxseq, size_t maxelem, size_t *nseq, size_t *nelem,
- hsize_t *off, size_t *len)
-{
- size_t elem_used; /* The number of elements used */
-
- FUNC_ENTER_STATIC_NOERR
-
- /* Check args */
- HDassert(space);
- HDassert(iter);
- HDassert(maxseq > 0);
- HDassert(maxelem > 0);
- HDassert(nseq);
- HDassert(nelem);
- HDassert(off);
- HDassert(len);
-
- /* Determine the actual number of elements to use */
- H5_CHECK_OVERFLOW(iter->elmt_left, hsize_t, size_t);
- elem_used = MIN(maxelem, (size_t)iter->elmt_left);
- HDassert(elem_used > 0);
-
- /* Compute the offset in the dataset */
- off[0] = iter->u.all.byte_offset;
- len[0] = elem_used * iter->elmt_size;
-
- /* Should only need one sequence for 'all' selections */
- *nseq = 1;
-
- /* Set the number of elements used */
- *nelem = elem_used;
-
- /* Update the iterator */
- iter->elmt_left -= elem_used;
- iter->u.all.elmt_offset += elem_used;
- iter->u.all.byte_offset += len[0];
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5S__all_get_seq_list() */
+} /* end H5Sselect_all() */
diff --git a/src/H5Sdbg.c b/src/H5Sdbg.c
index ebd05ce..8171191 100644
--- a/src/H5Sdbg.c
+++ b/src/H5Sdbg.c
@@ -57,16 +57,16 @@
/********************/
-/*********************/
-/* Package Variables */
-/*********************/
-
-
/*****************************/
/* Library Private Variables */
/*****************************/
+/*********************/
+/* Package Variables */
+/*********************/
+
+
/*******************/
/* Local Variables */
/*******************/
@@ -94,24 +94,24 @@ H5S_debug(H5F_t *f, const void *_mesg, FILE *stream, int indent, int fwidth)
switch(H5S_GET_EXTENT_TYPE(mesg)) {
case H5S_NULL:
- fprintf(stream, "%*s%-*s H5S_NULL\n", indent, "", fwidth,
+ HDfprintf(stream, "%*s%-*s H5S_NULL\n", indent, "", fwidth,
"Space class:");
break;
case H5S_SCALAR:
- fprintf(stream, "%*s%-*s H5S_SCALAR\n", indent, "", fwidth,
+ HDfprintf(stream, "%*s%-*s H5S_SCALAR\n", indent, "", fwidth,
"Space class:");
break;
case H5S_SIMPLE:
- fprintf(stream, "%*s%-*s H5S_SIMPLE\n", indent, "", fwidth,
+ HDfprintf(stream, "%*s%-*s H5S_SIMPLE\n", indent, "", fwidth,
"Space class:");
H5O_debug_id(H5O_SDSPACE_ID, f, &(mesg->extent), stream, indent + 3, MAX(0, fwidth - 3));
break;
case H5S_NO_CLASS:
default:
- fprintf(stream, "%*s%-*s **UNKNOWN-%ld**\n", indent, "", fwidth,
+ HDfprintf(stream, "%*s%-*s **UNKNOWN-%ld**\n", indent, "", fwidth,
"Space class:", (long)(H5S_GET_EXTENT_TYPE(mesg)));
break;
} /* end switch */
diff --git a/src/H5Sdeprec.c b/src/H5Sdeprec.c
new file mode 100644
index 0000000..e4ec1b0
--- /dev/null
+++ b/src/H5Sdeprec.c
@@ -0,0 +1,121 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5Sdeprec.c
+ *
+ * Purpose: Deprecated functions from the H5S interface. These
+ * functions are here for compatibility purposes and may be
+ * removed in the future. Applications should switch to the
+ * newer APIs.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#include "H5Smodule.h" /* This source code file is part of the H5S module */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5CXprivate.h" /* API Contexts */
+#include "H5Spkg.h" /* Dataspaces */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Iprivate.h" /* IDs */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
+#ifndef H5_NO_DEPRECATED_SYMBOLS
+
+/*-------------------------------------------------------------------------
+ * Function: H5Sencode1
+ *
+ * Purpose: Given a dataspace ID, converts the object description
+ * (including selection) into binary in a buffer.
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Raymond Lu
+ * slu@ncsa.uiuc.edu
+ * July 14, 2004
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Sencode1(hid_t obj_id, void *buf, size_t *nalloc)
+{
+ H5S_t *dspace;
+ hid_t temp_fapl_id = H5P_DEFAULT;
+ herr_t ret_value=SUCCEED;
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE3("e", "i*x*z", obj_id, buf, nalloc);
+
+ /* Check argument and retrieve object */
+ if (NULL == (dspace = (H5S_t *)H5I_object_verify(obj_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
+
+ /* Verify access property list and set up collective metadata if appropriate */
+ if(H5CX_set_apl(&temp_fapl_id, H5P_CLS_FACC, H5I_INVALID_HID, TRUE) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info")
+
+ /* Use (earliest, latest) i.e. not latest format */
+ if(H5S_encode(dspace, (unsigned char **)&buf, nalloc)<0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTENCODE, FAIL, "can't encode dataspace")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* H5Sencode1() */
+#endif /* H5_NO_DEPRECATED_SYMBOLS */
+
diff --git a/src/H5Shyper.c b/src/H5Shyper.c
index ed3fa45..9feb8de 100644
--- a/src/H5Shyper.c
+++ b/src/H5Shyper.c
@@ -15,59 +15,156 @@
* Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
* Thursday, June 18, 1998
*
- * Purpose: Hyperslab selection dataspace I/O functions.
+ * Purpose: Hyperslab selection dataspace I/O functions.
*/
-#include "H5Smodule.h" /* This source code file is part of the H5S module */
+/****************/
+/* Module Setup */
+/****************/
+#include "H5Smodule.h" /* This source code file is part of the H5S module */
-#include "H5private.h" /* Generic Functions */
-#include "H5Eprivate.h" /* Error handling */
-#include "H5FLprivate.h" /* Free Lists */
-#include "H5Iprivate.h" /* ID Functions */
-#include "H5Spkg.h" /* Dataspace functions */
-#include "H5VMprivate.h" /* Vector functions */
-/* Local Macros */
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5CXprivate.h" /* API Contexts */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5FLprivate.h" /* Free Lists */
+#include "H5Iprivate.h" /* ID Functions */
+#include "H5MMprivate.h" /* Memory management */
+#include "H5Spkg.h" /* Dataspace functions */
+#include "H5VMprivate.h" /* Vector functions */
-/* Local datatypes */
-/* Static function prototypes */
+/****************/
+/* Local Macros */
+/****************/
+
+/* Flags for which hyperslab fragments to compute */
+#define H5S_HYPER_COMPUTE_B_NOT_A 0x01
+#define H5S_HYPER_COMPUTE_A_AND_B 0x02
+#define H5S_HYPER_COMPUTE_A_NOT_B 0x04
+
+/* Macro to advance a span, possibly recycling it first */
+#define H5S_HYPER_ADVANCE_SPAN(recover, curr_span, next_span) \
+ do { \
+ H5S_hyper_span_t *saved_next_span = (next_span); \
+ \
+ /* Check if the span should be recovered */ \
+ if(recover) { \
+ H5S__hyper_free_span(curr_span); \
+ (recover) = FALSE; \
+ } /* end if */ \
+ \
+ /* Set the current span to saved next span */ \
+ (curr_span) = saved_next_span; \
+ } while(0)
+
+/* Macro to add "skipped" elements to projection during the execution of
+ * H5S__hyper_project_intersect() */
+#define H5S_HYPER_PROJ_INT_ADD_SKIP(UDATA, ADD, ERR) \
+ do { \
+ /* If there are any elements to add, we must add them \
+ * to the projection first before adding skip */ \
+ if((UDATA)->nelem > 0) \
+ if(H5S__hyper_proj_int_build_proj(UDATA) < 0) \
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, ERR, "can't add elements to projected selection") \
+ (UDATA)->skip += (ADD); \
+ } while(0) /* end H5S_HYPER_PROJ_INT_ADD_SKIP() */
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+/* Define alias for hsize_t, for allocating H5S_hyper_span_info_t + bounds objects */
+/* (Makes it easier to understand the alloc / free calls) */
+typedef hsize_t hbounds_t;
+
+/* Struct for holding persistent information during iteration for
+ * H5S__hyper_project_intersect() */
+typedef struct {
+ const H5S_hyper_span_t *ds_span[H5S_MAX_RANK]; /* Array of the current spans in the destination space in each dimension */
+ hsize_t ds_low[H5S_MAX_RANK]; /* Array of current low bounds (of iteration) for each element in ds_span */
+ H5S_hyper_span_info_t *ps_span_info[H5S_MAX_RANK]; /* Array of span info structs for projected space during iteration */
+ uint32_t ps_clean_bitmap; /* Bitmap of whether the nth rank has a clean projected space since the last time it was set to 1 */
+ unsigned ss_rank; /* Rank of source space */
+ unsigned ds_rank; /* Rank of destination space */
+ unsigned depth; /* Current depth of iterator in destination space */
+ hsize_t skip; /* Number of elements to skip in projected space */
+ hsize_t nelem; /* Number of elements to add to projected space (after skip) */
+ uint64_t op_gen; /* Operation generation for counting elements */
+} H5S_hyper_project_intersect_ud_t;
+
+/* Assert that H5S_MAX_RANK is <= 32 so our trick with using a 32 bit bitmap
+ * (ps_clean_bitmap) works. If H5S_MAX_RANK increases either increase the size
+ * of ps_clean_bitmap or change the algorithm to use an array. */
+#if H5S_MAX_RANK > 32
+#error H5S_MAX_RANK too large for ps_clean_bitmap field in H5S_hyper_project_intersect_ud_t struct
+#endif
+
+
+/********************/
+/* Local Prototypes */
+/********************/
static H5S_hyper_span_t *H5S__hyper_new_span(hsize_t low, hsize_t high,
H5S_hyper_span_info_t *down, H5S_hyper_span_t *next);
-static herr_t H5S__hyper_span_precompute(H5S_hyper_span_info_t *spans, size_t elmt_size);
-static void H5S__hyper_span_scratch(H5S_hyper_span_info_t *spans);
-static H5S_hyper_span_info_t *H5S__hyper_copy_span(H5S_hyper_span_info_t *spans);
+static H5S_hyper_span_info_t *H5S__hyper_new_span_info(unsigned rank);
+static H5S_hyper_span_info_t *H5S__hyper_copy_span(H5S_hyper_span_info_t *spans,
+ unsigned rank);
static hbool_t H5S__hyper_cmp_spans(const H5S_hyper_span_info_t *span_info1,
const H5S_hyper_span_info_t *span_info2);
-static herr_t H5S__hyper_free_span_info(H5S_hyper_span_info_t *span_info);
-static herr_t H5S__hyper_free_span(H5S_hyper_span_t *span);
-static hbool_t H5S__hyper_is_valid_helper(const H5S_hyper_span_info_t *spans,
- const hssize_t *offset, const hsize_t *size);
-static herr_t H5S__hyper_recover_span(hbool_t *recover,
- H5S_hyper_span_t **curr_span, H5S_hyper_span_t *next_span);
-static H5S_hyper_span_t *H5S__hyper_coord_to_span(unsigned rank,
- const hsize_t *coords);
-static herr_t H5S__hyper_append_span(H5S_hyper_span_t **prev_span,
- H5S_hyper_span_info_t **span_tree, hsize_t low, hsize_t high,
- H5S_hyper_span_info_t *down, H5S_hyper_span_t *next);
+static void H5S__hyper_free_span_info(H5S_hyper_span_info_t *span_info);
+static void H5S__hyper_free_span(H5S_hyper_span_t *span);
+static herr_t H5S__hyper_span_blocklist(const H5S_hyper_span_info_t *spans,
+ hsize_t start[], hsize_t end[], hsize_t rank, hsize_t *startblock, hsize_t *numblocks,
+ hsize_t **buf);
+static herr_t H5S__get_select_hyper_blocklist(H5S_t *space, hsize_t startblock,
+ hsize_t numblocks, hsize_t *buf);
+static H5S_hyper_span_t *H5S__hyper_coord_to_span(unsigned rank, const hsize_t *coords);
+static herr_t H5S__hyper_append_span(H5S_hyper_span_info_t **span_tree,
+ unsigned ndims, hsize_t low, hsize_t high, H5S_hyper_span_info_t *down);
static herr_t H5S__hyper_clip_spans(H5S_hyper_span_info_t *a_spans,
- H5S_hyper_span_info_t *b_spans, H5S_hyper_span_info_t **a_not_b,
+ H5S_hyper_span_info_t *b_spans, unsigned selector,
+ unsigned ndims, H5S_hyper_span_info_t **a_not_b,
H5S_hyper_span_info_t **a_and_b, H5S_hyper_span_info_t **b_not_a);
-static herr_t H5S__hyper_merge_spans(H5S_t *space,
- H5S_hyper_span_info_t *new_spans, hbool_t can_own);
-static hsize_t H5S__hyper_spans_nelem(const H5S_hyper_span_info_t *spans);
+static herr_t H5S__hyper_merge_spans(H5S_t *space, H5S_hyper_span_info_t *new_spans);
+static hsize_t H5S__hyper_spans_nelem_helper(H5S_hyper_span_info_t *spans,
+ uint64_t op_gen);
+static hsize_t H5S__hyper_spans_nelem(H5S_hyper_span_info_t *spans);
+static herr_t H5S__hyper_add_disjoint_spans(H5S_t *space, H5S_hyper_span_info_t *new_spans);
static H5S_hyper_span_info_t *H5S__hyper_make_spans(unsigned rank,
- const hsize_t *start, const hsize_t *stride, const hsize_t *count,
- const hsize_t *block);
+ const hsize_t *start, const hsize_t *stride,
+ const hsize_t *count, const hsize_t *block);
+static herr_t H5S__hyper_update_diminfo(H5S_t *space, H5S_seloper_t op,
+ const H5S_hyper_dim_t *new_hyper_diminfo);
static herr_t H5S__hyper_generate_spans(H5S_t *space);
+static hbool_t H5S__check_spans_overlap(const H5S_hyper_span_info_t *spans1,
+ const H5S_hyper_span_info_t *spans2);
+static herr_t H5S__fill_in_new_space(H5S_t *space1, H5S_seloper_t op,
+ H5S_hyper_span_info_t *space2_span_lst, hbool_t can_own_span2,
+ hbool_t *span2_owned, hbool_t *updated_spans, H5S_t **result);
static herr_t H5S__generate_hyperslab(H5S_t *space, H5S_seloper_t op,
const hsize_t start[], const hsize_t stride[], const hsize_t count[],
const hsize_t block[]);
-/* Needed for use in hyperslab code (H5Shyper.c) */
-#ifdef NEW_HYPERSLAB_API
-static herr_t H5S_select_select (H5S_t *space1, H5S_seloper_t op, H5S_t *space2);
-#endif /*NEW_HYPERSLAB_API*/
+static herr_t H5S__set_regular_hyperslab(H5S_t *space, const hsize_t start[],
+ const hsize_t *app_stride, const hsize_t app_count[], const hsize_t *app_block,
+ const hsize_t *opt_stride, const hsize_t opt_count[], const hsize_t *opt_block);
+static herr_t H5S__fill_in_select(H5S_t *space1, H5S_seloper_t op, H5S_t *space2,
+ H5S_t **result);
+static H5S_t *H5S__combine_select(H5S_t *space1, H5S_seloper_t op, H5S_t *space2);
+static herr_t H5S__hyper_iter_get_seq_list_gen(H5S_sel_iter_t *iter, size_t maxseq,
+ size_t maxelem, size_t *nseq, size_t *nelem, hsize_t *off, size_t *len);
+static herr_t H5S__hyper_iter_get_seq_list_opt(H5S_sel_iter_t *iter, size_t maxseq,
+ size_t maxelem, size_t *nseq, size_t *nelem, hsize_t *off, size_t *len);
+static herr_t H5S__hyper_iter_get_seq_list_single(H5S_sel_iter_t *iter, size_t maxseq,
+ size_t maxelem, size_t *nseq, size_t *nelem, hsize_t *off, size_t *len);
+static herr_t H5S__hyper_proj_int_build_proj(H5S_hyper_project_intersect_ud_t *udata);
+static herr_t H5S__hyper_proj_int_iterate(const H5S_hyper_span_info_t *ss_span_info,
+ const H5S_hyper_span_info_t *sis_span_info, hsize_t count, unsigned depth,
+ H5S_hyper_project_intersect_ud_t *udata);
static void H5S__hyper_get_clip_diminfo(hsize_t start, hsize_t stride,
hsize_t *count, hsize_t *block, hsize_t clip_size);
static hsize_t H5S__hyper_get_clip_extent_real(const H5S_t *clip_space,
@@ -75,15 +172,12 @@ static hsize_t H5S__hyper_get_clip_extent_real(const H5S_t *clip_space,
/* Selection callbacks */
static herr_t H5S__hyper_copy(H5S_t *dst, const H5S_t *src, hbool_t share_selection);
-static herr_t H5S__hyper_get_seq_list(const H5S_t *space, unsigned flags,
- H5S_sel_iter_t *iter, size_t maxseq, size_t maxbytes,
- size_t *nseq, size_t *nbytes, hsize_t *off, size_t *len);
static herr_t H5S__hyper_release(H5S_t *space);
static htri_t H5S__hyper_is_valid(const H5S_t *space);
+static hsize_t H5S__hyper_span_nblocks(H5S_hyper_span_info_t *spans);
static hssize_t H5S__hyper_serial_size(const H5S_t *space);
static herr_t H5S__hyper_serialize(const H5S_t *space, uint8_t **p);
-static herr_t H5S__hyper_deserialize(H5S_t *space, uint32_t version, uint8_t flags,
- const uint8_t **p);
+static herr_t H5S__hyper_deserialize(H5S_t **space, const uint8_t **p);
static herr_t H5S__hyper_bounds(const H5S_t *space, hsize_t *start, hsize_t *end);
static herr_t H5S__hyper_offset(const H5S_t *space, hsize_t *offset);
static int H5S__hyper_unlim_dim(const H5S_t *space);
@@ -92,10 +186,13 @@ static herr_t H5S__hyper_num_elem_non_unlim(const H5S_t *space,
static htri_t H5S__hyper_is_contiguous(const H5S_t *space);
static htri_t H5S__hyper_is_single(const H5S_t *space);
static htri_t H5S__hyper_is_regular(const H5S_t *space);
+static htri_t H5S__hyper_shape_same(const H5S_t *space1, const H5S_t *space2);
+static htri_t H5S__hyper_intersect_block(const H5S_t *space, const hsize_t *start,
+ const hsize_t *end);
static herr_t H5S__hyper_adjust_u(H5S_t *space, const hsize_t *offset);
static herr_t H5S__hyper_project_scalar(const H5S_t *space, hsize_t *offset);
static herr_t H5S__hyper_project_simple(const H5S_t *space, H5S_t *new_space, hsize_t *offset);
-static herr_t H5S__hyper_iter_init(H5S_sel_iter_t *iter, const H5S_t *space);
+static herr_t H5S__hyper_iter_init(const H5S_t *space, H5S_sel_iter_t *iter);
/* Selection iteration callbacks */
static herr_t H5S__hyper_iter_coords(const H5S_sel_iter_t *iter, hsize_t *coords);
@@ -104,12 +201,19 @@ static hsize_t H5S__hyper_iter_nelmts(const H5S_sel_iter_t *iter);
static htri_t H5S__hyper_iter_has_next_block(const H5S_sel_iter_t *sel_iter);
static herr_t H5S__hyper_iter_next(H5S_sel_iter_t *sel_iter, size_t nelem);
static herr_t H5S__hyper_iter_next_block(H5S_sel_iter_t *sel_iter);
+static herr_t H5S__hyper_iter_get_seq_list(H5S_sel_iter_t *iter, size_t maxseq,
+ size_t maxbytes, size_t *nseq, size_t *nbytes, hsize_t *off, size_t *len);
static herr_t H5S__hyper_iter_release(H5S_sel_iter_t *sel_iter);
-/* Static function for optimizing hyperslab */
-static hbool_t H5S__hyper_rebuild_helper(const H5S_hyper_span_t *span,
- H5S_hyper_dim_t span_slab_info[], unsigned rank);
-static hbool_t H5S__hyper_rebuild(H5S_t *space);
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
/* Selection properties for hyperslab selections */
const H5S_select_class_t H5S_sel_hyper[1] = {{
@@ -117,7 +221,6 @@ const H5S_select_class_t H5S_sel_hyper[1] = {{
/* Methods on selection */
H5S__hyper_copy,
- H5S__hyper_get_seq_list,
H5S__hyper_release,
H5S__hyper_is_valid,
H5S__hyper_serial_size,
@@ -130,12 +233,27 @@ const H5S_select_class_t H5S_sel_hyper[1] = {{
H5S__hyper_is_contiguous,
H5S__hyper_is_single,
H5S__hyper_is_regular,
+ H5S__hyper_shape_same,
+ H5S__hyper_intersect_block,
H5S__hyper_adjust_u,
H5S__hyper_project_scalar,
H5S__hyper_project_simple,
H5S__hyper_iter_init,
}};
+/* Format version bounds for dataspace hyperslab selection */
+const unsigned H5O_sds_hyper_ver_bounds[] = {
+ H5S_HYPER_VERSION_1, /* H5F_LIBVER_EARLIEST */
+ H5S_HYPER_VERSION_1, /* H5F_LIBVER_V18 */
+ H5S_HYPER_VERSION_2, /* H5F_LIBVER_V110 */
+ H5S_HYPER_VERSION_3, /* H5F_LIBVER_V112 */
+ H5S_HYPER_VERSION_3 /* H5F_LIBVER_LATEST */
+};
+
+/*******************/
+/* Local Variables */
+/*******************/
+
/* Iteration properties for hyperslab selections */
static const H5S_sel_iter_class_t H5S_sel_iter_hyper[1] = {{
H5S_SEL_HYPERSLABS,
@@ -147,22 +265,21 @@ static const H5S_sel_iter_class_t H5S_sel_iter_hyper[1] = {{
H5S__hyper_iter_has_next_block,
H5S__hyper_iter_next,
H5S__hyper_iter_next_block,
+ H5S__hyper_iter_get_seq_list,
H5S__hyper_iter_release,
}};
-/* Static variables */
-
/* Arrays for default stride, block, etc. */
-static const hsize_t H5S_hyper_zeros_g[H5O_LAYOUT_NDIMS] = {
+static const hsize_t H5S_hyper_zeros_g[H5S_MAX_RANK] = {
0,0,0,0, 0,0,0,0,
0,0,0,0, 0,0,0,0,
0,0,0,0, 0,0,0,0,
- 0,0,0,0, 0,0,0,0,0};
-static const hsize_t H5S_hyper_ones_g[H5O_LAYOUT_NDIMS] = {
+ 0,0,0,0, 0,0,0,0};
+static const hsize_t H5S_hyper_ones_g[H5S_MAX_RANK] = {
1,1,1,1, 1,1,1,1,
1,1,1,1, 1,1,1,1,
1,1,1,1, 1,1,1,1,
- 1,1,1,1, 1,1,1,1,1};
+ 1,1,1,1, 1,1,1,1};
/* Declare a free list to manage the H5S_hyper_sel_t struct */
H5FL_DEFINE_STATIC(H5S_hyper_sel_t);
@@ -170,12 +287,18 @@ H5FL_DEFINE_STATIC(H5S_hyper_sel_t);
/* Declare a free list to manage the H5S_hyper_span_t struct */
H5FL_DEFINE_STATIC(H5S_hyper_span_t);
-/* Declare a free list to manage the H5S_hyper_span_info_t struct */
-H5FL_DEFINE_STATIC(H5S_hyper_span_info_t);
+/* Declare a free list to manage the H5S_hyper_span_info_t + hsize_t array struct */
+H5FL_BARR_DEFINE_STATIC(H5S_hyper_span_info_t, hbounds_t, H5S_MAX_RANK * 2);
/* Declare extern free list to manage the H5S_sel_iter_t struct */
H5FL_EXTERN(H5S_sel_iter_t);
+/* Current operation generation */
+/* (Start with '1' to avoid clashing with '0' value in newly allocated structs) */
+static uint64_t H5S_hyper_op_gen_g = 1;
+
+
+/* Uncomment this, to provide the debugging routines for printing selection info */
/* #define H5S_HYPER_DEBUG */
#ifdef H5S_HYPER_DEBUG
static herr_t
@@ -184,9 +307,9 @@ H5S__hyper_print_spans_helper(FILE *f, const H5S_hyper_span_t *span, unsigned de
FUNC_ENTER_STATIC_NOERR
while(span) {
- HDfprintf(f,"%s: depth=%u, span=%p, (%Hu, %Hu), nelem=%Hu, pstride=%Hu\n", FUNC, depth, span, span->low, span->high, span->nelem, span->pstride);
- if(span->down && span->down->head) {
- HDfprintf(f,"%s: spans=%p, count=%u, scratch=%p, head=%p\n", FUNC, span->down, span->down->count, span->down->scratch, span->down->head);
+ HDfprintf(f,"%s: %*sdepth=%u, span=%p, (%Hu, %Hu), next=%p\n", FUNC, depth * 2, "", depth, span, span->low, span->high, span->next);
+ if(span->down) {
+ HDfprintf(f,"%s: %*sspans=%p, count=%u, bounds[0]={%Hu, %Hu}, head=%p\n", FUNC, (depth + 1) * 2, "", span->down, span->down->count, span->down->low_bounds[0], span->down->high_bounds[0], span->down->head);
H5S__hyper_print_spans_helper(f, span->down->head, depth + 1);
} /* end if */
span = span->next;
@@ -201,7 +324,7 @@ H5S__hyper_print_spans(FILE *f, const H5S_hyper_span_info_t *span_lst)
FUNC_ENTER_STATIC_NOERR
if(span_lst != NULL) {
- HDfprintf(f, "%s: spans=%p, count=%u, scratch=%p, head=%p\n", FUNC, span_lst, span_lst->count, span_lst->scratch, span_lst->head);
+ HDfprintf(f, "%s: spans=%p, count=%u, bounds[0]={%Hu, %Hu}, head=%p\n", FUNC, span_lst, span_lst->count, span_lst->low_bounds[0], span_lst->high_bounds[0], span_lst->head);
H5S__hyper_print_spans_helper(f, span_lst->head, 0);
} /* end if */
@@ -250,25 +373,194 @@ H5S__hyper_print_diminfo(FILE *f, const H5S_t *space)
{
FUNC_ENTER_STATIC_NOERR
- H5S__hyper_print_diminfo_helper(f, "opt_diminfo", space->extent.rank, space->select.sel_info.hslab->opt_diminfo);
- H5S__hyper_print_diminfo_helper(f, "app_diminfo", space->extent.rank, space->select.sel_info.hslab->app_diminfo);
+ H5S__hyper_print_diminfo_helper(f, "diminfo.opt", space->extent.rank, space->select.sel_info.hslab->diminfo.opt);
+ H5S__hyper_print_diminfo_helper(f, "diminfo.app", space->extent.rank, space->select.sel_info.hslab->diminfo.app);
FUNC_LEAVE_NOAPI(SUCCEED)
}
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S__hyper_print_spans_dfs
+ PURPOSE
+ Output the span elements for one span list in depth-first order
+ USAGE
+ herr_t H5S__hyper_print_spans_dfs(f, span_lst, depth)
+ FILE *f; IN: the file to output
+ const H5S_hyper_span_info_t *span_lst; IN: the span list to output
+ unsigned depth; IN: the level of this span list
+ RETURNS
+ non-negative on success, negative on failure
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static herr_t
+H5S__hyper_print_spans_dfs(FILE *f, const H5S_hyper_span_info_t *span_lst,
+ unsigned depth, unsigned dims)
+{
+ H5S_hyper_span_t *actual_tail = NULL;
+ H5S_hyper_span_t *cur_elem;
+ unsigned num_elems = 0;
+ unsigned u, elem_idx;
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* get the actual tail from head */
+ cur_elem = span_lst->head;
+ HDassert(cur_elem); /* at least 1 element */
+ while(cur_elem) {
+ actual_tail = cur_elem;
+ cur_elem = cur_elem->next;
+ num_elems++;
+ } /* end while */
+
+ for(u = 0; u < depth; u++)
+ HDfprintf(f, "\t");
+ HDfprintf(f, "DIM[%u]: ref_count=%u, #elems=%u, head=%p, tail=%p, actual_tail=%p, matched=%t\n", depth,
+ span_lst->count, num_elems, span_lst->head,
+ span_lst->tail, actual_tail, (span_lst->tail == actual_tail));
+
+ for(u = 0; u < depth; u++)
+ HDfprintf(f, "\t");
+ HDfprintf(f, "low_bounds=[");
+ for(u = 0; u < dims - 1; u++)
+ HDfprintf(f, "%llu,", span_lst->low_bounds[u]);
+ HDfprintf(f, "%llu]\n", span_lst->low_bounds[dims - 1]);
+
+ for(u = 0; u < depth; u++)
+ HDfprintf(f, "\t");
+ HDfprintf(f, "high_bounds=[");
+ for(u = 0; u < dims - 1; u++)
+ HDfprintf(f, "%llu,", span_lst->high_bounds[u]);
+ HDfprintf(f, "%llu]\n", span_lst->high_bounds[dims - 1]);
+
+ cur_elem = span_lst->head;
+ elem_idx = 0;
+ while(cur_elem) {
+ for(u = 0; u < depth; u++)
+ HDfprintf(f, "\t");
+ HDfprintf(f, "ELEM[%u]: ptr=%p, low=%Hu, high=%Hu, down=%p\n",
+ elem_idx++, cur_elem, cur_elem->low, cur_elem->high, cur_elem->down);
+ if(cur_elem->down)
+ H5S__hyper_print_spans_dfs(f, cur_elem->down, depth + 1, dims);
+ cur_elem = cur_elem->next;
+ } /* end while */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5S__hyper_print_spans_dfs() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S__hyper_print_space_dfs
+ PURPOSE
+ Output the span elements for one hyperslab selection space in depth-first order
+ USAGE
+ herr_t H5S__hyper_print_space_dfs(f, space)
+ FILE *f; IN: the file to output
+ const H5S_t *space; IN: the selection space to output
+ RETURNS
+ non-negative on success, negative on failure
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static herr_t
+H5S__hyper_print_space_dfs(FILE *f, const H5S_t *space)
+{
+ const H5S_hyper_sel_t *hslab = space->select.sel_info.hslab;
+ const unsigned dims = space->extent.rank;
+ unsigned u;
+
+ FUNC_ENTER_STATIC_NOERR
+
+ HDassert(hslab);
+
+ HDfprintf(f, "=======================\n");
+ HDfprintf(f, "SPACE: span_lst=%p, #dims=%u, offset_changed=%d\n", hslab->span_lst, dims, space->select.offset_changed);
+
+ HDfprintf(f, " offset=[");
+ for(u = 0; u < dims - 1; u++)
+ HDfprintf(f, "%lld,", space->select.offset[u]);
+ HDfprintf(f, "%lld]\n", space->select.offset[dims - 1]);
+
+ HDfprintf(f, " low_bounds=[");
+ if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) {
+ for(u = 0; u < dims - 1; u++)
+ HDfprintf(f, "%llu,", space->select.sel_info.hslab->diminfo.low_bounds[u]);
+ HDfprintf(f, "%llu]\n", space->select.sel_info.hslab->diminfo.low_bounds[dims - 1]);
+ } /* end if */
+ else {
+ for(u = 0; u < dims - 1; u++)
+ HDfprintf(f, "%llu,", space->select.sel_info.hslab->span_lst->low_bounds[u]);
+ HDfprintf(f, "%llu]\n", space->select.sel_info.hslab->span_lst->low_bounds[dims - 1]);
+ } /* end else */
+
+ HDfprintf(f, " high_bounds=[");
+ if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) {
+ for(u = 0; u < dims - 1; u++)
+ HDfprintf(f, "%llu,", space->select.sel_info.hslab->diminfo.high_bounds[u]);
+ HDfprintf(f, "%llu]\n", space->select.sel_info.hslab->diminfo.high_bounds[dims - 1]);
+ } /* end if */
+ else {
+ for(u = 0; u < dims - 1; u++)
+ HDfprintf(f, "%llu,", space->select.sel_info.hslab->span_lst->high_bounds[u]);
+ HDfprintf(f, "%llu]\n", space->select.sel_info.hslab->span_lst->high_bounds[dims - 1]);
+ } /* end else */
+
+ /* Print out diminfo, if it's valid */
+ if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES)
+ H5S__hyper_print_diminfo(f, space);
+
+ /* Start print out the highest-order of dimension */
+ if(hslab->span_lst)
+ H5S__hyper_print_spans_dfs(f, hslab->span_lst, 0, dims);
+ HDfprintf(f, "=======================\n\n");
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5S__hyper_print_space_dfs() */
#endif /* H5S_HYPER_DEBUG */
-
+
/*-------------------------------------------------------------------------
- * Function: H5S__hyper_iter_init
+ * Function: H5S__hyper_get_op_gen
+ *
+ * Purpose: Acquire a unique operation generation value
+ *
+ * Return: Operation generation value (can't fail)
*
- * Purpose: Initializes iteration information for hyperslab span tree selection.
+ * Programmer: Quincey Koziol
+ * Saturday, January 19, 2019
*
- * Return: non-negative on success, negative on failure.
+ * Notes: Assumes that a 64-bit value will not wrap around during
+ * the lifespan of the process.
*
- * Programmer: Quincey Koziol
+ *-------------------------------------------------------------------------
+ */
+uint64_t
+H5S__hyper_get_op_gen(void)
+{
+ FUNC_ENTER_PACKAGE_NOERR
+
+ FUNC_LEAVE_NOAPI(H5S_hyper_op_gen_g++);
+} /* end H5S__hyper_op_gen() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5S__hyper_iter_init
+ *
+ * Purpose: Initializes iteration information for hyperslab selection.
+ *
+ * Return: Non-negative on success, negative on failure.
+ *
+ * Programmer: Quincey Koziol
* Saturday, February 24, 2001
*
- * Notes: If the 'elmt_size' parameter is set to zero, the regular
+ * Notes: If the 'iter->elmt_size' field is set to zero, the regular
* hyperslab selection iterator will not be 'flattened'. This
* is used by the H5S_select_shape_same() code to avoid changing
* the rank and appearance of the selection.
@@ -276,40 +568,47 @@ H5S__hyper_print_diminfo(FILE *f, const H5S_t *space)
*-------------------------------------------------------------------------
*/
static herr_t
-H5S__hyper_iter_init(H5S_sel_iter_t *iter, const H5S_t *space)
+H5S__hyper_iter_init(const H5S_t *space, H5S_sel_iter_t *iter)
{
- const H5S_hyper_dim_t *tdiminfo; /* Temporary pointer to diminfo information */
- H5S_hyper_span_info_t *spans; /* Pointer to hyperslab span info node */
- unsigned rank; /* Dataspace's dimension rank */
- unsigned u; /* Index variable */
- int i; /* Index variable */
+ hsize_t *slab_size; /* Pointer to the dataspace dimensions to use for calc. slab */
+ hsize_t acc; /* Accumulator for computing cumulative sizes */
+ unsigned slab_dim; /* Rank of the fastest changing dimension for calc. slab */
+ unsigned rank; /* Dataspace's dimension rank */
+ unsigned u; /* Index variable */
+ int i; /* Index variable */
+ herr_t ret_value = SUCCEED; /* return value */
- FUNC_ENTER_STATIC_NOERR
+ FUNC_ENTER_STATIC
/* Check args */
HDassert(space && H5S_SEL_HYPERSLABS == H5S_GET_SELECT_TYPE(space));
HDassert(iter);
HDassert(space->select.sel_info.hslab->unlim_dim < 0);
- /* Initialize the number of points to iterate over */
- iter->elmt_left = space->select.num_elem;
+ /* Initialize the hyperslab iterator's rank */
iter->u.hyp.iter_rank = 0;
/* Get the rank of the dataspace */
- rank = space->extent.rank;
+ rank = iter->rank;
- /* Set the temporary pointer to the dimension information */
- tdiminfo = space->select.sel_info.hslab->opt_diminfo;
+ /* Attempt to rebuild diminfo if it is invalid and has not been confirmed
+ * to be impossible.
+ */
+ if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_NO)
+ H5S__hyper_rebuild((H5S_t *)space); /* Casting away const OK -NAF */
/* Check for the special case of just one H5Sselect_hyperslab call made */
- if(space->select.sel_info.hslab->diminfo_valid) {
+ if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) {
/* Initialize the information needed for regular hyperslab I/O */
+ const H5S_hyper_dim_t *tdiminfo; /* Temporary pointer to diminfo information */
const hsize_t *mem_size; /* Temporary pointer to dataspace extent's dimension sizes */
- hsize_t acc; /* Accumulator for "flattened" dimension's sizes */
unsigned cont_dim = 0; /* # of contiguous dimensions */
+ /* Set the temporary pointer to the dimension information */
+ tdiminfo = space->select.sel_info.hslab->diminfo.opt;
+
/* Set the temporary pointer to the dataspace extent's dimension sizes */
- mem_size = space->extent.size;
+ mem_size = iter->dims;
/*
* For a regular hyperslab to be contiguous up to some dimension, it
@@ -336,7 +635,7 @@ H5S__hyper_iter_init(H5S_sel_iter_t *iter, const H5S_t *space)
/* Check if the regular selection can be "flattened" */
if(cont_dim > 0) {
- unsigned last_dim_flattened = 1; /* Flag to indicate that the last dimension was flattened */
+ hbool_t last_dim_flattened = TRUE; /* Flag to indicate that the last dimension was flattened */
unsigned flat_rank = rank-cont_dim; /* Number of dimensions after flattening */
unsigned curr_dim; /* Current dimension */
@@ -352,7 +651,7 @@ H5S__hyper_iter_init(H5S_sel_iter_t *iter, const H5S_t *space)
acc *= mem_size[i];
/* Indicate that the dimension was flattened */
- last_dim_flattened = 1;
+ last_dim_flattened = TRUE;
} /* end if */
else {
if(last_dim_flattened) {
@@ -367,10 +666,10 @@ H5S__hyper_iter_init(H5S_sel_iter_t *iter, const H5S_t *space)
iter->u.hyp.diminfo[curr_dim].count = tdiminfo[i].count;
iter->u.hyp.diminfo[curr_dim].block = tdiminfo[i].block * acc;
iter->u.hyp.size[curr_dim] = mem_size[i] * acc;
- iter->u.hyp.sel_off[curr_dim] = space->select.offset[i] * (hssize_t)acc;
+ iter->u.hyp.sel_off[curr_dim] = iter->sel_off[i] * (hssize_t)acc;
/* Reset the "last dim flattened" flag to avoid flattened any further dimensions */
- last_dim_flattened = 0;
+ last_dim_flattened = FALSE;
/* Reset the "accumulator" for possible further dimension flattening */
acc = 1;
@@ -382,7 +681,7 @@ H5S__hyper_iter_init(H5S_sel_iter_t *iter, const H5S_t *space)
iter->u.hyp.diminfo[curr_dim].count = tdiminfo[i].count;
iter->u.hyp.diminfo[curr_dim].block = tdiminfo[i].block;
iter->u.hyp.size[curr_dim] = mem_size[i];
- iter->u.hyp.sel_off[curr_dim] = space->select.offset[i];
+ iter->u.hyp.sel_off[curr_dim] = iter->sel_off[i];
} /* end else */
/* Decrement "current" flattened dimension */
@@ -393,20 +692,23 @@ H5S__hyper_iter_init(H5S_sel_iter_t *iter, const H5S_t *space)
/* Initialize "flattened" iterator offset to initial location and dataspace extent and selection information to correct values */
for(u = 0; u < flat_rank; u++)
iter->u.hyp.off[u] = iter->u.hyp.diminfo[u].start;
+
+ /* Set up information for computing slab sizes */
+ slab_dim = iter->u.hyp.iter_rank - 1;
+ slab_size = iter->u.hyp.size;
} /* end if */
else {
+ /* Make local copy of the regular selection information */
+ HDcompile_assert(sizeof(iter->u.hyp.diminfo) == sizeof(space->select.sel_info.hslab->diminfo.opt));
+ H5MM_memcpy(iter->u.hyp.diminfo, tdiminfo, sizeof(iter->u.hyp.diminfo));
+
/* Initialize position to initial location */
- /* Also make local copy of the regular selection information */
- for(u = 0; u < rank; u++) {
- /* Regular selection information */
- iter->u.hyp.diminfo[u].start = tdiminfo[u].start;
- iter->u.hyp.diminfo[u].stride = tdiminfo[u].stride;
- iter->u.hyp.diminfo[u].count = tdiminfo[u].count;
- iter->u.hyp.diminfo[u].block = tdiminfo[u].block;
-
- /* Position information */
+ for(u = 0; u < rank; u++)
iter->u.hyp.off[u] = tdiminfo[u].start;
- } /* end if */
+
+ /* Set up information for computing slab sizes */
+ slab_dim = iter->rank - 1;
+ slab_size = iter->dims;
} /* end else */
/* Flag the diminfo information as valid in the iterator */
@@ -415,14 +717,30 @@ H5S__hyper_iter_init(H5S_sel_iter_t *iter, const H5S_t *space)
/* Initialize irregular region information also (for release) */
iter->u.hyp.spans = NULL;
} /* end if */
- else {
-/* Initialize the information needed for non-regular hyperslab I/O */
- HDassert(space->select.sel_info.hslab->span_lst);
- /* Make a copy of the span tree to iterate over */
- iter->u.hyp.spans = H5S__hyper_copy_span(space->select.sel_info.hslab->span_lst);
+ else { /* Initialize the information needed for non-regular hyperslab I/O */
+ H5S_hyper_span_info_t *spans; /* Pointer to hyperslab span info node */
- /* Set the nelem & pstride values according to the element size */
- H5S__hyper_span_precompute(iter->u.hyp.spans, iter->elmt_size);
+ /* If this iterator is created from an API call, by default we clone the
+ * selection now, as the dataspace could be modified or go out of scope.
+ *
+ * However, if the H5S_SEL_ITER_SHARE_WITH_DATASPACE flag is given,
+ * the selection is shared between the selection iterator and the
+ * dataspace. In this case, the application _must_not_ modify or
+ * close the dataspace that the iterator is operating on, or undefined
+ * behavior will occur.
+ */
+ if((iter->flags & H5S_SEL_ITER_API_CALL) &&
+ !(iter->flags & H5S_SEL_ITER_SHARE_WITH_DATASPACE)) {
+ /* Copy the span tree */
+ if(NULL == (iter->u.hyp.spans = H5S__hyper_copy_span(space->select.sel_info.hslab->span_lst, space->extent.rank)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy span tree")
+ } /* end if */
+ else {
+ /* Share the source dataspace's span tree by incrementing the reference count on it */
+ HDassert(space->select.sel_info.hslab->span_lst);
+ iter->u.hyp.spans = space->select.sel_info.hslab->span_lst;
+ iter->u.hyp.spans->count++;
+ } /* end else */
/* Initialize the starting span_info's and spans */
spans = iter->u.hyp.spans;
@@ -441,26 +759,45 @@ H5S__hyper_iter_init(H5S_sel_iter_t *iter, const H5S_t *space)
spans = spans->head->down;
} /* end for */
+ /* Set up information for computing slab sizes */
+ slab_dim = iter->rank - 1;
+ slab_size = iter->dims;
+
/* Flag the diminfo information as not valid in the iterator */
iter->u.hyp.diminfo_valid = FALSE;
} /* end else */
+ /* Compute the cumulative size of dataspace dimensions */
+ for(i = (int)slab_dim, acc = iter->elmt_size; i >= 0; i--) {
+ iter->u.hyp.slab[i] = acc;
+ acc *= slab_size[i];
+ } /* end for */
+
+ /* Initialize more information for irregular hyperslab selections */
+ if(!iter->u.hyp.diminfo_valid) {
+ /* Set the offset of the first element iterated on, in each dimension */
+ for(u = 0; u < rank; u++)
+ /* Compute the sequential element offset */
+ iter->u.hyp.loc_off[u] = ((hsize_t)((hssize_t)iter->u.hyp.off[u] + iter->sel_off[u])) * iter->u.hyp.slab[u];
+ } /* end if */
+
/* Initialize type of selection iterator */
iter->type = H5S_sel_iter_hyper;
- FUNC_LEAVE_NOAPI(SUCCEED)
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S__hyper_iter_init() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5S__hyper_iter_coords
+ * Function: H5S__hyper_iter_coords
*
- * Purpose: Retrieve the current coordinates of iterator for current
+ * Purpose: Retrieve the current coordinates of iterator for current
* selection
*
- * Return: non-negative on success, negative on failure
+ * Return: Non-negative on success, negative on failure
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* Tuesday, April 22, 2003
*
*-------------------------------------------------------------------------
@@ -528,24 +865,24 @@ H5S__hyper_iter_coords(const H5S_sel_iter_t *iter, hsize_t *coords)
HDassert(v < 0);
} /* end if */
else
- HDmemcpy(coords, iter->u.hyp.off, sizeof(hsize_t) * iter->rank);
+ H5MM_memcpy(coords, iter->u.hyp.off, sizeof(hsize_t) * iter->rank);
} /* end if */
else
- HDmemcpy(coords, iter->u.hyp.off, sizeof(hsize_t) * iter->rank);
+ H5MM_memcpy(coords, iter->u.hyp.off, sizeof(hsize_t) * iter->rank);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5S__hyper_iter_coords() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5S__hyper_iter_block
+ * Function: H5S__hyper_iter_block
*
- * Purpose: Retrieve the current block of iterator for current
+ * Purpose: Retrieve the current block of iterator for current
* selection
*
- * Return: non-negative on success, negative on failure
+ * Return: Non-negative on success, negative on failure
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* Monday, June 2, 2003
*
* Notes: This routine assumes that the iterator is always located at
@@ -569,34 +906,32 @@ H5S__hyper_iter_block(const H5S_sel_iter_t *iter, hsize_t *start, hsize_t *end)
/* Check for a single "regular" hyperslab */
if(iter->u.hyp.diminfo_valid) {
- /* Compute the end of the block */
+ /* Copy the start and compute the end of the block */
for(u = 0; u < iter->rank; u++) {
start[u] = iter->u.hyp.off[u];
end[u] = (start[u] + iter->u.hyp.diminfo[u].block) - 1;
} /* end for */
} /* end if */
else {
- /* Copy the start of the block */
- for(u = 0; u < iter->rank; u++)
+ /* Copy the start & end of the block */
+ for(u = 0; u < iter->rank; u++) {
start[u] = iter->u.hyp.span[u]->low;
-
- /* Copy the end of the block */
- for(u = 0; u < iter->rank; u++)
end[u] = iter->u.hyp.span[u]->high;
+ } /* end for */
} /* end else */
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5S__hyper_iter_block() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5S__hyper_iter_nelmts
+ * Function: H5S__hyper_iter_nelmts
*
- * Purpose: Return number of elements left to process in iterator
+ * Purpose: Return number of elements left to process in iterator
*
- * Return: non-negative number of elements on success, zero on failure
+ * Return: Non-negative number of elements on success, zero on failure
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* Tuesday, June 16, 1998
*
*-------------------------------------------------------------------------
@@ -612,7 +947,7 @@ H5S__hyper_iter_nelmts(const H5S_sel_iter_t *iter)
FUNC_LEAVE_NOAPI(iter->elmt_left)
} /* end H5S__hyper_iter_nelmts() */
-
+
/*--------------------------------------------------------------------------
NAME
H5S__hyper_iter_has_next_block
@@ -630,7 +965,7 @@ H5S__hyper_iter_nelmts(const H5S_sel_iter_t *iter)
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-static htri_t
+static H5_ATTR_PURE htri_t
H5S__hyper_iter_has_next_block(const H5S_sel_iter_t *iter)
{
unsigned u; /* Local index variable */
@@ -668,17 +1003,17 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S__hyper_iter_has_next_block() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5S__hyper_iter_next
+ * Function: H5S__hyper_iter_next
*
- * Purpose: Moves a hyperslab iterator to the beginning of the next sequence
+ * Purpose: Moves a hyperslab iterator to the beginning of the next sequence
* of elements to read. Handles walking off the end in all dimensions.
*
- * Return: Success: non-negative
- * Failure: negative
+ * Return: Success: non-negative
+ * Failure: negative
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* Friday, September 8, 2000
*
*-------------------------------------------------------------------------
@@ -688,7 +1023,7 @@ H5S__hyper_iter_next(H5S_sel_iter_t *iter, size_t nelem)
{
unsigned ndims; /* Number of dimensions of dataset */
int fast_dim; /* Rank of the fastest changing dimension for the dataspace */
- unsigned i; /* Counters */
+ unsigned u; /* Counters */
FUNC_ENTER_STATIC_NOERR
@@ -696,19 +1031,17 @@ H5S__hyper_iter_next(H5S_sel_iter_t *iter, size_t nelem)
/* (i.e. a regular hyperslab selection */
if(iter->u.hyp.diminfo_valid) {
const H5S_hyper_dim_t *tdiminfo; /* Temporary pointer to diminfo information */
- hsize_t iter_offset[H5O_LAYOUT_NDIMS];
- hsize_t iter_count[H5O_LAYOUT_NDIMS];
+ hsize_t iter_offset[H5S_MAX_RANK];
+ hsize_t iter_count[H5S_MAX_RANK];
int temp_dim; /* Temporary rank holder */
/* Check if this is a "flattened" regular hyperslab selection */
- if(iter->u.hyp.iter_rank != 0 && iter->u.hyp.iter_rank < iter->rank) {
+ if(iter->u.hyp.iter_rank != 0 && iter->u.hyp.iter_rank < iter->rank)
/* Set the aliases for the dimension rank */
ndims = iter->u.hyp.iter_rank;
- } /* end if */
- else {
+ else
/* Set the aliases for the dimension rank */
ndims = iter->rank;
- } /* end else */
/* Set the fastest dimension rank */
fast_dim = (int)ndims - 1;
@@ -717,14 +1050,14 @@ H5S__hyper_iter_next(H5S_sel_iter_t *iter, size_t nelem)
tdiminfo = iter->u.hyp.diminfo;
/* Calculate the offset and block count for each dimension */
- for(i = 0; i < ndims; i++) {
- if(tdiminfo[i].count == 1) {
- iter_offset[i] = iter->u.hyp.off[i] - tdiminfo[i].start;
- iter_count[i] = 0;
+ for(u = 0; u < ndims; u++) {
+ if(tdiminfo[u].count == 1) {
+ iter_offset[u] = iter->u.hyp.off[u] - tdiminfo[u].start;
+ iter_count[u] = 0;
} /* end if */
else {
- iter_offset[i] = (iter->u.hyp.off[i] - tdiminfo[i].start) % tdiminfo[i].stride;
- iter_count[i] = (iter->u.hyp.off[i] - tdiminfo[i].start) / tdiminfo[i].stride;
+ iter_offset[u] = (iter->u.hyp.off[u] - tdiminfo[u].start) % tdiminfo[u].stride;
+ iter_count[u] = (iter->u.hyp.off[u] - tdiminfo[u].start) / tdiminfo[u].stride;
} /* end else */
} /* end for */
@@ -749,10 +1082,9 @@ H5S__hyper_iter_next(H5S_sel_iter_t *iter, size_t nelem)
/* Decrement the number of elements advanced */
nelem -= actual_elem;
} /* end if */
- else {
+ else
/* Move to the next row in the current dimension */
iter_offset[temp_dim]++;
- } /* end else */
/* If this block is still in the range of blocks to output for the dimension, break out of loop */
if(iter_offset[temp_dim] < tdiminfo[temp_dim].block)
@@ -775,8 +1107,8 @@ H5S__hyper_iter_next(H5S_sel_iter_t *iter, size_t nelem)
} /* end while */
/* Translate current iter_offset and iter_count into iterator position */
- for(i = 0; i < ndims; i++)
- iter->u.hyp.off[i] = tdiminfo[i].start + (tdiminfo[i].stride * iter_count[i]) + iter_offset[i];
+ for(u = 0; u < ndims; u++)
+ iter->u.hyp.off[u] = tdiminfo[u].start + (tdiminfo[u].stride * iter_count[u]) + iter_offset[u];
} /* end if */
/* Must be an irregular hyperslab selection */
else {
@@ -820,15 +1152,13 @@ H5S__hyper_iter_next(H5S_sel_iter_t *iter, size_t nelem)
/* Decrement the number of elements advanced */
nelem -= actual_elem;
} /* end if */
- else {
+ else
/* Move to the next row in the current dimension */
abs_arr[curr_dim]++;
- } /* end else */
/* Check if we are still within the span */
- if(abs_arr[curr_dim] <= curr_span->high) {
+ if(abs_arr[curr_dim] <= curr_span->high)
break;
- } /* end if */
/* If we walked off that span, advance to the next span */
else {
/* Advance span in this dimension */
@@ -844,10 +1174,9 @@ H5S__hyper_iter_next(H5S_sel_iter_t *iter, size_t nelem)
break;
} /* end if */
- else {
+ else
/* If we finished the span list in this dimension, decrement the dimension worked on and loop again */
curr_dim--;
- } /* end else */
} /* end else */
} /* end while */
@@ -881,17 +1210,17 @@ H5S__hyper_iter_next(H5S_sel_iter_t *iter, size_t nelem)
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5S__hyper_iter_next() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5S__hyper_iter_next_block
+ * Function: H5S__hyper_iter_next_block
*
- * Purpose: Moves a hyperslab iterator to the beginning of the next sequence
+ * Purpose: Moves a hyperslab iterator to the beginning of the next sequence
* of elements to read. Handles walking off the end in all dimensions.
*
- * Return: Success: non-negative
- * Failure: negative
+ * Return: Success: non-negative
+ * Failure: negative
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* Tuesday, June 3, 2003
*
*-------------------------------------------------------------------------
@@ -906,22 +1235,20 @@ H5S__hyper_iter_next_block(H5S_sel_iter_t *iter)
FUNC_ENTER_STATIC_NOERR
/* Check for the special case of just one H5Sselect_hyperslab call made */
- /* (i.e. a regular hyperslab selection */
+ /* (i.e. a regular hyperslab selection) */
if(iter->u.hyp.diminfo_valid) {
const H5S_hyper_dim_t *tdiminfo; /* Temporary pointer to diminfo information */
- hsize_t iter_offset[H5O_LAYOUT_NDIMS];
- hsize_t iter_count[H5O_LAYOUT_NDIMS];
+ hsize_t iter_offset[H5S_MAX_RANK];
+ hsize_t iter_count[H5S_MAX_RANK];
int temp_dim; /* Temporary rank holder */
/* Check if this is a "flattened" regular hyperslab selection */
- if(iter->u.hyp.iter_rank != 0 && iter->u.hyp.iter_rank < iter->rank) {
+ if(iter->u.hyp.iter_rank != 0 && iter->u.hyp.iter_rank < iter->rank)
/* Set the aliases for the dimension rank */
ndims = iter->u.hyp.iter_rank;
- } /* end if */
- else {
+ else
/* Set the aliases for the dimension rank */
ndims = iter->rank;
- } /* end else */
/* Set the fastest dimension rank */
fast_dim = (int)ndims - 1;
@@ -944,14 +1271,12 @@ H5S__hyper_iter_next_block(H5S_sel_iter_t *iter)
/* Advance one block */
temp_dim = fast_dim; /* Start with the fastest changing dimension */
while(temp_dim >= 0) {
- if(temp_dim == fast_dim) {
+ if(temp_dim == fast_dim)
/* Move iterator over current block */
iter_offset[temp_dim] += tdiminfo[temp_dim].block;
- } /* end if */
- else {
+ else
/* Move to the next row in the current dimension */
iter_offset[temp_dim]++;
- } /* end else */
/* If this block is still in the range of blocks to output for the dimension, break out of loop */
if(iter_offset[temp_dim] < tdiminfo[temp_dim].block)
@@ -1000,19 +1325,16 @@ H5S__hyper_iter_next_block(H5S_sel_iter_t *iter)
curr_span = ispan[curr_dim];
/* Increment absolute position */
- if(curr_dim == fast_dim) {
+ if(curr_dim == fast_dim)
/* Move the iterator over rest of element in span */
abs_arr[curr_dim] = curr_span->high + 1;
- } /* end if */
- else {
+ else
/* Move to the next row in the current dimension */
abs_arr[curr_dim]++;
- } /* end else */
/* Check if we are still within the span */
- if(abs_arr[curr_dim] <= curr_span->high) {
+ if(abs_arr[curr_dim] <= curr_span->high)
break;
- } /* end if */
/* If we walked off that span, advance to the next span */
else {
/* Advance span in this dimension */
@@ -1028,10 +1350,9 @@ H5S__hyper_iter_next_block(H5S_sel_iter_t *iter)
break;
} /* end if */
- else {
+ else
/* If we finished the span list in this dimension, decrement the dimension worked on and loop again */
curr_dim--;
- } /* end else */
} /* end else */
} /* end while */
@@ -1062,241 +1383,1479 @@ H5S__hyper_iter_next_block(H5S_sel_iter_t *iter)
} /* end else */
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5S__hyper_iter_next() */
+} /* end H5S__hyper_iter_next_block() */
+
-
/*--------------------------------------------------------------------------
NAME
- H5S__hyper_iter_release
+ H5S__hyper_iter_get_seq_list_gen
PURPOSE
- Release hyperslab selection iterator information for a dataspace
+ Create a list of offsets & lengths for a selection
USAGE
- herr_t H5S__hyper_iter_release(iter)
- H5S_sel_iter_t *iter; IN: Pointer to selection iterator
+ herr_t H5S__hyper_iter_get_seq_list_gen(iter,maxseq,maxelem,nseq,nelem,off,len)
+ H5S_sel_iter_t *iter; IN/OUT: Selection iterator describing last
+ position of interest in selection.
+ size_t maxseq; IN: Maximum number of sequences to generate
+ size_t maxelem; IN: Maximum number of elements to include in the
+ generated sequences
+ size_t *nseq; OUT: Actual number of sequences generated
+ size_t *nelem; OUT: Actual number of elements in sequences generated
+ hsize_t *off; OUT: Array of offsets
+ size_t *len; OUT: Array of lengths
RETURNS
- Non-negative on success/Negative on failure
+ Non-negative on success/Negative on failure.
DESCRIPTION
- Releases all information for a dataspace hyperslab selection iterator
+ Use the selection in the dataspace to generate a list of byte offsets and
+ lengths for the region(s) selected. Start/Restart from the position in the
+ ITER parameter. The number of sequences generated is limited by the MAXSEQ
+ parameter and the number of sequences actually generated is stored in the
+ NSEQ parameter.
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S__hyper_iter_release(H5S_sel_iter_t *iter)
+H5S__hyper_iter_get_seq_list_gen(H5S_sel_iter_t *iter, size_t maxseq, size_t maxelem,
+ size_t *nseq, size_t *nelem, hsize_t *off, size_t *len)
{
+ H5S_hyper_span_t *curr_span; /* Current hyperslab span node */
+ H5S_hyper_span_t **ispan; /* Iterator's hyperslab span nodes */
+ hsize_t *slab; /* Cumulative size of each dimension in bytes */
+ hsize_t loc_off; /* Byte offset in the dataspace */
+ hsize_t last_span_end = 0; /* The offset of the end of the last span */
+ hsize_t *abs_arr; /* Absolute hyperslab span position, in elements */
+ hsize_t *loc_arr; /* Byte offset of hyperslab span position within buffer */
+ const hssize_t *sel_off; /* Offset within the dataspace extent */
+ size_t span_elmts = 0; /* Number of elements to actually use for this span */
+ size_t span_size = 0; /* Number of bytes in current span to actually process */
+ size_t io_left; /* Initial number of elements to process */
+ size_t io_elmts_left; /* Number of elements left to process */
+ size_t io_used; /* Number of elements processed */
+ size_t curr_seq = 0; /* Number of sequence/offsets stored in the arrays */
+ size_t elem_size; /* Size of each element iterating over */
+ unsigned ndims; /* Number of dimensions of dataset */
+ unsigned fast_dim; /* Rank of the fastest changing dimension for the dataspace */
+ int curr_dim; /* Current dimension being operated on */
+ unsigned u; /* Index variable */
+
FUNC_ENTER_STATIC_NOERR
/* Check args */
HDassert(iter);
+ HDassert(maxseq > 0);
+ HDassert(maxelem > 0);
+ HDassert(nseq);
+ HDassert(nelem);
+ HDassert(off);
+ HDassert(len);
-/* Release the information needed for non-regular hyperslab I/O */
- /* Free the copy of the selections span tree */
- if(iter->u.hyp.spans != NULL)
- H5S__hyper_free_span_info(iter->u.hyp.spans);
+ /* Set the rank of the fastest changing dimension */
+ ndims = iter->rank;
+ fast_dim = (ndims - 1);
+
+ /* Get the pointers to the current span info and span nodes */
+ curr_span = iter->u.hyp.span[fast_dim];
+ abs_arr = iter->u.hyp.off;
+ loc_arr = iter->u.hyp.loc_off;
+ slab = iter->u.hyp.slab;
+ sel_off = iter->sel_off;
+ ispan = iter->u.hyp.span;
+ elem_size = iter->elmt_size;
+
+ /* Set the amount of elements to perform I/O on, etc. */
+ H5_CHECK_OVERFLOW(iter->elmt_left, hsize_t, size_t);
+ io_elmts_left = io_left = MIN(maxelem, (size_t)iter->elmt_left);
+
+ /* Set the offset of the first element iterated on */
+ for(u = 0, loc_off = 0; u < ndims; u++)
+ loc_off += loc_arr[u];
+
+ /* Take care of any partial spans leftover from previous I/Os */
+ if(abs_arr[fast_dim] != curr_span->low) {
+ /* Finish the span in the fastest changing dimension */
+
+ /* Compute the number of elements to attempt in this span */
+ H5_CHECKED_ASSIGN(span_elmts, size_t, ((curr_span->high - abs_arr[fast_dim]) + 1), hsize_t);
+
+ /* Check number of elements against upper bounds allowed */
+ if(span_elmts > io_elmts_left)
+ span_elmts = io_elmts_left;
+
+ /* Set the span_size, in bytes */
+ span_size = span_elmts * elem_size;
+
+ /* Add the partial span to the list of sequences */
+ off[curr_seq] = loc_off;
+ len[curr_seq] = span_size;
+
+ /* Increment sequence count */
+ curr_seq++;
+
+ /* Set the location of the last span's end */
+ last_span_end = loc_off + span_size;
+
+ /* Decrement I/O left to perform */
+ io_elmts_left -= span_elmts;
+
+ /* Check if we are done */
+ if(io_elmts_left > 0) {
+ /* Move to next span in fastest changing dimension */
+ curr_span = curr_span->next;
+
+ if(NULL != curr_span) {
+ /* Move location offset of destination */
+ loc_off += (curr_span->low - abs_arr[fast_dim]) * elem_size;
+
+ /* Move iterator for fastest changing dimension */
+ abs_arr[fast_dim] = curr_span->low;
+ loc_arr[fast_dim] = ((hsize_t)((hssize_t)curr_span->low + sel_off[fast_dim])) * slab[fast_dim];
+ ispan[fast_dim] = curr_span;
+ } /* end if */
+ } /* end if */
+ else {
+ /* Advance the hyperslab iterator */
+ abs_arr[fast_dim] += span_elmts;
+
+ /* Check if we are still within the span */
+ if(abs_arr[fast_dim] <= curr_span->high) {
+ /* Sanity check */
+ HDassert(ispan[fast_dim] == curr_span);
+
+ /* Update byte offset */
+ loc_arr[fast_dim] += span_size;
+ } /* end if */
+ /* If we walked off that span, advance to the next span */
+ else {
+ /* Advance span in this dimension */
+ curr_span = curr_span->next;
+
+ /* Check if we have a valid span in this dimension still */
+ if(NULL != curr_span) {
+ /* Reset absolute position */
+ abs_arr[fast_dim] = curr_span->low;
+
+ /* Update location offset */
+ loc_arr[fast_dim] = ((hsize_t)((hssize_t)curr_span->low + sel_off[fast_dim])) * slab[fast_dim];
+
+ /* Reset the span in the current dimension */
+ ispan[fast_dim] = curr_span;
+ } /* end if */
+ } /* end else */
+ } /* end else */
+
+ /* Adjust iterator pointers */
+
+ if(NULL == curr_span) {
+/* Same as code in main loop */
+ /* Start at the next fastest dim */
+ curr_dim = (int)(fast_dim - 1);
+
+ /* Work back up through the dimensions */
+ while(curr_dim >= 0) {
+ /* Reset the current span */
+ curr_span = ispan[curr_dim];
+
+ /* Increment absolute position */
+ abs_arr[curr_dim]++;
+
+ /* Check if we are still within the span */
+ if(abs_arr[curr_dim] <= curr_span->high) {
+ /* Update location offset */
+ loc_arr[curr_dim] += slab[curr_dim];
+
+ break;
+ } /* end if */
+ /* If we walked off that span, advance to the next span */
+ else {
+ /* Advance span in this dimension */
+ curr_span = curr_span->next;
+
+ /* Check if we have a valid span in this dimension still */
+ if(NULL != curr_span) {
+ /* Reset the span in the current dimension */
+ ispan[curr_dim] = curr_span;
+
+ /* Reset absolute position */
+ abs_arr[curr_dim] = curr_span->low;
+
+ /* Update byte location */
+ loc_arr[curr_dim] = ((hsize_t)((hssize_t)curr_span->low + sel_off[curr_dim])) * slab[curr_dim];
+
+ break;
+ } /* end if */
+ else
+ /* If we finished the span list in this dimension, decrement the dimension worked on and loop again */
+ curr_dim--;
+ } /* end else */
+ } /* end while */
+
+ /* Check if we have more spans in the tree */
+ if(curr_dim >= 0) {
+ /* Walk back down the iterator positions, resetting them */
+ while((unsigned)curr_dim < fast_dim) {
+ HDassert(curr_span);
+ HDassert(curr_span->down);
+ HDassert(curr_span->down->head);
+
+ /* Increment current dimension */
+ curr_dim++;
+
+ /* Set the new span_info & span for this dimension */
+ ispan[curr_dim] = curr_span->down->head;
+
+ /* Advance span down the tree */
+ curr_span = curr_span->down->head;
+
+ /* Reset the absolute offset for the dim */
+ abs_arr[curr_dim] = curr_span->low;
+
+ /* Update the location offset */
+ loc_arr[curr_dim] = ((hsize_t)((hssize_t)curr_span->low + sel_off[curr_dim])) * slab[curr_dim];
+ } /* end while */
+
+ /* Verify that the curr_span points to the fastest dim */
+ HDassert(curr_span == ispan[fast_dim]);
+
+ /* Reset the buffer offset */
+ for(u = 0, loc_off = 0; u < ndims; u++)
+ loc_off += loc_arr[u];
+ } /* end else */
+ else
+ /* We had better be done with I/O or bad things are going to happen... */
+ HDassert(io_elmts_left == 0);
+ } /* end if */
+ } /* end if */
+
+ /* Perform the I/O on the elements, based on the position of the iterator */
+ while(io_elmts_left > 0 && curr_seq < maxseq) {
+ H5S_hyper_span_t *prev_span; /* Previous hyperslab span node */
+
+ /* Sanity check */
+ HDassert(curr_span);
+
+ /* Set to current span, so the first adjustment to loc_off is 0 */
+ prev_span = curr_span;
+
+ /* Loop over all the spans in the fastest changing dimension */
+ while(curr_span != NULL) {
+ hsize_t nelmts; /* # of elements covered by current span */
+
+ /* Move location offset of current span */
+ loc_off += (curr_span->low - prev_span->low) * elem_size;
+
+ /* Compute the number of elements to attempt in this span */
+ nelmts = (curr_span->high - curr_span->low) + 1;
+ H5_CHECKED_ASSIGN(span_elmts, size_t, nelmts, hsize_t);
+
+ /* Check number of elements against upper bounds allowed */
+ if(span_elmts >= io_elmts_left) {
+ /* Trim the number of elements to output */
+ span_elmts = io_elmts_left;
+ span_size = span_elmts * elem_size;
+ io_elmts_left = 0;
+
+/* COMMON */
+ /* Store the I/O information for the span */
+
+ /* Check if this is appending onto previous sequence */
+ if(curr_seq > 0 && last_span_end == loc_off)
+ len[curr_seq - 1] += span_size;
+ else {
+ off[curr_seq] = loc_off;
+ len[curr_seq] = span_size;
+
+ /* Increment the number of sequences in arrays */
+ curr_seq++;
+ } /* end else */
+/* end COMMON */
+
+ /* Break out now, we are finished with I/O */
+ break;
+ } /* end if */
+ else {
+ /* Decrement I/O left to perform */
+ span_size = span_elmts * elem_size;
+ io_elmts_left -= span_elmts;
+
+/* COMMON */
+ /* Store the I/O information for the span */
+
+ /* Check if this is appending onto previous sequence */
+ if(curr_seq > 0 && last_span_end == loc_off)
+ len[curr_seq - 1] += span_size;
+ else {
+ off[curr_seq] = loc_off;
+ len[curr_seq] = span_size;
+
+ /* Increment the number of sequences in arrays */
+ curr_seq++;
+ } /* end else */
+/* end COMMON */
+
+ /* If the sequence & offset arrays are full, do what? */
+ if(curr_seq >= maxseq)
+ /* Break out now, we are finished with sequences */
+ break;
+ } /* end else */
+
+ /* Set the location of the last span's end */
+ last_span_end = loc_off + span_size;
+
+ /* Move to next span in fastest changing dimension */
+ prev_span = curr_span;
+ curr_span = curr_span->next;
+ } /* end while */
+
+ /* Check if we are done */
+ if(io_elmts_left == 0 || curr_seq >= maxseq) {
+ /* Sanity checks */
+ HDassert(curr_span);
+
+ /* Update absolute position */
+ abs_arr[fast_dim] = curr_span->low + span_elmts;
+
+ /* Check if we are still within the span */
+ if(abs_arr[fast_dim] <= curr_span->high) {
+ /* Reset the span for the fast dimension */
+ ispan[fast_dim] = curr_span;
+
+ /* Update location offset */
+ loc_arr[fast_dim] = ((hsize_t)((hssize_t)curr_span->low + (hssize_t)span_elmts + sel_off[fast_dim])) * slab[fast_dim];
+
+ break;
+ } /* end if */
+ /* If we walked off that span, advance to the next span */
+ else {
+ /* Advance span in this dimension */
+ curr_span = curr_span->next;
+
+ /* Check if we have a valid span in this dimension still */
+ if(curr_span != NULL) {
+ /* Reset absolute position */
+ abs_arr[fast_dim] = curr_span->low;
+ loc_arr[fast_dim] = ((hsize_t)((hssize_t)curr_span->low + sel_off[fast_dim])) * slab[fast_dim];
+ ispan[fast_dim] = curr_span;
+
+ break;
+ } /* end if */
+ } /* end else */
+ } /* end if */
+
+ /* Adjust iterator pointers */
+
+ /* Start at the next fastest dim */
+ curr_dim = (int)(fast_dim - 1);
+
+ /* Work back up through the dimensions */
+ while(curr_dim >= 0) {
+ /* Reset the current span */
+ curr_span = ispan[curr_dim];
+
+ /* Increment absolute position */
+ abs_arr[curr_dim]++;
+
+ /* Check if we are still within the span */
+ if(abs_arr[curr_dim] <= curr_span->high) {
+ /* Update location offset */
+ loc_arr[curr_dim] += slab[curr_dim];
+
+ break;
+ } /* end if */
+ /* If we walked off that span, advance to the next span */
+ else {
+ /* Advance span in this dimension */
+ curr_span = curr_span->next;
+
+ /* Check if we have a valid span in this dimension still */
+ if(curr_span != NULL) {
+ /* Reset the span in the current dimension */
+ ispan[curr_dim] = curr_span;
+
+ /* Reset absolute position */
+ abs_arr[curr_dim] = curr_span->low;
+
+ /* Update location offset */
+ loc_arr[curr_dim] = ((hsize_t)((hssize_t)curr_span->low + sel_off[curr_dim])) * slab[curr_dim];
+
+ break;
+ } /* end if */
+ else
+ /* If we finished the span list in this dimension, decrement the dimension worked on and loop again */
+ curr_dim--;
+ } /* end else */
+ } /* end while */
+
+ /* Check if we are finished with the spans in the tree */
+ if(curr_dim < 0) {
+ /* We had better be done with I/O or bad things are going to happen... */
+ HDassert(io_elmts_left == 0);
+ break;
+ } /* end if */
+ else {
+ /* Walk back down the iterator positions, resetting them */
+ while((unsigned)curr_dim < fast_dim) {
+ HDassert(curr_span);
+ HDassert(curr_span->down);
+ HDassert(curr_span->down->head);
+
+ /* Increment current dimension to the next dimension down */
+ curr_dim++;
+
+ /* Set the new span for the next dimension down */
+ ispan[curr_dim] = curr_span->down->head;
+
+ /* Advance span down the tree */
+ curr_span = curr_span->down->head;
+
+ /* Reset the absolute offset for the dim */
+ abs_arr[curr_dim] = curr_span->low;
+
+ /* Update location offset */
+ loc_arr[curr_dim] = ((hsize_t)((hssize_t)curr_span->low + sel_off[curr_dim])) * slab[curr_dim];
+ } /* end while */
+
+ /* Verify that the curr_span points to the fastest dim */
+ HDassert(curr_span == ispan[fast_dim]);
+ } /* end else */
+
+ /* Reset the buffer offset */
+ for(u = 0, loc_off = 0; u < ndims; u++)
+ loc_off += loc_arr[u];
+ } /* end while */
+
+ /* Decrement number of elements left in iterator */
+ io_used = io_left - io_elmts_left;
+ iter->elmt_left -= io_used;
+
+ /* Set the number of sequences generated */
+ *nseq = curr_seq;
+
+ /* Set the number of elements used */
+ *nelem = io_used;
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5S__hyper_iter_release() */
+} /* end H5S__hyper_iter_get_seq_list_gen() */
+
-
/*--------------------------------------------------------------------------
NAME
- H5S__hyper_new_span
+ H5S__hyper_iter_get_seq_list_opt
PURPOSE
- Make a new hyperslab span node
+ Create a list of offsets & lengths for a selection
USAGE
- H5S_hyper_span_t *H5S__hyper_new_span(low, high, down, next)
- hsize_t low, high; IN: Low and high bounds for new span node
- H5S_hyper_span_info_t *down; IN: Down span tree for new node
- H5S_hyper_span_t *next; IN: Next span for new node
+ herr_t H5S__hyper_iter_get_seq_list_opt(iter,maxseq,maxelem,nseq,nelem,off,len)
+ H5S_sel_iter_t *iter; IN/OUT: Selection iterator describing last
+ position of interest in selection.
+ size_t maxseq; IN: Maximum number of sequences to generate
+ size_t maxelem; IN: Maximum number of elements to include in the
+ generated sequences
+ size_t *nseq; OUT: Actual number of sequences generated
+ size_t *nelem; OUT: Actual number of elements in sequences generated
+ hsize_t *off; OUT: Array of offsets
+ size_t *len; OUT: Array of lengths
RETURNS
- Pointer to next span node on success, NULL on failure
+ Non-negative on success/Negative on failure.
DESCRIPTION
- Allocate and initialize a new hyperslab span node, filling in the low &
- high bounds, the down span and next span pointers also. Increment the
- reference count of the 'down span' if applicable.
+ Use the selection in the dataspace to generate a list of byte offsets and
+ lengths for the region(s) selected. Start/Restart from the position in the
+ ITER parameter. The number of sequences generated is limited by the MAXSEQ
+ parameter and the number of sequences actually generated is stored in the
+ NSEQ parameter.
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-static H5S_hyper_span_t *
-H5S__hyper_new_span(hsize_t low, hsize_t high, H5S_hyper_span_info_t *down, H5S_hyper_span_t *next)
+static herr_t
+H5S__hyper_iter_get_seq_list_opt(H5S_sel_iter_t *iter, size_t maxseq, size_t maxelem,
+ size_t *nseq, size_t *nelem, hsize_t *off, size_t *len)
{
- H5S_hyper_span_t *ret_value = NULL; /* Return value */
+ hsize_t *mem_size; /* Size of the source buffer */
+ hsize_t *slab; /* Hyperslab size */
+ const hssize_t *sel_off; /* Selection offset in dataspace */
+ hsize_t offset[H5S_MAX_RANK]; /* Coordinate offset in dataspace */
+ hsize_t tmp_count[H5S_MAX_RANK]; /* Temporary block count */
+ hsize_t tmp_block[H5S_MAX_RANK]; /* Temporary block offset */
+ hsize_t wrap[H5S_MAX_RANK]; /* Bytes to wrap around at the end of a row */
+ hsize_t skip[H5S_MAX_RANK]; /* Bytes to skip between blocks */
+ const H5S_hyper_dim_t *tdiminfo; /* Temporary pointer to diminfo information */
+ hsize_t fast_dim_start, /* Local copies of fastest changing dimension info */
+ fast_dim_stride,
+ fast_dim_block,
+ fast_dim_offset;
+ size_t fast_dim_buf_off; /* Local copy of amount to move fastest dimension buffer offset */
+ size_t fast_dim_count; /* Number of blocks left in fastest changing dimension */
+ size_t tot_blk_count; /* Total number of blocks left to output */
+ size_t act_blk_count; /* Actual number of blocks to output */
+ size_t total_rows; /* Total number of entire rows to output */
+ size_t curr_rows; /* Current number of entire rows to output */
+ unsigned fast_dim; /* Rank of the fastest changing dimension for the dataspace */
+ unsigned ndims; /* Number of dimensions of dataset */
+ int temp_dim; /* Temporary rank holder */
+ hsize_t loc; /* Coordinate offset */
+ size_t curr_seq = 0; /* Current sequence being operated on */
+ size_t actual_elem; /* The actual number of elements to count */
+ size_t actual_bytes;/* The actual number of bytes to copy */
+ size_t io_left; /* The number of elements left in I/O operation */
+ size_t start_io_left; /* The initial number of elements left in I/O operation */
+ size_t elem_size; /* Size of each element iterating over */
+ unsigned u; /* Local index variable */
- FUNC_ENTER_STATIC
+ FUNC_ENTER_STATIC_NOERR
- /* Allocate a new span node */
- if(NULL == (ret_value = H5FL_MALLOC(H5S_hyper_span_t)))
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, NULL, "can't allocate hyperslab span")
+ /* Check args */
+ HDassert(iter);
+ HDassert(maxseq > 0);
+ HDassert(maxelem > 0);
+ HDassert(nseq);
+ HDassert(nelem);
+ HDassert(off);
+ HDassert(len);
- /* Copy the span's basic information */
- ret_value->low = low;
- ret_value->high = high;
- ret_value->nelem = (high - low) + 1;
- ret_value->pstride = 0;
- ret_value->down = down;
- ret_value->next = next;
+ /* Set the local copy of the diminfo pointer */
+ tdiminfo = iter->u.hyp.diminfo;
- /* Increment the reference count of the 'down span' if there is one */
- if(ret_value->down)
- ret_value->down->count++;
+ /* Check if this is a "flattened" regular hyperslab selection */
+ if(iter->u.hyp.iter_rank != 0 && iter->u.hyp.iter_rank < iter->rank) {
+ /* Set the aliases for a few important dimension ranks */
+ ndims = iter->u.hyp.iter_rank;
+
+ /* Set the local copy of the selection offset */
+ sel_off = iter->u.hyp.sel_off;
+
+ /* Set up the pointer to the size of the memory dataspace */
+ mem_size = iter->u.hyp.size;
+ } /* end if */
+ else {
+ /* Set the aliases for a few important dimension ranks */
+ ndims = iter->rank;
+
+ /* Set the local copy of the selection offset */
+ sel_off = iter->sel_off;
+
+ /* Set up the pointer to the size of the memory dataspace */
+ mem_size = iter->dims;
+ } /* end else */
+
+ /* Set up some local variables */
+ fast_dim = ndims - 1;
+ elem_size = iter->elmt_size;
+ slab = iter->u.hyp.slab;
+
+ /* Calculate the number of elements to sequence through */
+ H5_CHECK_OVERFLOW(iter->elmt_left, hsize_t, size_t);
+ io_left = MIN((size_t)iter->elmt_left, maxelem);
+
+ /* Sanity check that there aren't any "remainder" sequences in process */
+ HDassert(!((iter->u.hyp.off[fast_dim] - tdiminfo[fast_dim].start) % tdiminfo[fast_dim].stride != 0 ||
+ ((iter->u.hyp.off[fast_dim] != tdiminfo[fast_dim].start) && tdiminfo[fast_dim].count == 1)));
+
+ /* We've cleared the "remainder" of the previous fastest dimension
+ * sequence before calling this routine, so we must be at the beginning of
+ * a sequence. Use the fancy algorithm to compute the offsets and run
+ * through as many as possible, until the buffer fills up.
+ */
+
+ /* Keep the number of elements we started with */
+ start_io_left = io_left;
+
+ /* Compute the arrays to perform I/O on */
+
+ /* Copy the location of the point to get */
+ /* (Add in the selection offset) */
+ for(u = 0; u < ndims; u++)
+ offset[u] = (hsize_t)((hssize_t)iter->u.hyp.off[u] + sel_off[u]);
+
+ /* Compute the current "counts" for this location */
+ for(u = 0; u < ndims; u++) {
+ if(tdiminfo[u].count == 1) {
+ tmp_count[u] = 0;
+ tmp_block[u] = iter->u.hyp.off[u] - tdiminfo[u].start;
+ } /* end if */
+ else {
+ tmp_count[u] = (iter->u.hyp.off[u] - tdiminfo[u].start) / tdiminfo[u].stride;
+ tmp_block[u] = (iter->u.hyp.off[u] - tdiminfo[u].start) % tdiminfo[u].stride;
+ } /* end else */
+ } /* end for */
+
+ /* Compute the initial buffer offset */
+ for(u = 0, loc = 0; u < ndims; u++)
+ loc += offset[u] * slab[u];
+
+ /* Set the number of elements to write each time */
+ H5_CHECKED_ASSIGN(actual_elem, size_t, tdiminfo[fast_dim].block, hsize_t);
+
+ /* Set the number of actual bytes */
+ actual_bytes = actual_elem * elem_size;
+
+ /* Set local copies of information for the fastest changing dimension */
+ fast_dim_start = tdiminfo[fast_dim].start;
+ fast_dim_stride = tdiminfo[fast_dim].stride;
+ fast_dim_block = tdiminfo[fast_dim].block;
+ H5_CHECKED_ASSIGN(fast_dim_buf_off, size_t, slab[fast_dim] * fast_dim_stride, hsize_t);
+ fast_dim_offset = (hsize_t)((hssize_t)fast_dim_start + sel_off[fast_dim]);
+
+ /* Compute the number of blocks which would fit into the buffer */
+ H5_CHECK_OVERFLOW(io_left / fast_dim_block, hsize_t, size_t);
+ tot_blk_count = (size_t)(io_left / fast_dim_block);
+
+ /* Don't go over the maximum number of sequences allowed */
+ tot_blk_count = MIN(tot_blk_count, (maxseq - curr_seq));
+
+ /* Compute the amount to wrap at the end of each row */
+ for(u = 0; u < ndims; u++)
+ wrap[u] = (mem_size[u] - (tdiminfo[u].stride * tdiminfo[u].count)) * slab[u];
+
+ /* Compute the amount to skip between blocks */
+ for(u = 0; u < ndims; u++)
+ skip[u] = (tdiminfo[u].stride - tdiminfo[u].block) * slab[u];
+
+ /* Check if there is a partial row left (with full blocks) */
+ if(tmp_count[fast_dim] > 0) {
+ /* Get number of blocks in fastest dimension */
+ H5_CHECKED_ASSIGN(fast_dim_count, size_t, tdiminfo[fast_dim].count - tmp_count[fast_dim], hsize_t);
+
+ /* Make certain this entire row will fit into buffer */
+ fast_dim_count = MIN(fast_dim_count, tot_blk_count);
+
+ /* Number of blocks to sequence over */
+ act_blk_count = fast_dim_count;
+
+ /* Loop over all the blocks in the fastest changing dimension */
+ while(fast_dim_count > 0) {
+ /* Store the sequence information */
+ off[curr_seq] = loc;
+ len[curr_seq] = actual_bytes;
+
+ /* Increment sequence count */
+ curr_seq++;
+
+ /* Increment information to reflect block just processed */
+ loc += fast_dim_buf_off;
+
+ /* Decrement number of blocks */
+ fast_dim_count--;
+ } /* end while */
+
+ /* Decrement number of elements left */
+ io_left -= actual_elem * act_blk_count;
+
+ /* Decrement number of blocks left */
+ tot_blk_count -= act_blk_count;
+
+ /* Increment information to reflect block just processed */
+ tmp_count[fast_dim] += act_blk_count;
+
+ /* Check if we finished the entire row of blocks */
+ if(tmp_count[fast_dim] >= tdiminfo[fast_dim].count) {
+ /* Increment offset in destination buffer */
+ loc += wrap[fast_dim];
+
+ /* Increment information to reflect block just processed */
+ offset[fast_dim] = fast_dim_offset; /* reset the offset in the fastest dimension */
+ tmp_count[fast_dim] = 0;
+
+ /* Increment the offset and count for the other dimensions */
+ temp_dim = (int)fast_dim - 1;
+ while(temp_dim >= 0) {
+ /* Move to the next row in the curent dimension */
+ offset[temp_dim]++;
+ tmp_block[temp_dim]++;
+
+ /* If this block is still in the range of blocks to output for the dimension, break out of loop */
+ if(tmp_block[temp_dim] < tdiminfo[temp_dim].block)
+ break;
+ else {
+ /* Move to the next block in the current dimension */
+ offset[temp_dim] += (tdiminfo[temp_dim].stride - tdiminfo[temp_dim].block);
+ loc += skip[temp_dim];
+ tmp_block[temp_dim] = 0;
+ tmp_count[temp_dim]++;
+
+ /* If this block is still in the range of blocks to output for the dimension, break out of loop */
+ if(tmp_count[temp_dim] < tdiminfo[temp_dim].count)
+ break;
+ else {
+ offset[temp_dim] = (hsize_t)((hssize_t)tdiminfo[temp_dim].start + sel_off[temp_dim]);
+ loc += wrap[temp_dim];
+ tmp_count[temp_dim] = 0; /* reset back to the beginning of the line */
+ tmp_block[temp_dim] = 0;
+ } /* end else */
+ } /* end else */
+
+ /* Decrement dimension count */
+ temp_dim--;
+ } /* end while */
+ } /* end if */
+ else {
+ /* Update the offset in the fastest dimension */
+ offset[fast_dim] += (fast_dim_stride * act_blk_count);
+ } /* end else */
+ } /* end if */
+
+ /* Compute the number of entire rows to read in */
+ H5_CHECK_OVERFLOW(tot_blk_count / tdiminfo[fast_dim].count, hsize_t, size_t);
+ curr_rows = total_rows = (size_t)(tot_blk_count / tdiminfo[fast_dim].count);
+
+ /* Reset copy of number of blocks in fastest dimension */
+ H5_CHECKED_ASSIGN(fast_dim_count, size_t, tdiminfo[fast_dim].count, hsize_t);
+
+ /* Read in data until an entire sequence can't be written out any longer */
+ while(curr_rows > 0) {
+
+#define DUFF_GUTS \
+/* Store the sequence information */ \
+off[curr_seq] = loc; \
+len[curr_seq] = actual_bytes; \
+ \
+/* Increment sequence count */ \
+curr_seq++; \
+ \
+/* Increment information to reflect block just processed */ \
+loc += fast_dim_buf_off;
+
+#ifdef NO_DUFFS_DEVICE
+ /* Loop over all the blocks in the fastest changing dimension */
+ while(fast_dim_count > 0) {
+ DUFF_GUTS
+
+ /* Decrement number of blocks */
+ fast_dim_count--;
+ } /* end while */
+#else /* NO_DUFFS_DEVICE */
+ {
+ size_t duffs_index; /* Counting index for Duff's device */
+
+ duffs_index = (fast_dim_count + 7) / 8;
+ switch (fast_dim_count % 8) {
+ default:
+ HDassert(0 && "This Should never be executed!");
+ break;
+ case 0:
+ do
+ {
+ DUFF_GUTS
+ H5_ATTR_FALLTHROUGH
+ case 7:
+ DUFF_GUTS
+ H5_ATTR_FALLTHROUGH
+ case 6:
+ DUFF_GUTS
+ H5_ATTR_FALLTHROUGH
+ case 5:
+ DUFF_GUTS
+ H5_ATTR_FALLTHROUGH
+ case 4:
+ DUFF_GUTS
+ H5_ATTR_FALLTHROUGH
+ case 3:
+ DUFF_GUTS
+ H5_ATTR_FALLTHROUGH
+ case 2:
+ DUFF_GUTS
+ H5_ATTR_FALLTHROUGH
+ case 1:
+ DUFF_GUTS
+ } while (--duffs_index > 0);
+ } /* end switch */
+ }
+#endif /* NO_DUFFS_DEVICE */
+#undef DUFF_GUTS
+
+ /* Increment offset in destination buffer */
+ loc += wrap[fast_dim];
+
+ /* Increment the offset and count for the other dimensions */
+ temp_dim = (int)fast_dim - 1;
+ while(temp_dim >= 0) {
+ /* Move to the next row in the curent dimension */
+ offset[temp_dim]++;
+ tmp_block[temp_dim]++;
+
+ /* If this block is still in the range of blocks to output for the dimension, break out of loop */
+ if(tmp_block[temp_dim] < tdiminfo[temp_dim].block)
+ break;
+ else {
+ /* Move to the next block in the current dimension */
+ offset[temp_dim] += (tdiminfo[temp_dim].stride - tdiminfo[temp_dim].block);
+ loc += skip[temp_dim];
+ tmp_block[temp_dim] = 0;
+ tmp_count[temp_dim]++;
+
+ /* If this block is still in the range of blocks to output for the dimension, break out of loop */
+ if(tmp_count[temp_dim] < tdiminfo[temp_dim].count)
+ break;
+ else {
+ offset[temp_dim] = (hsize_t)((hssize_t)tdiminfo[temp_dim].start + sel_off[temp_dim]);
+ loc += wrap[temp_dim];
+ tmp_count[temp_dim] = 0; /* reset back to the beginning of the line */
+ tmp_block[temp_dim] = 0;
+ } /* end else */
+ } /* end else */
+
+ /* Decrement dimension count */
+ temp_dim--;
+ } /* end while */
+
+ /* Decrement the number of rows left */
+ curr_rows--;
+ } /* end while */
+
+ /* Adjust the number of blocks & elements left to transfer */
+
+ /* Decrement number of elements left */
+ H5_CHECK_OVERFLOW(actual_elem * (total_rows * tdiminfo[fast_dim].count), hsize_t, size_t);
+ io_left -= (size_t)(actual_elem * (total_rows * tdiminfo[fast_dim].count));
+
+ /* Decrement number of blocks left */
+ H5_CHECK_OVERFLOW((total_rows * tdiminfo[fast_dim].count), hsize_t, size_t);
+ tot_blk_count -= (size_t)(total_rows * tdiminfo[fast_dim].count);
+
+ /* Read in partial row of blocks */
+ if(io_left > 0 && curr_seq < maxseq) {
+ /* Get remaining number of blocks left to output */
+ fast_dim_count = tot_blk_count;
+
+ /* Loop over all the blocks in the fastest changing dimension */
+ while(fast_dim_count > 0) {
+ /* Store the sequence information */
+ off[curr_seq] = loc;
+ len[curr_seq] = actual_bytes;
+
+ /* Increment sequence count */
+ curr_seq++;
+
+ /* Increment information to reflect block just processed */
+ loc += fast_dim_buf_off;
+
+ /* Decrement number of blocks */
+ fast_dim_count--;
+ } /* end while */
+
+ /* Decrement number of elements left */
+ io_left -= actual_elem * tot_blk_count;
+
+ /* Increment information to reflect block just processed */
+ offset[fast_dim] += (fast_dim_stride * tot_blk_count); /* move the offset in the fastest dimension */
+
+ /* Handle any leftover, partial blocks in this row */
+ if(io_left > 0 && curr_seq < maxseq) {
+ actual_elem = io_left;
+ actual_bytes = actual_elem * elem_size;
+
+ /* Store the sequence information */
+ off[curr_seq] = loc;
+ len[curr_seq] = actual_bytes;
+
+ /* Increment sequence count */
+ curr_seq++;
+
+ /* Decrement the number of elements left */
+ io_left -= actual_elem;
+
+ /* Increment buffer correctly */
+ offset[fast_dim] += actual_elem;
+ } /* end if */
+
+ /* don't bother checking slower dimensions */
+ HDassert(io_left == 0 || curr_seq == maxseq);
+ } /* end if */
+
+ /* Update the iterator */
+
+ /* Update the iterator with the location we stopped */
+ /* (Subtract out the selection offset) */
+ for(u = 0; u < ndims; u++)
+ iter->u.hyp.off[u] = (hsize_t)((hssize_t)offset[u] - sel_off[u]);
+
+ /* Decrement the number of elements left in selection */
+ iter->elmt_left -= (start_io_left - io_left);
+
+ /* Increment the number of sequences generated */
+ *nseq += curr_seq;
+
+ /* Increment the number of elements used */
+ *nelem += start_io_left - io_left;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5S__hyper_iter_get_seq_list_opt() */
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5S__hyper_new_span() */
-
/*--------------------------------------------------------------------------
NAME
- H5S__hyper_span_precompute_helper
+ H5S__hyper_iter_get_seq_list_single
PURPOSE
- Helper routine to precompute the nelem and pstrides in bytes.
+ Create a list of offsets & lengths for a selection
USAGE
- void H5S__hyper_span_precompute_helper(span_info, elmt_size)
- H5S_hyper_span_info_t *span_info; IN/OUT: Span tree to work on
- size_t elmt_size; IN: element size to work with
+ herr_t H5S__hyper_iter_get_seq_list_single(flags, iter, maxseq, maxelem, nseq, nelem, off, len)
+ unsigned flags; IN: Flags for extra information about operation
+ H5S_sel_iter_t *iter; IN/OUT: Selection iterator describing last
+ position of interest in selection.
+ size_t maxseq; IN: Maximum number of sequences to generate
+ size_t maxelem; IN: Maximum number of elements to include in the
+ generated sequences
+ size_t *nseq; OUT: Actual number of sequences generated
+ size_t *nelem; OUT: Actual number of elements in sequences generated
+ hsize_t *off; OUT: Array of offsets
+ size_t *len; OUT: Array of lengths
RETURNS
- None
+ Non-negative on success/Negative on failure.
DESCRIPTION
- Change the nelem and pstride values in the span tree from elements to
- bytes using the elmt_size parameter.
+ Use the selection in the dataspace to generate a list of byte offsets and
+ lengths for the region(s) selected. Start/Restart from the position in the
+ ITER parameter. The number of sequences generated is limited by the MAXSEQ
+ parameter and the number of sequences actually generated is stored in the
+ NSEQ parameter.
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-static void
-H5S__hyper_span_precompute_helper(H5S_hyper_span_info_t *spans, size_t elmt_size)
+static herr_t
+H5S__hyper_iter_get_seq_list_single(H5S_sel_iter_t *iter, size_t maxseq, size_t maxelem,
+ size_t *nseq, size_t *nelem, hsize_t *off, size_t *len)
{
+ const H5S_hyper_dim_t *tdiminfo; /* Temporary pointer to diminfo information */
+ const hssize_t *sel_off; /* Selection offset in dataspace */
+ hsize_t *mem_size; /* Size of the source buffer */
+ hsize_t base_offset[H5S_MAX_RANK]; /* Base coordinate offset in dataspace */
+ hsize_t offset[H5S_MAX_RANK]; /* Coordinate offset in dataspace */
+ hsize_t *slab; /* Hyperslab size */
+ hsize_t fast_dim_block; /* Local copies of fastest changing dimension info */
+ hsize_t loc; /* Coordinate offset */
+ size_t tot_blk_count; /* Total number of blocks left to output */
+ size_t elem_size; /* Size of each element iterating over */
+ size_t io_left; /* The number of elements left in I/O operation */
+ size_t actual_elem; /* The actual number of elements to count */
+ unsigned ndims; /* Number of dimensions of dataset */
+ unsigned fast_dim; /* Rank of the fastest changing dimension for the dataspace */
+ unsigned skip_dim; /* Rank of the dimension to skip along */
+ unsigned u; /* Local index variable */
+
FUNC_ENTER_STATIC_NOERR
- /* Sanity checks */
- HDassert(spans);
- HDassert(spans->scratch == (H5S_hyper_span_info_t *)~((size_t)NULL) ||
- spans->scratch == NULL);
+ /* Check args */
+ HDassert(iter);
+ HDassert(maxseq > 0);
+ HDassert(maxelem > 0);
+ HDassert(nseq);
+ HDassert(nelem);
+ HDassert(off);
+ HDassert(len);
- /* Check if we've already set this down span tree */
- if(spans->scratch != (H5S_hyper_span_info_t *)~((size_t)NULL)) {
- H5S_hyper_span_t *span; /* Hyperslab span */
+ /* Set a local copy of the diminfo pointer */
+ tdiminfo = iter->u.hyp.diminfo;
- /* Set the tree's scratch pointer */
- spans->scratch = (H5S_hyper_span_info_t *)~((size_t)NULL);
+ /* Check if this is a "flattened" regular hyperslab selection */
+ if(iter->u.hyp.iter_rank != 0 && iter->u.hyp.iter_rank < iter->rank) {
+ /* Set the aliases for a few important dimension ranks */
+ ndims = iter->u.hyp.iter_rank;
- /* Set the scratch pointers in all the nodes */
- span = spans->head;
+ /* Set the local copy of the selection offset */
+ sel_off = iter->u.hyp.sel_off;
- /* Loop over all the spans for this down span tree */
- while(span != NULL) {
- /* If there are down spans, precompute their values also */
- if(span->down != NULL)
- H5S__hyper_span_precompute_helper(span->down, elmt_size);
+ /* Set up the pointer to the size of the memory dataspace */
+ mem_size = iter->u.hyp.size;
+ } /* end if */
+ else {
+ /* Set the aliases for a few important dimension ranks */
+ ndims = iter->rank;
- /* Change the nelem & pstride values into bytes */
- span->nelem *= elmt_size;
- span->pstride *= elmt_size;
+ /* Set the local copy of the selection offset */
+ sel_off = iter->sel_off;
- /* Advance to next span */
- span = span->next;
- } /* end while */
+ /* Set up the pointer to the size of the memory dataspace */
+ mem_size = iter->dims;
+ } /* end else */
+
+ /* Set up some local variables */
+ fast_dim = ndims - 1;
+ elem_size = iter->elmt_size;
+ slab = iter->u.hyp.slab;
+
+ /* Copy the base location of the block */
+ /* (Add in the selection offset) */
+ for(u = 0; u < ndims; u++)
+ base_offset[u] = (hsize_t)((hssize_t)tdiminfo[u].start + sel_off[u]);
+
+ /* Copy the location of the point to get */
+ /* (Add in the selection offset) */
+ for(u = 0; u < ndims; u++)
+ offset[u] = (hsize_t)((hssize_t)iter->u.hyp.off[u] + sel_off[u]);
+
+ /* Compute the initial buffer offset */
+ for(u = 0, loc = 0; u < ndims; u++)
+ loc += offset[u] * slab[u];
+
+ /* Set local copies of information for the fastest changing dimension */
+ fast_dim_block = tdiminfo[fast_dim].block;
+
+ /* Calculate the number of elements to sequence through */
+ H5_CHECK_OVERFLOW(iter->elmt_left, hsize_t, size_t);
+ io_left = MIN((size_t)iter->elmt_left, maxelem);
+
+ /* Compute the number of blocks which would fit into the buffer */
+ H5_CHECK_OVERFLOW(io_left / fast_dim_block, hsize_t, size_t);
+ tot_blk_count = (size_t)(io_left / fast_dim_block);
+
+ /* Don't go over the maximum number of sequences allowed */
+ tot_blk_count = MIN(tot_blk_count, maxseq);
+
+ /* Set the number of elements to write each time */
+ H5_CHECKED_ASSIGN(actual_elem, size_t, fast_dim_block, hsize_t);
+
+ /* Check for blocks to operate on */
+ if(tot_blk_count > 0) {
+ size_t actual_bytes; /* The actual number of bytes to copy */
+
+ /* Set the number of actual bytes */
+ actual_bytes = actual_elem * elem_size;
+
+ /* Check for 1-dim selection */
+ if(0 == fast_dim) {
+ /* Sanity checks */
+ HDassert(1 == tot_blk_count);
+ HDassert(io_left == actual_elem);
+
+ /* Store the sequence information */
+ *off++ = loc;
+ *len++ = actual_bytes;
+ } /* end if */
+ else {
+ hsize_t skip_slab; /* Temporary copy of slab[fast_dim - 1] */
+ size_t blk_count; /* Total number of blocks left to output */
+ int i; /* Local index variable */
+
+ /* Find first dimension w/block >1 */
+ skip_dim = fast_dim;
+ for(i = (int)(fast_dim - 1); i >= 0; i--)
+ if(tdiminfo[i].block > 1) {
+ skip_dim = (unsigned)i;
+ break;
+ } /* end if */
+ skip_slab = slab[skip_dim];
+
+ /* Check for being able to use fast algorithm for 1-D */
+ if(0 == skip_dim) {
+ /* Create sequences until an entire row can't be used */
+ blk_count = tot_blk_count;
+ while(blk_count > 0) {
+ /* Store the sequence information */
+ *off++ = loc;
+ *len++ = actual_bytes;
+
+ /* Increment offset in destination buffer */
+ loc += skip_slab;
+
+ /* Decrement block count */
+ blk_count--;
+ } /* end while */
+
+ /* Move to the next location */
+ offset[skip_dim] += tot_blk_count;
+ } /* end if */
+ else {
+ hsize_t tmp_block[H5S_MAX_RANK]; /* Temporary block offset */
+ hsize_t skip[H5S_MAX_RANK]; /* Bytes to skip between blocks */
+ int temp_dim; /* Temporary rank holder */
+
+ /* Set the starting block location */
+ for(u = 0; u < ndims; u++)
+ tmp_block[u] = iter->u.hyp.off[u] - tdiminfo[u].start;
+
+ /* Compute the amount to skip between sequences */
+ for(u = 0; u < ndims; u++)
+ skip[u] = (mem_size[u] - tdiminfo[u].block) * slab[u];
+
+ /* Create sequences until an entire row can't be used */
+ blk_count = tot_blk_count;
+ while(blk_count > 0) {
+ /* Store the sequence information */
+ *off++ = loc;
+ *len++ = actual_bytes;
+
+ /* Set temporary dimension for advancing offsets */
+ temp_dim = (int)skip_dim;
+
+ /* Increment offset in destination buffer */
+ loc += skip_slab;
+
+ /* Increment the offset and count for the other dimensions */
+ while(temp_dim >= 0) {
+ /* Move to the next row in the curent dimension */
+ offset[temp_dim]++;
+ tmp_block[temp_dim]++;
+
+ /* If this block is still in the range of blocks to output for the dimension, break out of loop */
+ if(tmp_block[temp_dim] < tdiminfo[temp_dim].block)
+ break;
+ else {
+ offset[temp_dim] = base_offset[temp_dim];
+ loc += skip[temp_dim];
+ tmp_block[temp_dim] = 0;
+ } /* end else */
+
+ /* Decrement dimension count */
+ temp_dim--;
+ } /* end while */
+
+ /* Decrement block count */
+ blk_count--;
+ } /* end while */
+ } /* end else */
+ } /* end else */
+
+ /* Update the iterator, if there were any blocks used */
+
+ /* Decrement the number of elements left in selection */
+ iter->elmt_left -= tot_blk_count * actual_elem;
+
+ /* Check if there are elements left in iterator */
+ if(iter->elmt_left > 0) {
+ /* Update the iterator with the location we stopped */
+ /* (Subtract out the selection offset) */
+ for(u = 0; u < ndims; u++)
+ iter->u.hyp.off[u] = (hsize_t)((hssize_t)offset[u] - sel_off[u]);
+ } /* end if */
+
+ /* Increment the number of sequences generated */
+ *nseq += tot_blk_count;
+
+ /* Increment the number of elements used */
+ *nelem += tot_blk_count * actual_elem;
} /* end if */
- FUNC_LEAVE_NOAPI_VOID
-} /* end H5S__hyper_span_precompute_helper() */
+ /* Check for partial block, with room for another sequence */
+ if(io_left > (tot_blk_count * actual_elem) && tot_blk_count < maxseq) {
+ size_t elmt_remainder; /* Elements remaining */
+
+ /* Compute elements left */
+ elmt_remainder = io_left - (tot_blk_count * actual_elem);
+ HDassert(elmt_remainder < fast_dim_block);
+ HDassert(elmt_remainder > 0);
+
+ /* Store the sequence information */
+ *off++ = loc;
+ *len++ = elmt_remainder * elem_size;
+
+ /* Update the iterator with the location we stopped */
+ iter->u.hyp.off[fast_dim] += (hsize_t)elmt_remainder;
+
+ /* Decrement the number of elements left in selection */
+ iter->elmt_left -= elmt_remainder;
+
+ /* Increment the number of sequences generated */
+ (*nseq)++;
+
+ /* Increment the number of elements used */
+ *nelem += elmt_remainder;
+ } /* end if */
+
+ /* Sanity check */
+ HDassert(*nseq > 0);
+ HDassert(*nelem > 0);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5S__hyper_iter_get_seq_list_single() */
+
-
/*--------------------------------------------------------------------------
NAME
- H5S__hyper_span_precompute
+ H5S__hyper_iter_get_seq_list
PURPOSE
- Precompute the nelem and pstrides in bytes.
+ Create a list of offsets & lengths for a selection
USAGE
- herr_t H5S__hyper_span_precompute(span_info, elmt_size)
- H5S_hyper_span_info_t *span_info; IN/OUT: Span tree to work on
- size_t elmt_size; IN: element size to work with
+ herr_t H5S__hyper_iter_get_seq_list(iter,maxseq,maxelem,nseq,nelem,off,len)
+ H5S_t *space; IN: Dataspace containing selection to use.
+ unsigned flags; IN: Flags for extra information about operation
+ H5S_sel_iter_t *iter; IN/OUT: Selection iterator describing last
+ position of interest in selection.
+ size_t maxseq; IN: Maximum number of sequences to generate
+ size_t maxelem; IN: Maximum number of elements to include in the
+ generated sequences
+ size_t *nseq; OUT: Actual number of sequences generated
+ size_t *nelem; OUT: Actual number of elements in sequences generated
+ hsize_t *off; OUT: Array of offsets (in bytes)
+ size_t *len; OUT: Array of lengths (in bytes)
RETURNS
- Non-negative on success, negative on failure
+ Non-negative on success/Negative on failure.
DESCRIPTION
- Change the nelem and pstride values in the span tree from elements to
- bytes using the elmt_size parameter.
+ Use the selection in the dataspace to generate a list of byte offsets and
+ lengths for the region(s) selected. Start/Restart from the position in the
+ ITER parameter. The number of sequences generated is limited by the MAXSEQ
+ parameter and the number of sequences actually generated is stored in the
+ NSEQ parameter.
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S__hyper_span_precompute(H5S_hyper_span_info_t *spans, size_t elmt_size)
+H5S__hyper_iter_get_seq_list(H5S_sel_iter_t *iter, size_t maxseq,
+ size_t maxelem, size_t *nseq, size_t *nelem, hsize_t *off, size_t *len)
{
+ herr_t ret_value = FAIL; /* return value */
+
FUNC_ENTER_STATIC_NOERR
- HDassert(spans);
+ /* Check args */
+ HDassert(iter);
+ HDassert(iter->elmt_left > 0);
+ HDassert(maxseq > 0);
+ HDassert(maxelem > 0);
+ HDassert(nseq);
+ HDassert(nelem);
+ HDassert(off);
+ HDassert(len);
- /* Call the helper routine to actually do the work */
- H5S__hyper_span_precompute_helper(spans, elmt_size);
+ /* Check for the special case of just one H5Sselect_hyperslab call made */
+ if(iter->u.hyp.diminfo_valid) {
+ const H5S_hyper_dim_t *tdiminfo; /* Temporary pointer to diminfo information */
+ const hssize_t *sel_off; /* Selection offset in dataspace */
+ unsigned ndims; /* Number of dimensions of dataset */
+ unsigned fast_dim; /* Rank of the fastest changing dimension for the dataspace */
+ hbool_t single_block; /* Whether the selection is a single block */
+ unsigned u; /* Local index variable */
- /* Reset the scratch pointers for the next routine which needs them */
- H5S__hyper_span_scratch(spans);
+ /* Set a local copy of the diminfo pointer */
+ tdiminfo = iter->u.hyp.diminfo;
+
+ /* Check if this is a "flattened" regular hyperslab selection */
+ if(iter->u.hyp.iter_rank != 0 && iter->u.hyp.iter_rank < iter->rank) {
+ /* Set the aliases for a few important dimension ranks */
+ ndims = iter->u.hyp.iter_rank;
+
+ /* Set the local copy of the selection offset */
+ sel_off = iter->u.hyp.sel_off;
+ } /* end if */
+ else {
+ /* Set the aliases for a few important dimension ranks */
+ ndims = iter->rank;
+
+ /* Set the local copy of the selection offset */
+ sel_off = iter->sel_off;
+ } /* end else */
+ fast_dim = ndims - 1;
+
+ /* Check if we stopped in the middle of a sequence of elements */
+ if((iter->u.hyp.off[fast_dim] - tdiminfo[fast_dim].start) % tdiminfo[fast_dim].stride != 0 ||
+ ((iter->u.hyp.off[fast_dim] != tdiminfo[fast_dim].start) && tdiminfo[fast_dim].count == 1)) {
+ hsize_t *slab; /* Hyperslab size */
+ hsize_t loc; /* Coordinate offset */
+ size_t leftover; /* The number of elements left over from the last sequence */
+ size_t actual_elem; /* The actual number of elements to count */
+ size_t elem_size; /* Size of each element iterating over */
+
+ /* Calculate the number of elements left in the sequence */
+ if(tdiminfo[fast_dim].count == 1) {
+ H5_CHECKED_ASSIGN(leftover, size_t, tdiminfo[fast_dim].block - (iter->u.hyp.off[fast_dim] - tdiminfo[fast_dim].start), hsize_t);
+ } /* end if */
+ else {
+ H5_CHECKED_ASSIGN(leftover, size_t, tdiminfo[fast_dim].block - ((iter->u.hyp.off[fast_dim] - tdiminfo[fast_dim].start) % tdiminfo[fast_dim].stride), hsize_t);
+ } /* end else */
+
+ /* Make certain that we don't write too many */
+ actual_elem = MIN3(leftover, (size_t)iter->elmt_left, maxelem);
+
+ /* Set up some local variables */
+ elem_size = iter->elmt_size;
+ slab = iter->u.hyp.slab;
+
+ /* Compute the initial buffer offset */
+ for(u = 0, loc = 0; u < ndims; u++)
+ loc += ((hsize_t)((hssize_t)iter->u.hyp.off[u] + sel_off[u])) * slab[u];
+
+ /* Add a new sequence */
+ off[0] = loc;
+ H5_CHECKED_ASSIGN(len[0], size_t, actual_elem * elem_size, hsize_t);
+
+ /* Increment sequence array locations */
+ off++;
+ len++;
+
+ /* Advance the hyperslab iterator */
+ H5S__hyper_iter_next(iter, actual_elem);
+
+ /* Decrement the number of elements left in selection */
+ iter->elmt_left -= actual_elem;
+
+ /* Decrement element/sequence limits */
+ maxelem -= actual_elem;
+ maxseq--;
+
+ /* Set the number of sequences generated and elements used */
+ *nseq = 1;
+ *nelem = actual_elem;
+
+ /* Check for using up all the sequences/elements */
+ if(0 == iter->elmt_left || 0 == maxelem || 0 == maxseq)
+ return(SUCCEED);
+ } /* end if */
+ else {
+ /* Reset the number of sequences generated and elements used */
+ *nseq = 0;
+ *nelem = 0;
+ } /* end else */
+
+ /* Check for a single block selected */
+ single_block = TRUE;
+ for(u = 0; u < ndims; u++)
+ if(1 != tdiminfo[u].count) {
+ single_block = FALSE;
+ break;
+ } /* end if */
+
+ /* Check for single block selection */
+ if(single_block)
+ /* Use single-block optimized call to generate sequence list */
+ ret_value = H5S__hyper_iter_get_seq_list_single(iter, maxseq, maxelem, nseq, nelem, off, len);
+ else
+ /* Use optimized call to generate sequence list */
+ ret_value = H5S__hyper_iter_get_seq_list_opt(iter, maxseq, maxelem, nseq, nelem, off, len);
+ } /* end if */
+ else
+ /* Call the general sequence generator routine */
+ ret_value = H5S__hyper_iter_get_seq_list_gen(iter, maxseq, maxelem, nseq, nelem, off, len);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S__hyper_iter_get_seq_list() */
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5S__hyper_span_precompute() */
-
/*--------------------------------------------------------------------------
NAME
- H5S__hyper_span_scratch
+ H5S__hyper_iter_release
PURPOSE
- Reset the scratch pointers on hyperslab span trees
+ Release hyperslab selection iterator information for a dataspace
USAGE
- void H5S__hyper_span_scratch(span_info)
- H5S_hyper_span_info_t *span_info; IN: Span tree to reset
+ herr_t H5S__hyper_iter_release(iter)
+ H5S_sel_iter_t *iter; IN: Pointer to selection iterator
RETURNS
- <none>
+ Non-negative on success/Negative on failure
DESCRIPTION
- Reset the scratch pointers on a hyperslab span tree to NULL.
+ Releases all information for a dataspace hyperslab selection iterator
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-static void
-H5S__hyper_span_scratch(H5S_hyper_span_info_t *spans)
+static herr_t
+H5S__hyper_iter_release(H5S_sel_iter_t *iter)
{
FUNC_ENTER_STATIC_NOERR
- HDassert(spans);
+ /* Check args */
+ HDassert(iter);
- /* Check if we've already set this down span tree */
- if(spans->scratch != NULL) {
- H5S_hyper_span_t *span; /* Hyperslab span */
+ /* Free the copy of the hyperslab selection span tree */
+ if(iter->u.hyp.spans != NULL)
+ H5S__hyper_free_span_info(iter->u.hyp.spans);
- /* Reset the tree's scratch pointer */
- spans->scratch = NULL;
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5S__hyper_iter_release() */
- /* Set the scratch pointers in all the nodes */
- span = spans->head;
- while(span != NULL) {
- /* If there are down spans, set their scratch value also */
- if(span->down != NULL)
- H5S__hyper_span_scratch(span->down);
- /* Advance to next span */
- span = span->next;
- } /* end while */
- } /* end if */
+/*--------------------------------------------------------------------------
+ NAME
+ H5S__hyper_new_span
+ PURPOSE
+ Make a new hyperslab span node
+ USAGE
+ H5S_hyper_span_t *H5S__hyper_new_span(low, high, down, next)
+ hsize_t low, high; IN: Low and high bounds for new span node
+ H5S_hyper_span_info_t *down; IN: Down span tree for new node
+ H5S_hyper_span_t *next; IN: Next span for new node
+ RETURNS
+ Pointer to new span node on success, NULL on failure
+ DESCRIPTION
+ Allocate and initialize a new hyperslab span node, filling in the low &
+ high bounds, the down span and next span pointers also. Increment the
+ reference count of the 'down span' if applicable.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static H5S_hyper_span_t *
+H5S__hyper_new_span(hsize_t low, hsize_t high, H5S_hyper_span_info_t *down,
+ H5S_hyper_span_t *next)
+{
+ H5S_hyper_span_t *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Allocate a new span node */
+ if(NULL == (ret_value = H5FL_MALLOC(H5S_hyper_span_t)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, NULL, "can't allocate hyperslab span")
+
+ /* Copy the span's basic information */
+ ret_value->low = low;
+ ret_value->high = high;
+ ret_value->down = down;
+ ret_value->next = next;
+
+ /* Increment the reference count of the 'down span' if there is one */
+ if(ret_value->down)
+ ret_value->down->count++;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S__hyper_new_span() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S__hyper_new_span_info
+ PURPOSE
+ Make a new hyperslab span info node
+ USAGE
+ H5S_hyper_span_info_t *H5S__hyper_new_span_info(rank)
+ unsigned rank; IN: Rank of span info, in selection
+ RETURNS
+ Pointer to new span node info on success, NULL on failure
+ DESCRIPTION
+ Allocate and initialize a new hyperslab span info node of a given rank,
+ setting up the low & high bound array pointers.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ Note that this uses the C99 "flexible array member" feature.
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static H5S_hyper_span_info_t *
+H5S__hyper_new_span_info(unsigned rank)
+{
+ H5S_hyper_span_info_t *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity check */
+ HDassert(rank > 0);
+ HDassert(rank <= H5S_MAX_RANK);
+
+ /* Allocate a new span info node */
+ if(NULL == (ret_value = (H5S_hyper_span_info_t *)H5FL_ARR_CALLOC(hbounds_t, rank * 2)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, NULL, "can't allocate hyperslab span info")
+
+ /* Set low & high bound pointers into the 'bounds' array */
+ ret_value->low_bounds = ret_value->bounds;
+ ret_value->high_bounds = &ret_value->bounds[rank];
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S__hyper_new_span_info() */
- FUNC_LEAVE_NOAPI_VOID
-} /* end H5S__hyper_span_scratch() */
-
/*--------------------------------------------------------------------------
NAME
H5S__hyper_copy_span_helper
PURPOSE
Helper routine to copy a hyperslab span tree
USAGE
- H5S_hyper_span_info_t * H5S__hyper_copy_span_helper(spans)
- H5S_hyper_span_info_t *spans; IN: Span tree to copy
+ H5S_hyper_span_info_t * H5S__hyper_copy_span_helper(spans, rank)
+ H5S_hyper_span_info_t *spans; IN: Span tree to copy
+ unsigned rank; IN: Rank of span tree
+ uint64_t op_gen; IN: Operation generation
RETURNS
Pointer to the copied span tree on success, NULL on failure
DESCRIPTION
@@ -1307,7 +2866,8 @@ H5S__hyper_span_scratch(H5S_hyper_span_info_t *spans)
REVISION LOG
--------------------------------------------------------------------------*/
static H5S_hyper_span_info_t *
-H5S__hyper_copy_span_helper(H5S_hyper_span_info_t *spans)
+H5S__hyper_copy_span_helper(H5S_hyper_span_info_t *spans, unsigned rank,
+ uint64_t op_gen)
{
H5S_hyper_span_t *span; /* Hyperslab span */
H5S_hyper_span_t *new_span; /* Temporary hyperslab span */
@@ -1319,26 +2879,30 @@ H5S__hyper_copy_span_helper(H5S_hyper_span_info_t *spans)
/* Sanity checks */
HDassert(spans);
- HDassert(spans->scratch != (H5S_hyper_span_info_t *)~((size_t)NULL));
/* Check if the span tree was already copied */
- if(spans->scratch != NULL) {
+ if(spans->op_gen == op_gen) {
/* Just return the value of the already copied span tree */
- ret_value = spans->scratch;
+ ret_value = spans->u.copied;
/* Increment the reference count of the span tree */
ret_value->count++;
} /* end if */
else {
/* Allocate a new span_info node */
- if(NULL == (ret_value = H5FL_CALLOC(H5S_hyper_span_info_t)))
+ if(NULL == (ret_value = H5S__hyper_new_span_info(rank)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, NULL, "can't allocate hyperslab span info")
- /* Copy the span_info information */
+ /* Set the non-zero span_info information */
+ H5MM_memcpy(ret_value->low_bounds, spans->low_bounds, rank * sizeof(hsize_t));
+ H5MM_memcpy(ret_value->high_bounds, spans->high_bounds, rank * sizeof(hsize_t));
ret_value->count = 1;
- /* Set the scratch pointer in the node being copied to the newly allocated node */
- spans->scratch = ret_value;
+ /* Set the operation generation for the span info, to avoid future copies */
+ spans->op_gen = op_gen;
+
+ /* Set the 'copied' pointer in the node being copied to the newly allocated node */
+ spans->u.copied = ret_value;
/* Copy over the nodes in the span list */
span = spans->head;
@@ -1354,12 +2918,9 @@ H5S__hyper_copy_span_helper(H5S_hyper_span_info_t *spans)
else
prev_span->next = new_span;
- /* Copy the pstride */
- new_span->pstride = span->pstride;
-
/* Recurse to copy the 'down' spans, if there are any */
if(span->down != NULL) {
- if(NULL == (new_down = H5S__hyper_copy_span_helper(span->down)))
+ if(NULL == (new_down = H5S__hyper_copy_span_helper(span->down, rank - 1, op_gen)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, NULL, "can't copy hyperslab spans")
new_span->down = new_down;
} /* end if */
@@ -1370,23 +2931,27 @@ H5S__hyper_copy_span_helper(H5S_hyper_span_info_t *spans)
/* Advance to next span */
span = span->next;
} /* end while */
+
+ /* Retain a pointer to the last span */
+ ret_value->tail = prev_span;
} /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S__hyper_copy_span_helper() */
-
+
/*--------------------------------------------------------------------------
NAME
H5S__hyper_copy_span
PURPOSE
Copy a hyperslab span tree
USAGE
- H5S_hyper_span_info_t * H5S__hyper_copy_span(span_info)
- H5S_hyper_span_info_t *span_info; IN: Span tree to copy
+ H5S_hyper_span_info_t * H5S__hyper_copy_span(span_info, rank)
+ H5S_hyper_span_info_t *span_info; IN: Span tree to copy
+ unsigned rank; IN: Rank of span tree
RETURNS
- Non-negative on success, negative on failure
+ Pointer to the copied span tree on success, NULL on failure
DESCRIPTION
Copy a hyperslab span tree, using reference counting as appropriate.
(Which means that just the nodes in the top span tree are duplicated and
@@ -1397,67 +2962,73 @@ done:
REVISION LOG
--------------------------------------------------------------------------*/
static H5S_hyper_span_info_t *
-H5S__hyper_copy_span(H5S_hyper_span_info_t *spans)
+H5S__hyper_copy_span(H5S_hyper_span_info_t *spans, unsigned rank)
{
+ uint64_t op_gen; /* Operation generation value */
H5S_hyper_span_info_t *ret_value = NULL; /* Return value */
FUNC_ENTER_STATIC
+ /* Sanity check */
HDassert(spans);
+ /* Acquire an operation generation value for this operation */
+ op_gen = H5S__hyper_get_op_gen();
+
/* Copy the hyperslab span tree */
- if(NULL == (ret_value = H5S__hyper_copy_span_helper(spans)))
+ if(NULL == (ret_value = H5S__hyper_copy_span_helper(spans, rank, op_gen)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, NULL, "can't copy hyperslab span tree")
- /* Reset the scratch pointers for the next routine which needs them */
- H5S__hyper_span_scratch(spans);
-
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S__hyper_copy_span() */
-
+
/*--------------------------------------------------------------------------
NAME
H5S__hyper_cmp_spans
PURPOSE
- Check if two hyperslab slabs are the same
+ Check if two hyperslab span trees are the same
USAGE
hbool_t H5S__hyper_cmp_spans(span1, span2)
- H5S_hyper_span_t *span1; IN: First span tree to compare
- H5S_hyper_span_t *span2; IN: Second span tree to compare
+ H5S_hyper_span_info_t *span_info1; IN: First span tree to compare
+ H5S_hyper_span_info_t *span_info2; IN: Second span tree to compare
RETURNS
TRUE (1) or FALSE (0) on success, can't fail
DESCRIPTION
- Compare two hyperslab slabs to determine if they refer to the same
- selection. If span1 & span2 are both NULL, that counts as equal
+ Compare two hyperslab span trees to determine if they refer to the same
+ selection. If span1 & span2 are both NULL, that counts as equal.
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-static hbool_t
-H5S__hyper_cmp_spans(const H5S_hyper_span_info_t *span_info1, const H5S_hyper_span_info_t *span_info2)
+static H5_ATTR_PURE hbool_t
+H5S__hyper_cmp_spans(const H5S_hyper_span_info_t *span_info1,
+ const H5S_hyper_span_info_t *span_info2)
{
- hbool_t ret_value = FALSE; /* Return value */
+ hbool_t ret_value = TRUE; /* Return value */
FUNC_ENTER_STATIC_NOERR
- /* Check for redundant comparison */
- if(span_info1 == span_info2)
- ret_value = TRUE;
- else {
- const H5S_hyper_span_t *span1;
- const H5S_hyper_span_t *span2;
-
- /* Check for both spans being NULL */
- if(span_info1 == NULL && span_info2 == NULL)
- ret_value = TRUE;
+ /* Check for redundant comparison (or both spans being NULL) */
+ if(span_info1 != span_info2) {
+ /* Check for one span being NULL */
+ if(span_info1 == NULL || span_info2 == NULL)
+ HGOTO_DONE(FALSE)
else {
- /* Check for one span being NULL */
- if(span_info1 == NULL || span_info2 == NULL)
- ret_value = FALSE;
+ /* Compare low & high bounds for this span list */
+ /* (Could compare lower dimensions also, but not certain if
+ * that's worth it. - QAK, 2019/01/23)
+ */
+ if(span_info1->low_bounds[0] != span_info2->low_bounds[0])
+ HGOTO_DONE(FALSE)
+ else if(span_info1->high_bounds[0] != span_info2->high_bounds[0])
+ HGOTO_DONE(FALSE)
else {
+ const H5S_hyper_span_t *span1;
+ const H5S_hyper_span_t *span2;
+
/* Get the pointers to the actual lists of spans */
span1 = span_info1->head;
span2 = span_info2->head;
@@ -1469,28 +3040,20 @@ H5S__hyper_cmp_spans(const H5S_hyper_span_info_t *span_info1, const H5S_hyper_sp
/* infinite loop which must be broken out of */
while(1) {
/* Check for both spans being NULL */
- if(span1 == NULL && span2 == NULL) {
- ret_value = TRUE;
- break;
- } /* end if */
+ if(span1 == NULL && span2 == NULL)
+ HGOTO_DONE(TRUE)
else {
/* Check for one span being NULL */
- if(span1 == NULL || span2 == NULL) {
- ret_value = FALSE;
- break;
- } /* end if */
+ if(span1 == NULL || span2 == NULL)
+ HGOTO_DONE(FALSE)
else {
/* Check if the actual low & high span information is the same */
- if(span1->low != span2->low || span1->high != span2->high) {
- ret_value = FALSE;
- break;
- } /* end if */
+ if(span1->low != span2->low || span1->high != span2->high)
+ HGOTO_DONE(FALSE)
else {
- if(span1->down != NULL || span2 != NULL) {
- if(!H5S__hyper_cmp_spans(span1->down, span2->down)) {
- ret_value = FALSE;
- break;
- } /* end if */
+ if(span1->down != NULL || span2->down != NULL) {
+ if(!H5S__hyper_cmp_spans(span1->down, span2->down))
+ HGOTO_DONE(FALSE)
else {
/* Keep going... */
} /* end else */
@@ -1508,22 +3071,25 @@ H5S__hyper_cmp_spans(const H5S_hyper_span_info_t *span_info1, const H5S_hyper_sp
} /* end while */
} /* end else */
} /* end else */
- } /* end else */
+ } /* end if */
+ /* Fall through, with default return value of 'TRUE' if spans were already visited */
+
+done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S__hyper_cmp_spans() */
-
+
/*--------------------------------------------------------------------------
NAME
H5S__hyper_free_span_info
PURPOSE
Free a hyperslab span info node
USAGE
- herr_t H5S__hyper_free_span_info(span_info)
+ void H5S__hyper_free_span_info(span_info)
H5S_hyper_span_info_t *span_info; IN: Span info node to free
RETURNS
- Non-negative on success, negative on failure
+ None
DESCRIPTION
Free a hyperslab span info node, along with all the span nodes and the
'down spans' from the nodes, if reducing their reference count to zero
@@ -1533,14 +3099,12 @@ H5S__hyper_cmp_spans(const H5S_hyper_span_info_t *span_info1, const H5S_hyper_sp
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-static herr_t
+static void
H5S__hyper_free_span_info(H5S_hyper_span_info_t *span_info)
{
- H5S_hyper_span_t *span, *next_span;
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_STATIC
+ FUNC_ENTER_STATIC_NOERR
+ /* Sanity check */
HDassert(span_info);
/* Decrement the span tree's reference count */
@@ -1548,35 +3112,41 @@ H5S__hyper_free_span_info(H5S_hyper_span_info_t *span_info)
/* Free the span tree if the reference count drops to zero */
if(span_info->count == 0) {
+ H5S_hyper_span_t *span; /* Pointer to spans to iterate over */
/* Work through the list of spans pointed to by this 'info' node */
span = span_info->head;
while(span != NULL) {
+ H5S_hyper_span_t *next_span; /* Pointer to next span to iterate over */
+
+ /* Keep a pointer to the next span */
next_span = span->next;
- if(H5S__hyper_free_span(span) < 0)
- HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "failed to release hyperslab span")
+
+ /* Free the current span */
+ H5S__hyper_free_span(span);
+
+ /* Advance to next span */
span = next_span;
} /* end while */
/* Free this span info */
- span_info = H5FL_FREE(H5S_hyper_span_info_t, span_info);
+ span_info = (H5S_hyper_span_info_t *)H5FL_ARR_FREE(hbounds_t, span_info);
} /* end if */
-done:
- FUNC_LEAVE_NOAPI(ret_value)
+ FUNC_LEAVE_NOAPI_VOID
} /* end H5S__hyper_free_span_info() */
-
+
/*--------------------------------------------------------------------------
NAME
H5S__hyper_free_span
PURPOSE
Free a hyperslab span node
USAGE
- herr_t H5S__hyper_free_span(span)
+ void H5S__hyper_free_span(span)
H5S_hyper_span_t *span; IN: Span node to free
RETURNS
- Non-negative on success, negative on failure
+ None
DESCRIPTION
Free a hyperslab span node, along with the 'down spans' from the node,
if reducing their reference count to zero indicates it is appropriate to
@@ -1586,39 +3156,37 @@ done:
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-static herr_t
+static void
H5S__hyper_free_span(H5S_hyper_span_t *span)
{
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_STATIC
+ FUNC_ENTER_STATIC_NOERR
+ /* Sanity check */
HDassert(span);
/* Decrement the reference count of the 'down spans', freeing them if appropriate */
if(span->down != NULL)
- if(H5S__hyper_free_span_info(span->down) < 0)
- HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "failed to release hyperslab span tree")
+ H5S__hyper_free_span_info(span->down);
/* Free this span */
span = H5FL_FREE(H5S_hyper_span_t, span);
-done:
- FUNC_LEAVE_NOAPI(ret_value)
+ FUNC_LEAVE_NOAPI_VOID
} /* end H5S__hyper_free_span() */
-
+
/*--------------------------------------------------------------------------
NAME
H5S__hyper_copy
PURPOSE
Copy a selection from one dataspace to another
USAGE
- herr_t H5S__hyper_copy(dst, src)
+ herr_t H5S__hyper_copy(dst, src, share_selection)
H5S_t *dst; OUT: Pointer to the destination dataspace
H5S_t *src; IN: Pointer to the source dataspace
+ hbool_t; IN: Whether to share the selection between the dataspaces
RETURNS
- Non-negative on success/Negative on failure
+ Non-negative on success, negative on failure
DESCRIPTION
Copies all the hyperslab selection information from the source
dataspace to the destination dataspace.
@@ -1655,15 +3223,8 @@ H5S__hyper_copy(H5S_t *dst, const H5S_t *src, hbool_t share_selection)
/* Copy the hyperslab information */
dst_hslab->diminfo_valid = src_hslab->diminfo_valid;
- if(src_hslab->diminfo_valid) {
- size_t u; /* Local index variable */
-
- for(u=0; u<src->extent.rank; u++) {
- dst_hslab->opt_diminfo[u]=src_hslab->opt_diminfo[u];
- dst_hslab->app_diminfo[u]=src_hslab->app_diminfo[u];
- } /* end for */
- } /* end if */
- dst->select.sel_info.hslab->span_lst=src->select.sel_info.hslab->span_lst;
+ if(src_hslab->diminfo_valid == H5S_DIMINFO_VALID_YES)
+ H5MM_memcpy(&dst_hslab->diminfo, &src_hslab->diminfo, sizeof(H5S_hyper_diminfo_t));
/* Check if there is hyperslab span information to copy */
/* (Regular hyperslab information is copied with the selection structure) */
@@ -1675,7 +3236,7 @@ H5S__hyper_copy(H5S_t *dst, const H5S_t *src, hbool_t share_selection)
} /* end if */
else
/* Copy the hyperslab span information */
- dst->select.sel_info.hslab->span_lst = H5S__hyper_copy_span(src->select.sel_info.hslab->span_lst);
+ dst->select.sel_info.hslab->span_lst = H5S__hyper_copy_span(src->select.sel_info.hslab->span_lst, src->extent.rank);
} /* end if */
else
dst->select.sel_info.hslab->span_lst = NULL;
@@ -1688,21 +3249,19 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S__hyper_copy() */
-
+
/*--------------------------------------------------------------------------
NAME
- H5S__hyper_is_valid_helper
+ H5S__hyper_is_valid
PURPOSE
Check whether the selection fits within the extent, with the current
offset defined.
USAGE
- hbool_t H5S__hyper_is_valid_helper(spans, offset, rank);
- const H5S_hyper_span_info_t *spans; IN: Pointer to current hyperslab span tree
- const hssize_t *offset; IN: Pointer to offset array
- const hsize_t *size; IN: Pointer to size array
- hsize_t rank; IN: Current rank looking at
+ htri_t H5S__hyper_is_valid(space);
+ H5S_t *space; IN: Dataspace pointer to query
RETURNS
- TRUE if the selection fits within the extent, FALSE if it does not
+ TRUE if the selection fits within the extent, FALSE if it does not and
+ Negative on an error.
DESCRIPTION
Determines if the current selection at the current offset fits within the
extent for the dataspace.
@@ -1711,111 +3270,111 @@ done:
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-static hbool_t
-H5S__hyper_is_valid_helper(const H5S_hyper_span_info_t *spans, const hssize_t *offset,
- const hsize_t *size)
+static htri_t
+H5S__hyper_is_valid(const H5S_t *space)
{
- H5S_hyper_span_t *curr; /* Hyperslab information nodes */
- hbool_t ret_value = TRUE; /* Return value */
+ const hsize_t *low_bounds, *high_bounds; /* Pointers to the correct pair of low & high bounds */
+ unsigned u; /* Counter */
+ htri_t ret_value = TRUE; /* return value */
FUNC_ENTER_STATIC_NOERR
- HDassert(spans);
- HDassert(offset);
- HDassert(size);
+ HDassert(space);
- /* Check each point to determine whether selection + offset is within extent */
- curr = spans->head;
- while(curr != NULL) {
- /* Check if an offset has been defined */
- /* Bounds check the selected point + offset against the extent */
- if((((hssize_t)curr->low + *offset) >= (hssize_t)*size)
- || (((hssize_t)curr->low + *offset) < 0)
- || (((hssize_t)curr->high + *offset) >= (hssize_t)*size)
- || (((hssize_t)curr->high + *offset) < 0))
- HGOTO_DONE(FALSE)
+ /* Check for unlimited selection */
+ if(space->select.sel_info.hslab->unlim_dim >= 0)
+ HGOTO_DONE(FALSE)
- /* Recurse if this node has down spans */
- if(curr->down != NULL)
- if(!H5S__hyper_is_valid_helper(curr->down, offset + 1, size + 1))
- HGOTO_DONE(FALSE)
+ /* Check which set of low & high bounds we should be using */
+ if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) {
+ low_bounds = space->select.sel_info.hslab->diminfo.low_bounds;
+ high_bounds = space->select.sel_info.hslab->diminfo.high_bounds;
+ } /* end if */
+ else {
+ low_bounds = space->select.sel_info.hslab->span_lst->low_bounds;
+ high_bounds = space->select.sel_info.hslab->span_lst->high_bounds;
+ } /* end else */
- /* Advance to next node */
- curr = curr->next;
- } /* end while */
+ /* Check each dimension */
+ for(u = 0; u < space->extent.rank; u++) {
+ /* Bounds check the selected point + offset against the extent */
+ if(((hssize_t)low_bounds[u] + space->select.offset[u]) < 0)
+ HGOTO_DONE(FALSE)
+ if((high_bounds[u] + (hsize_t)space->select.offset[u]) >= space->extent.size[u])
+ HGOTO_DONE(FALSE)
+ } /* end for */
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5S__hyper_is_valid_helper() */
+} /* end H5S__hyper_is_valid() */
+
-
/*--------------------------------------------------------------------------
NAME
- H5S__hyper_is_valid
+ H5S__hyper_span_nblocks_helper
PURPOSE
- Check whether the selection fits within the extent, with the current
- offset defined.
+ Helper routine to count the number of blocks in a span tree
USAGE
- htri_t H5S__hyper_is_valid(space);
- H5S_t *space; IN: Dataspace pointer to query
+ hsize_t H5S__hyper_span_nblocks_helper(spans)
+ H5S_hyper_span_info_t *spans; IN: Hyperslab span tree to count blocks of
+ uint64_t op_gen; IN: Operation generation
RETURNS
- TRUE if the selection fits within the extent, FALSE if it does not and
- Negative on an error.
+ Number of blocks in span tree on success; negative on failure
DESCRIPTION
- Determines if the current selection at the current offset fits within the
- extent for the dataspace.
+ Counts the number of blocks described by the spans in a span tree.
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-static htri_t
-H5S__hyper_is_valid(const H5S_t *space)
+static hsize_t
+H5S__hyper_span_nblocks_helper(H5S_hyper_span_info_t *spans, uint64_t op_gen)
{
- htri_t ret_value = TRUE; /* return value */
+ hsize_t ret_value = 0; /* Return value */
FUNC_ENTER_STATIC_NOERR
- HDassert(space);
+ /* Sanity check */
+ HDassert(spans);
- /* Check for unlimited selection */
- if(space->select.sel_info.hslab->unlim_dim >= 0)
- HGOTO_DONE(FALSE)
+ /* Check if the span tree was already counted */
+ if(spans->op_gen == op_gen)
+ /* Just return the # of blocks in the already counted span tree */
+ ret_value = spans->u.nblocks;
+ else { /* Count the number of elements in the span tree */
+ H5S_hyper_span_t *span; /* Hyperslab span */
- /* Check for a "regular" hyperslab selection */
- if(space->select.sel_info.hslab->diminfo_valid) {
- const H5S_hyper_dim_t *diminfo=space->select.sel_info.hslab->opt_diminfo; /* local alias for diminfo */
- hssize_t end; /* The high bound of a region in a dimension */
- unsigned u; /* Counter */
+ span = spans->head;
+ if(span->down) {
+ while(span) {
+ /* If there are down spans, add the total down span blocks */
+ ret_value += H5S__hyper_span_nblocks_helper(span->down, op_gen);
- /* Check each dimension */
- for(u = 0; u < space->extent.rank; u++) {
- /* if block or count is zero, then can skip the test since */
- /* no data point is chosen */
- if(diminfo[u].count && diminfo[u].block) {
- /* Bounds check the start point in this dimension */
- if(((hssize_t)diminfo[u].start + space->select.offset[u]) < 0 ||
- ((hssize_t)diminfo[u].start + space->select.offset[u]) >= (hssize_t)space->extent.size[u])
- HGOTO_DONE(FALSE)
+ /* Advance to next span */
+ span = span->next;
+ } /* end while */
+ } /* end if */
+ else {
+ while(span) {
+ /* If there are no down spans, just count the block in this span */
+ ret_value++;
- /* Compute the largest location in this dimension */
- end = (hssize_t)(diminfo[u].start + diminfo[u].stride * (diminfo[u].count - 1) + (diminfo[u].block - 1)) + space->select.offset[u];
+ /* Advance to next span */
+ span = span->next;
+ } /* end while */
+ } /* end else */
- /* Bounds check the end point in this dimension */
- if(end < 0 || end >= (hssize_t)space->extent.size[u])
- HGOTO_DONE(FALSE)
- } /* end if */
- } /* end for */
- } /* end if */
- else
- /* Call the recursive routine to validate the span tree */
- ret_value = H5S__hyper_is_valid_helper(space->select.sel_info.hslab->span_lst, space->select.offset, space->extent.size);
+ /* Set the operation generation for this span tree, to avoid re-computing */
+ spans->op_gen = op_gen;
+
+ /* Hold a copy of the # of blocks */
+ spans->u.nblocks = ret_value;
+ } /* end else */
-done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5S__hyper_is_valid() */
+} /* end H5S__hyper_span_nblocks_helper() */
+
-
/*--------------------------------------------------------------------------
NAME
H5S__hyper_span_nblocks
@@ -1823,7 +3382,7 @@ done:
Count the number of blocks in a span tree
USAGE
hsize_t H5S__hyper_span_nblocks(spans)
- const H5S_hyper_span_info_t *spans; IN: Hyperslab span tree to count elements of
+ H5S_hyper_span_info_t *spans; IN: Hyperslab span tree to count blocks of
RETURNS
Number of blocks in span tree on success; negative on failure
DESCRIPTION
@@ -1834,7 +3393,7 @@ done:
REVISION LOG
--------------------------------------------------------------------------*/
static hsize_t
-H5S__hyper_span_nblocks(const H5S_hyper_span_info_t *spans)
+H5S__hyper_span_nblocks(H5S_hyper_span_info_t *spans)
{
hsize_t ret_value = 0; /* Return value */
@@ -1842,34 +3401,27 @@ H5S__hyper_span_nblocks(const H5S_hyper_span_info_t *spans)
/* Count the number of elements in the span tree */
if(spans != NULL) {
- H5S_hyper_span_t *span; /* Hyperslab span */
+ uint64_t op_gen; /* Operation generation value */
- span = spans->head;
- while(span != NULL) {
- /* If there are down spans, add the total down span blocks */
- if(span->down != NULL)
- ret_value += H5S__hyper_span_nblocks(span->down);
- /* If there are no down spans, just count the block in this span */
- else
- ret_value++;
+ /* Acquire an operation generation value for this operation */
+ op_gen = H5S__hyper_get_op_gen();
- /* Advance to next span */
- span = span->next;
- } /* end while */
- } /* end else */
+ ret_value = H5S__hyper_span_nblocks_helper(spans, op_gen);
+ } /* end if */
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S__hyper_span_nblocks() */
-
+
/*--------------------------------------------------------------------------
NAME
H5S__get_select_hyper_nblocks
PURPOSE
Get the number of hyperslab blocks in current hyperslab selection
USAGE
- hsize_t H5S__get_select_hyper_nblocks(space)
+ hsize_t H5S__get_select_hyper_nblocks(space, app_ref)
H5S_t *space; IN: Dataspace ptr of selection to query
+ hbool_t app_ref; IN: Whether this is an appl. ref. call
RETURNS
The number of hyperslab blocks in selection on success, negative on failure
DESCRIPTION
@@ -1880,7 +3432,7 @@ H5S__hyper_span_nblocks(const H5S_hyper_span_info_t *spans)
REVISION LOG
--------------------------------------------------------------------------*/
static hsize_t
-H5S__get_select_hyper_nblocks(const H5S_t *space)
+H5S__get_select_hyper_nblocks(const H5S_t *space, hbool_t app_ref)
{
hsize_t ret_value = 0; /* Return value */
@@ -1890,12 +3442,14 @@ H5S__get_select_hyper_nblocks(const H5S_t *space)
HDassert(space->select.sel_info.hslab->unlim_dim < 0);
/* Check for a "regular" hyperslab selection */
- if(space->select.sel_info.hslab->diminfo_valid) {
+ /* (No need to rebuild the dimension info yet -QAK) */
+ if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) {
unsigned u; /* Local index variable */
/* Check each dimension */
for(ret_value = 1, u = 0; u < space->extent.rank; u++)
- ret_value *= space->select.sel_info.hslab->app_diminfo[u].count;
+ ret_value *= (app_ref ? space->select.sel_info.hslab->diminfo.app[u].count :
+ space->select.sel_info.hslab->diminfo.opt[u].count);
} /* end if */
else
ret_value = H5S__hyper_span_nblocks(space->select.sel_info.hslab->span_lst);
@@ -1903,7 +3457,7 @@ H5S__get_select_hyper_nblocks(const H5S_t *space)
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S__get_select_hyper_nblocks() */
-
+
/*--------------------------------------------------------------------------
NAME
H5Sget_select_hyper_nblocks
@@ -1938,13 +3492,214 @@ H5Sget_select_hyper_nblocks(hid_t spaceid)
if(space->select.sel_info.hslab->unlim_dim >= 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "cannot get number of blocks for unlimited selection")
- ret_value = (hssize_t)H5S__get_select_hyper_nblocks(space);
+ ret_value = (hssize_t)H5S__get_select_hyper_nblocks(space, TRUE);
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Sget_select_hyper_nblocks() */
-
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S__hyper_get_enc_size_real
+ PURPOSE
+ Determine the size to encode the hyperslab selection info
+ USAGE
+ hssize_t H5S__hyper_get_enc_size_real(max_size, enc_size)
+ hsize_t max_size: IN: The maximum size of the hyperslab selection info
+ unint8_t *enc_size: OUT:The encoding size
+ RETURNS
+ The size to encode hyperslab selection info
+ DESCRIPTION
+ Determine the size by comparing "max_size" with (2^32 - 1) and (2^16 - 1).
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static uint8_t
+H5S__hyper_get_enc_size_real(hsize_t max_size)
+{
+ uint8_t ret_value = H5S_SELECT_INFO_ENC_SIZE_2;
+
+ FUNC_ENTER_STATIC_NOERR
+
+ if(max_size > H5S_UINT32_MAX)
+ ret_value = H5S_SELECT_INFO_ENC_SIZE_8;
+ else if(max_size > H5S_UINT16_MAX)
+ ret_value = H5S_SELECT_INFO_ENC_SIZE_4;
+ else
+ ret_value = H5S_SELECT_INFO_ENC_SIZE_2;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5S__hyper_get_enc_size_real() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S__hyper_get_version_enc_size
+ PURPOSE
+ Determine the version and encoded size to use for encoding hyperslab selection info
+ USAGE
+ hssize_t H5S__hyper_get_version_enc_size(space, block_count, version, enc_size)
+ const H5S_t *space: IN: The dataspace
+ hsize_t block_count: IN: The number of blocks in the selection
+ uint32_t *version: OUT: The version to use for encoding
+ uint8_t *enc_size: OUT: The encoded size to use
+
+ RETURNS
+ The version and the size to encode hyperslab selection info
+ DESCRIPTION
+ Determine the version to use for encoding hyperslab selection info based
+ on the following:
+ (1) the file format setting in fapl
+ (2) whether the number of blocks or selection high bounds exceeds H5S_UINT32_MAX or not
+
+ Determine the encoded size based on version:
+ For version 3, the encoded size is determined according to:
+ (a) regular hyperslab
+ (1) The maximum needed to store start/stride/count/block
+ (2) Special handling for count/block: need to provide room for H5S_UNLIMITED
+ (b) irregular hyperslab
+ The maximum size needed to store:
+ (1) the number of blocks
+ (2) the selection high bounds
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static herr_t
+H5S__hyper_get_version_enc_size(const H5S_t *space, hsize_t block_count, uint32_t *version, uint8_t *enc_size)
+{
+ hsize_t bounds_start[H5S_MAX_RANK]; /* Starting coordinate of bounding box */
+ hsize_t bounds_end[H5S_MAX_RANK]; /* Opposite coordinate of bounding box */
+ hbool_t count_up_version = FALSE; /* Whether number of blocks exceed H5S_UINT32_MAX */
+ hbool_t bound_up_version = FALSE; /* Whether high bounds exceed H5S_UINT32_MAX */
+ H5F_libver_t low_bound; /* The 'low' bound of library format versions */
+ H5F_libver_t high_bound; /* The 'high' bound of library format versions */
+ htri_t is_regular; /* A regular hyperslab or not */
+ uint32_t tmp_version; /* Local temporay version */
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Get bounding box for the selection */
+ HDmemset(bounds_end, 0, sizeof(bounds_end));
+
+ if(space->select.sel_info.hslab->unlim_dim < 0) /* ! H5S_UNLIMITED */
+ /* Get bounding box for the selection */
+ if(H5S__hyper_bounds(space, bounds_start, bounds_end) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get selection bounds")
+
+ /* Determine whether the number of blocks or the high bounds in the selection exceed (2^32 - 1) */
+ if(block_count > H5S_UINT32_MAX)
+ count_up_version = TRUE;
+ else {
+ for(u = 0; u < space->extent.rank; u++)
+ if(bounds_end[u] > H5S_UINT32_MAX) {
+ bound_up_version = TRUE;
+ break;
+ } /* end if */
+ } /* end else */
+
+ /* Get the file's low_bound and high_bound */
+ if(H5CX_get_libver_bounds(&low_bound, &high_bound) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get low/high bounds from API context")
+
+ /* Determine regular hyperslab */
+ is_regular = H5S__hyper_is_regular(space);
+
+ if(low_bound >= H5F_LIBVER_V112 || space->select.sel_info.hslab->unlim_dim >= 0)
+ tmp_version = MAX(H5S_HYPER_VERSION_2, H5O_sds_hyper_ver_bounds[low_bound]);
+ else {
+ if(count_up_version || bound_up_version)
+ tmp_version = is_regular ? H5S_HYPER_VERSION_2 : H5S_HYPER_VERSION_3;
+ else
+ tmp_version = (is_regular && block_count >= 4) ? H5O_sds_hyper_ver_bounds[low_bound] : H5S_HYPER_VERSION_1;
+ } /* end else */
+
+ /* Version bounds check */
+ if(tmp_version > H5O_sds_hyper_ver_bounds[high_bound]) {
+ /* Fail for irregular hyperslab if exceeds 32 bits */
+ if(count_up_version)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "The number of blocks in hyperslab selection exceeds 2^32")
+ else if(bound_up_version)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "The end of bounding box in hyperslab selection exceeds 2^32")
+ else
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "Dataspace hyperslab selection version out of bounds")
+ } /* end if */
+
+ /* Set the message version */
+ *version = tmp_version;
+
+ /* Determine the encoded size based on version */
+ switch(tmp_version) {
+ case H5S_HYPER_VERSION_1:
+ *enc_size = H5S_SELECT_INFO_ENC_SIZE_4;
+ break;
+
+ case H5S_HYPER_VERSION_2:
+ *enc_size = H5S_SELECT_INFO_ENC_SIZE_8;
+ break;
+
+ case H5S_HYPER_VERSION_3:
+ if(is_regular) {
+ uint8_t enc1, enc2;
+ hsize_t max1 = 0;
+ hsize_t max2 = 0;
+
+ /* Find max for count[] and block[] */
+ for(u = 0; u < space->extent.rank; u++) {
+ if(space->select.sel_info.hslab->diminfo.opt[u].count != H5S_UNLIMITED &&
+ space->select.sel_info.hslab->diminfo.opt[u].count > max1)
+ max1 = space->select.sel_info.hslab->diminfo.opt[u].count;
+ if(space->select.sel_info.hslab->diminfo.opt[u].block != H5S_UNLIMITED &&
+ space->select.sel_info.hslab->diminfo.opt[u].block > max1)
+ max1 = space->select.sel_info.hslab->diminfo.opt[u].block;
+ } /* end for */
+
+ /* +1 to provide room for H5S_UNLIMITED */
+ enc1 = H5S__hyper_get_enc_size_real(++max1);
+
+ /* Find max for start[] and stride[] */
+ for(u = 0; u < space->extent.rank; u++) {
+ if(space->select.sel_info.hslab->diminfo.opt[u].start > max2)
+ max2 = space->select.sel_info.hslab->diminfo.opt[u].start;
+ if(space->select.sel_info.hslab->diminfo.opt[u].stride > max2)
+ max2 = space->select.sel_info.hslab->diminfo.opt[u].stride;
+ } /* end for */
+
+ /* Determine the encoding size */
+ enc2 = H5S__hyper_get_enc_size_real(max2);
+
+ *enc_size = MAX(enc1, enc2);
+ } /* end if */
+ else {
+ hsize_t max_size = block_count;
+ HDassert(space->select.sel_info.hslab->unlim_dim < 0);
+
+ /* Find max for block_count and bounds_end[] */
+ for(u = 0; u < space->extent.rank; u++)
+ if(bounds_end[u] > max_size)
+ max_size = bounds_end[u];
+
+ /* Determine the encoding size */
+ *enc_size = H5S__hyper_get_enc_size_real(max_size);
+ } /* end else */
+ break;
+
+ default:
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unknown hyperslab selection version")
+ break;
+ } /* end switch */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5S__hyper_get_version_enc_size() */
+
+
/*--------------------------------------------------------------------------
NAME
H5S__hyper_serial_size
@@ -1967,65 +3722,91 @@ done:
static hssize_t
H5S__hyper_serial_size(const H5S_t *space)
{
- hsize_t block_count; /* block counter for regular hyperslabs */
- unsigned u; /* Counter */
- hssize_t ret_value = -1; /* return value */
+ hsize_t block_count = 0; /* block counter for regular hyperslabs */
+ uint32_t version; /* Version number */
+ uint8_t enc_size; /* Encoded size of hyerslab selection info */
+ hssize_t ret_value = -1; /* return value */
- FUNC_ENTER_STATIC_NOERR
+ FUNC_ENTER_STATIC
HDassert(space);
- /* Check for version (right now, an unlimited dimension is the only thing
- * that would bump the version) */
- if(space->select.sel_info.hslab->unlim_dim >= 0)
+ if(space->select.sel_info.hslab->unlim_dim < 0) /* ! H5S_UNLIMITED */
+ block_count = H5S__get_select_hyper_nblocks(space, FALSE);
+
+ /* Determine the version and the encoded size */
+ if(H5S__hyper_get_version_enc_size(space, block_count, &version, &enc_size) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't determine hyper version & enc_size")
+
+ if(version == H5S_HYPER_VERSION_3) {
+ /* Version 3: regular */
+ /* Size required is always:
+ * <type (4 bytes)> + <version (4 bytes)> + <flags (1 byte)> +
+ * <size of offset info (1 byte)> + <rank (4 bytes)> +
+ * (4 (start/stride/count/block) * <enc_size> * <rank>) =
+ * 14 + (4 * enc_size * rank) bytes
+ */
+ if(H5S__hyper_is_regular(space))
+ ret_value = (hssize_t)14 +
+ ((hssize_t)4 * (hssize_t)enc_size * (hssize_t)space->extent.rank);
+ else {
+ /* Version 3: irregular */
+ /* Size required is always:
+ * <type (4 bytes)> + <version (4 bytes)> + <flags (1 byte)> +
+ * <size of offset info (1 byte)> + <rank (4 bytes)> +
+ * < # of blocks (depend on enc_size) > +
+ * (2 (starting/ending offset) * <rank> * <enc_size> * <# of blocks) =
+ * = 14 bytes + enc_size (block_count) + (2 * enc_size * rank * block_count) bytes
+ */
+ ret_value = 14 + enc_size;
+ H5_CHECK_OVERFLOW(((unsigned)2 * enc_size * space->extent.rank * block_count), hsize_t, hssize_t);
+ ret_value += (hssize_t)((unsigned)2 * enc_size * space->extent.rank * block_count);
+ } /* end else */
+ } /* end if */
+ else if(version == H5S_HYPER_VERSION_2) {
/* Version 2 */
/* Size required is always:
* <type (4 bytes)> + <version (4 bytes)> + <flags (1 byte)> +
* <length (4 bytes)> + <rank (4 bytes)> +
- * (4 (start/stride/count/block) * <rank> * <value (8 bytes)>) =
- * 17 + (4 * rank * 8) bytes
+ * (4 (start/stride/count/block) * <enc_size (8 bytes)> * <rank>) =
+ * 17 + (4 * 8 * rank) bytes
*/
- ret_value = (hssize_t)17 + ((hssize_t)4 * (hssize_t)space->extent.rank
- * (hssize_t)8);
+ HDassert(enc_size == 8);
+ ret_value = (hssize_t)17 + ((hssize_t)4 * (hssize_t)8 * (hssize_t)space->extent.rank);
+ } /* end else-if */
else {
+ HDassert(version == H5S_HYPER_VERSION_1);
+ HDassert(enc_size == 4);
/* Version 1 */
/* Basic number of bytes required to serialize hyperslab selection:
* <type (4 bytes)> + <version (4 bytes)> + <padding (4 bytes)> +
- * <length (4 bytes)> + <rank (4 bytes)> + <# of blocks (4 bytes)>
- * = 24 bytes
+ * <length (4 bytes)> + <rank (4 bytes)> + <# of blocks (4 bytes)> +
+ * (2 (starting/ending offset) * <enc_size (4 bytes)> * <rank> * <# of blocks) =
+ * = 24 bytes + (2 * 4 * rank * block_count)
*/
ret_value = 24;
-
- /* Check for a "regular" hyperslab selection */
- if(space->select.sel_info.hslab->diminfo_valid) {
- /* Check each dimension */
- for(block_count = 1, u = 0; u < space->extent.rank; u++)
- block_count *= space->select.sel_info.hslab->opt_diminfo[u].count;
- } /* end if */
- else
- /* Spin through hyperslab spans, adding 8 * rank bytes for each block */
- block_count = H5S__hyper_span_nblocks(space->select.sel_info.hslab->span_lst);
-
H5_CHECK_OVERFLOW((8 * space->extent.rank * block_count), hsize_t, hssize_t);
- ret_value += (hssize_t)(8 * block_count * space->extent.rank);
+ ret_value += (hssize_t)(8 * space->extent.rank * block_count);
} /* end else */
+done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S__hyper_serial_size() */
-
+
/*--------------------------------------------------------------------------
NAME
H5S__hyper_serialize_helper
PURPOSE
Serialize the current selection into a user-provided buffer.
USAGE
- void H5S__hyper_serialize_helper(spans, start, end, rank, buf)
+ void H5S__hyper_serialize_helper(spans, start, end, rank, enc_size, buf)
H5S_hyper_span_info_t *spans; IN: Hyperslab span tree to serialize
hssize_t start[]; IN/OUT: Accumulated start points
hssize_t end[]; IN/OUT: Accumulated end points
hsize_t rank; IN: Current rank looking at
- uint8 *buf; OUT: Buffer to put serialized selection into
+ uint8_t enc_size IN: Encoded size of hyperslab selection info
+ uint8_t *buf; OUT: Buffer to put serialized selection into
RETURNS
None
DESCRIPTION
@@ -2038,7 +3819,7 @@ H5S__hyper_serial_size(const H5S_t *space)
--------------------------------------------------------------------------*/
static void
H5S__hyper_serialize_helper(const H5S_hyper_span_info_t *spans,
- hsize_t *start, hsize_t *end, hsize_t rank, uint8_t **p)
+ hsize_t *start, hsize_t *end, hsize_t rank, uint8_t enc_size, uint8_t **p)
{
H5S_hyper_span_t *curr; /* Pointer to current hyperslab span */
uint8_t *pp = (*p); /* Local pointer for decoding */
@@ -2049,7 +3830,7 @@ H5S__hyper_serialize_helper(const H5S_hyper_span_info_t *spans,
HDassert(spans);
HDassert(start);
HDassert(end);
- HDassert(rank < H5O_LAYOUT_NDIMS);
+ HDassert(rank < H5S_MAX_RANK);
HDassert(p && pp);
/* Walk through the list of spans, recursing or outputting them */
@@ -2062,26 +3843,65 @@ H5S__hyper_serialize_helper(const H5S_hyper_span_info_t *spans,
end[rank] = curr->high;
/* Recurse down to the next dimension */
- H5S__hyper_serialize_helper(curr->down, start, end, rank + 1, &pp);
+ H5S__hyper_serialize_helper(curr->down, start, end, rank + 1, enc_size, &pp);
} /* end if */
else {
hsize_t u; /* Index variable */
/* Encode all the previous dimensions starting & ending points */
+ switch(enc_size) {
+ case H5S_SELECT_INFO_ENC_SIZE_2:
+ /* Encode previous starting points */
+ for(u=0; u<rank; u++)
+ UINT16ENCODE(pp, (uint16_t)start[u]);
- /* Encode previous starting points */
- for(u = 0; u < rank; u++)
- UINT32ENCODE(pp, (uint32_t)start[u]);
+ /* Encode starting point for this span */
+ UINT16ENCODE(pp, (uint16_t)curr->low);
- /* Encode starting point for this span */
- UINT32ENCODE(pp, (uint32_t)curr->low);
+ /* Encode previous ending points */
+ for(u=0; u<rank; u++)
+ UINT16ENCODE(pp, (uint16_t)end[u]);
- /* Encode previous ending points */
- for(u = 0; u < rank; u++)
- UINT32ENCODE(pp, (uint32_t)end[u]);
+ /* Encode starting point for this span */
+ UINT16ENCODE(pp, (uint16_t)curr->high);
+ break;
+
+ case H5S_SELECT_INFO_ENC_SIZE_4:
+ /* Encode previous starting points */
+ for(u=0; u<rank; u++)
+ UINT32ENCODE(pp, (uint32_t)start[u]);
+
+ /* Encode starting point for this span */
+ UINT32ENCODE(pp, (uint32_t)curr->low);
+
+ /* Encode previous ending points */
+ for(u=0; u<rank; u++)
+ UINT32ENCODE(pp, (uint32_t)end[u]);
+
+ /* Encode starting point for this span */
+ UINT32ENCODE(pp, (uint32_t)curr->high);
+ break;
+
+ case H5S_SELECT_INFO_ENC_SIZE_8:
+ /* Encode previous starting points */
+ for(u=0; u<rank; u++)
+ UINT64ENCODE(pp, (uint64_t)start[u]);
+
+ /* Encode starting point for this span */
+ UINT64ENCODE(pp, (uint64_t)curr->low);
+
+ /* Encode previous ending points */
+ for(u=0; u<rank; u++)
+ UINT64ENCODE(pp, (uint64_t)end[u]);
- /* Encode starting point for this span */
- UINT32ENCODE(pp, (uint32_t)curr->high);
+ /* Encode starting point for this span */
+ UINT64ENCODE(pp, (uint64_t)curr->high);
+ break;
+
+ default:
+ HDassert(0 && "Unknown enc size?!?");
+
+ } /* end switch */
} /* end else */
/* Advance to next node */
@@ -2092,9 +3912,9 @@ H5S__hyper_serialize_helper(const H5S_hyper_span_info_t *spans,
*p = pp;
FUNC_LEAVE_NOAPI_VOID
-} /* H5S__hyper_serialize_helper() */
+} /* end H5S__hyper_serialize_helper() */
+
-
/*--------------------------------------------------------------------------
NAME
H5S__hyper_serialize
@@ -2119,14 +3939,26 @@ H5S__hyper_serialize_helper(const H5S_hyper_span_info_t *spans,
static herr_t
H5S__hyper_serialize(const H5S_t *space, uint8_t **p)
{
- uint8_t *pp; /* Local pointer for decoding */
- uint8_t *lenp; /* Pointer to length location for later storage */
- uint32_t len = 0; /* Number of bytes used */
+ const H5S_hyper_dim_t *diminfo; /* Alias for dataspace's diminfo information */
+ hsize_t tmp_count[H5S_MAX_RANK]; /* Temporary hyperslab counts */
+ hsize_t offset[H5S_MAX_RANK]; /* Offset of element in dataspace */
+ hsize_t start[H5S_MAX_RANK]; /* Location of start of hyperslab */
+ hsize_t end[H5S_MAX_RANK]; /* Location of end of hyperslab */
+ uint8_t *pp; /* Local pointer for decoding */
+ uint8_t *lenp = NULL; /* pointer to length location for later storage */
+ uint32_t len = 0; /* number of bytes used */
uint32_t version; /* Version number */
uint8_t flags = 0; /* Flags for message */
- hsize_t block_count; /* Block counter for regular hyperslabs */
+ hsize_t block_count = 0; /* block counter for regular hyperslabs */
+ unsigned fast_dim; /* Rank of the fastest changing dimension for the dataspace */
+ unsigned ndims; /* Rank of the dataspace */
+ unsigned u; /* Local counting variable */
+ hbool_t complete = FALSE; /* Whether we are done with the iteration */
+ hbool_t is_regular; /* Whether selection is regular */
+ uint8_t enc_size;
+ herr_t ret_value = SUCCEED; /* return value */
- FUNC_ENTER_STATIC_NOERR
+ FUNC_ENTER_STATIC
/* Sanity checks */
HDassert(space);
@@ -2134,164 +3966,231 @@ H5S__hyper_serialize(const H5S_t *space, uint8_t **p)
pp = (*p);
HDassert(pp);
- /* Calculate version */
- if(space->select.sel_info.hslab->unlim_dim >= 0) {
- version = 2;
- flags |= H5S_SELECT_FLAG_UNLIM;
- } /* end if */
- else
- version = 1;
+ /* Set some convienence values */
+ ndims = space->extent.rank;
+ diminfo = space->select.sel_info.hslab->diminfo.opt;
+
+ if(space->select.sel_info.hslab->unlim_dim < 0) /* ! H5S_UNLIMITED */
+ block_count = H5S__get_select_hyper_nblocks(space, FALSE);
+
+ /* Determine the version and the encoded size */
+ if(H5S__hyper_get_version_enc_size(space, block_count, &version, &enc_size) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't determine hyper version & enc_size")
+
+ is_regular = H5S__hyper_is_regular(space);
+ if(is_regular &&
+ (version == H5S_HYPER_VERSION_2 || version == H5S_HYPER_VERSION_3))
+ flags |= H5S_HYPER_REGULAR;
/* Store the preamble information */
UINT32ENCODE(pp, (uint32_t)H5S_GET_SELECT_TYPE(space)); /* Store the type of selection */
UINT32ENCODE(pp, version); /* Store the version number */
- if(version >= 2)
- *(pp)++ = flags; /* Store the flags */
- else
- UINT32ENCODE(pp, (uint32_t)0); /* Store the un-used padding */
- lenp = pp; /* keep the pointer to the length location for later */
- pp += 4; /* skip over space for length */
- /* Encode number of dimensions */
- UINT32ENCODE(pp, (uint32_t)space->extent.rank);
- len += 4;
+ if(version >= 3) {
+ *(pp)++ = flags; /* Store the flags */
+ *(pp)++ = enc_size; /* Store size of offset info */
+ } /* end if */
+ else {
+ if(version == 2)
+ *(pp)++ = flags; /* Store the flags */
+ else
+ UINT32ENCODE(pp, (uint32_t)0); /* Store the un-used padding */
+ lenp = pp; /* keep the pointer to the length location for later */
+ pp += 4; /* skip over space for length */
- /* If there is an unlimited dimension, only encode opt_unlim_diminfo */
- if(flags & H5S_SELECT_FLAG_UNLIM) {
- unsigned i;
+ len += 4; /* ndims */
+ } /* end else */
- HDassert(H5S_UNLIMITED == HSIZE_UNDEF);
+ /* Encode number of dimensions */
+ UINT32ENCODE(pp, (uint32_t)ndims);
- /* Iterate over dimensions */
- for(i = 0; i < space->extent.rank; i++) {
+ if(is_regular) {
+ if(version >= H5S_HYPER_VERSION_2) {
+ HDassert(H5S_UNLIMITED == HSIZE_UNDEF);
+
+ /* Iterate over dimensions */
/* Encode start/stride/block/count */
- UINT64ENCODE(pp, space->select.sel_info.hslab->opt_diminfo[i].start);
- UINT64ENCODE(pp, space->select.sel_info.hslab->opt_diminfo[i].stride);
- UINT64ENCODE(pp, space->select.sel_info.hslab->opt_diminfo[i].count);
- UINT64ENCODE(pp, space->select.sel_info.hslab->opt_diminfo[i].block);
- } /* end for */
- } /* end if */
- /* Check for a "regular" hyperslab selection */
- else if(space->select.sel_info.hslab->diminfo_valid) {
- const H5S_hyper_dim_t *diminfo; /* Alias for dataspace's diminfo information */
- hsize_t offset[H5O_LAYOUT_NDIMS]; /* Offset of element in dataspace */
- hsize_t tmp_count[H5O_LAYOUT_NDIMS]; /* Temporary hyperslab counts */
- unsigned fast_dim; /* Rank of the fastest changing dimension for the dataspace */
- unsigned ndims; /* Rank of the dataspace */
- unsigned u; /* Local counting variable */
- hbool_t done; /* Whether we are done with the iteration */
+ switch(enc_size) {
+ case H5S_SELECT_INFO_ENC_SIZE_2:
+ HDassert(version == H5S_HYPER_VERSION_3);
+ for(u = 0; u < space->extent.rank; u++) {
+ UINT16ENCODE(pp, diminfo[u].start);
+ UINT16ENCODE(pp, diminfo[u].stride);
+ if(diminfo[u].count == H5S_UNLIMITED)
+ UINT16ENCODE(pp, H5S_UINT16_MAX)
+ else
+ UINT16ENCODE(pp, diminfo[u].count)
+ if(diminfo[u].block == H5S_UNLIMITED)
+ UINT16ENCODE(pp, H5S_UINT16_MAX)
+ else
+ UINT16ENCODE(pp, diminfo[u].block)
+ } /* end for */
+ break;
- /* Set some convenience values */
- ndims = space->extent.rank;
- fast_dim = ndims - 1;
- diminfo = space->select.sel_info.hslab->opt_diminfo;
+ case H5S_SELECT_INFO_ENC_SIZE_4:
+ HDassert(version == H5S_HYPER_VERSION_3);
+ for(u = 0; u < space->extent.rank; u++) {
+ UINT32ENCODE(pp, diminfo[u].start);
+ UINT32ENCODE(pp, diminfo[u].stride);
+ if(diminfo[u].count == H5S_UNLIMITED)
+ UINT32ENCODE(pp, H5S_UINT32_MAX)
+ else
+ UINT32ENCODE(pp, diminfo[u].count)
+ if(diminfo[u].block == H5S_UNLIMITED)
+ UINT32ENCODE(pp, H5S_UINT32_MAX)
+ else
+ UINT32ENCODE(pp, diminfo[u].block)
+ } /* end for */
+ break;
- /* Check each dimension */
- for(block_count = 1, u = 0; u < ndims; u++)
- block_count *= diminfo[u].count;
+ case H5S_SELECT_INFO_ENC_SIZE_8:
+ HDassert(version == H5S_HYPER_VERSION_2 || version == H5S_HYPER_VERSION_3);
+ for(u = 0; u < space->extent.rank; u++) {
+ UINT64ENCODE(pp, diminfo[u].start);
+ UINT64ENCODE(pp, diminfo[u].stride);
+ if(diminfo[u].count == H5S_UNLIMITED)
+ UINT64ENCODE(pp, H5S_UINT64_MAX)
+ else
+ UINT64ENCODE(pp, diminfo[u].count)
+ if(diminfo[u].block == H5S_UNLIMITED)
+ UINT64ENCODE(pp, H5S_UINT64_MAX)
+ else
+ UINT64ENCODE(pp, diminfo[u].block)
+ } /* end for */
+ if(version == H5S_HYPER_VERSION_2)
+ len += (4 * space->extent.rank * 8);
+ break;
+ default:
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unknown offset info size for hyperslab")
+ break;
+ } /* end switch */
+ } /* end if */
+ else {
+ HDassert(version == H5S_HYPER_VERSION_1);
- /* Encode number of hyperslabs */
- H5_CHECK_OVERFLOW(block_count, hsize_t, uint32_t);
- UINT32ENCODE(pp, (uint32_t)block_count);
- len += 4;
+ /* Set some convienence values */
+ fast_dim = ndims - 1;
- /* Now serialize the information for the regular hyperslab */
+ /* Encode number of hyperslabs */
+ H5_CHECK_OVERFLOW(block_count, hsize_t, uint32_t);
+ UINT32ENCODE(pp, (uint32_t)block_count);
+ len += 4;
- /* Build the tables of count sizes as well as the initial offset */
- for(u = 0; u < ndims; u++) {
- tmp_count[u] = diminfo[u].count;
- offset[u] = diminfo[u].start;
- } /* end for */
+ /* Now serialize the information for the regular hyperslab */
- /* We're not done with the iteration */
- done = FALSE;
+ /* Build the tables of count sizes as well as the initial offset */
+ for(u = 0; u < ndims; u++) {
+ tmp_count[u] = diminfo[u].count;
+ offset[u] = diminfo[u].start;
+ } /* end for */
- /* Go iterate over the hyperslabs */
- while(done == FALSE) {
- /* Iterate over the blocks in the fastest dimension */
- while(tmp_count[fast_dim] > 0) {
- /* Add 8 bytes times the rank for each hyperslab selected */
- len += 8 * ndims;
+ /* Go iterate over the hyperslabs */
+ while(complete == FALSE) {
+ /* Iterate over the blocks in the fastest dimension */
+ while(tmp_count[fast_dim] > 0) {
+ /* Add 8 bytes times the rank for each hyperslab selected */
+ len += 8 * ndims;
- /* Encode hyperslab starting location */
- for(u = 0; u < ndims; u++)
- UINT32ENCODE(pp, (uint32_t)offset[u]);
+ /* Encode hyperslab starting location */
+ for(u = 0; u < ndims; u++)
+ UINT32ENCODE(pp, (uint32_t)offset[u]);
- /* Encode hyperslab ending location */
- for(u = 0; u < ndims; u++)
- UINT32ENCODE(pp, (uint32_t)(offset[u] + (diminfo[u].block - 1)));
+ /* Encode hyperslab ending location */
+ for(u = 0; u < ndims; u++)
+ UINT32ENCODE(pp, (uint32_t)(offset[u] + (diminfo[u].block - 1)));
- /* Move the offset to the next sequence to start */
- offset[fast_dim]+=diminfo[fast_dim].stride;
+ /* Move the offset to the next sequence to start */
+ offset[fast_dim]+=diminfo[fast_dim].stride;
- /* Decrement the block count */
- tmp_count[fast_dim]--;
- } /* end while */
+ /* Decrement the block count */
+ tmp_count[fast_dim]--;
+ } /* end while */
- /* Work on other dimensions if necessary */
- if(fast_dim > 0) {
- int temp_dim; /* Temporary rank holder */
+ /* Work on other dimensions if necessary */
+ if(fast_dim > 0) {
+ int temp_dim; /* Temporary rank holder */
- /* Reset the block counts */
- tmp_count[fast_dim] = diminfo[fast_dim].count;
+ /* Reset the block counts */
+ tmp_count[fast_dim] = diminfo[fast_dim].count;
- /* Bubble up the decrement to the slower changing dimensions */
- temp_dim = (int)fast_dim - 1;
- while(temp_dim >= 0 && done == FALSE) {
- /* Decrement the block count */
- tmp_count[temp_dim]--;
+ /* Bubble up the decrement to the slower changing dimensions */
+ temp_dim = (int)fast_dim - 1;
+ while(temp_dim >= 0 && complete == FALSE) {
+ /* Decrement the block count */
+ tmp_count[temp_dim]--;
- /* Check if we have more blocks left */
- if(tmp_count[temp_dim] > 0)
- break;
+ /* Check if we have more blocks left */
+ if(tmp_count[temp_dim] > 0)
+ break;
- /* Check for getting out of iterator */
- if(temp_dim == 0)
- done = TRUE;
+ /* Check for getting out of iterator */
+ if(temp_dim == 0)
+ complete = TRUE;
- /* Reset the block count in this dimension */
- tmp_count[temp_dim] = diminfo[temp_dim].count;
+ /* Reset the block count in this dimension */
+ tmp_count[temp_dim] = diminfo[temp_dim].count;
- /* Wrapped a dimension, go up to next dimension */
- temp_dim--;
- } /* end while */
- } /* end if */
- else
- break; /* Break out now, for 1-D selections */
+ /* Wrapped a dimension, go up to next dimension */
+ temp_dim--;
+ } /* end while */
+ } /* end if */
+ else
+ break; /* Break out now, for 1-D selections */
- /* Re-compute offset array */
- for(u = 0; u < ndims; u++)
- offset[u] = diminfo[u].start + diminfo[u].stride * (diminfo[u].count - tmp_count[u]);
- } /* end while */
+ /* Re-compute offset array */
+ for(u = 0; u < ndims; u++)
+ offset[u] = diminfo[u].start + diminfo[u].stride * (diminfo[u].count - tmp_count[u]);
+ } /* end while */
+ } /* end else */
} /* end if */
- else {
- hsize_t start[H5O_LAYOUT_NDIMS]; /* Location of start of hyperslab */
- hsize_t end[H5O_LAYOUT_NDIMS]; /* Location of end of hyperslab */
-
+ else { /* irregular */
/* Encode number of hyperslabs */
- block_count = H5S__hyper_span_nblocks(space->select.sel_info.hslab->span_lst);
- H5_CHECK_OVERFLOW(block_count, hsize_t, uint32_t);
- UINT32ENCODE(pp, (uint32_t)block_count);
- len += 4;
+ switch(enc_size) {
+ case H5S_SELECT_INFO_ENC_SIZE_2:
+ HDassert(version == H5S_HYPER_VERSION_3);
+ H5_CHECK_OVERFLOW(block_count, hsize_t, uint16_t);
+ UINT16ENCODE(pp, (uint16_t)block_count);
+ break;
- /* Add 8 bytes times the rank for each hyperslab selected */
- H5_CHECK_OVERFLOW((8 * space->extent.rank * block_count), hsize_t, size_t);
- len += (uint32_t)(8 * space->extent.rank * block_count);
+ case H5S_SELECT_INFO_ENC_SIZE_4:
+ HDassert(version == H5S_HYPER_VERSION_1 || version == H5S_HYPER_VERSION_3);
+ H5_CHECK_OVERFLOW(block_count, hsize_t, uint32_t);
+ UINT32ENCODE(pp, (uint32_t)block_count);
+ break;
- /* Encode each hyperslab in selection */
- H5S__hyper_serialize_helper(space->select.sel_info.hslab->span_lst, start, end, (hsize_t)0, &pp);
+ case H5S_SELECT_INFO_ENC_SIZE_8:
+ HDassert(version == H5S_HYPER_VERSION_3);
+ UINT64ENCODE(pp, block_count);
+ break;
+
+ default:
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unknown offset info size for hyperslab")
+ break;
+ } /* end switch */
+
+ if(version == H5S_HYPER_VERSION_1) {
+ len += 4; /* block_count */
+
+ /* Add 8 bytes times the rank for each hyperslab selected */
+ H5_CHECK_OVERFLOW((8 * ndims * block_count), hsize_t, size_t);
+ len += (uint32_t)(8 * ndims * block_count);
+ } /* end if */
+
+ H5S__hyper_serialize_helper(space->select.sel_info.hslab->span_lst, start, end, (hsize_t)0, enc_size, &pp);
} /* end else */
/* Encode length */
- UINT32ENCODE(lenp, (uint32_t)len); /* Store the length of the extra information */
+ if(version <= H5S_HYPER_VERSION_2)
+ UINT32ENCODE(lenp, (uint32_t)len); /* Store the length of the extra information */
/* Update encoding pointer */
*p = pp;
- FUNC_LEAVE_NOAPI(SUCCEED)
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S__hyper_serialize() */
-
+
/*--------------------------------------------------------------------------
NAME
H5S__hyper_deserialize
@@ -2299,10 +4198,8 @@ H5S__hyper_serialize(const H5S_t *space, uint8_t **p)
Deserialize the current selection from a user-provided buffer.
USAGE
herr_t H5S__hyper_deserialize(space, p)
- H5S_t *space; IN/OUT: Dataspace pointer to place
+ H5S_t **space; IN/OUT: Dataspace pointer to place
selection into
- uint32_t version IN: Selection version
- uint8_t flags IN: Selection flags
uint8 **p; OUT: Pointer to buffer holding serialized
selection. Will be advanced to end of
serialized selection.
@@ -2317,82 +4214,216 @@ H5S__hyper_serialize(const H5S_t *space, uint8_t **p)
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S__hyper_deserialize(H5S_t *space, uint32_t H5_ATTR_UNUSED version, uint8_t flags,
- const uint8_t **p)
+H5S__hyper_deserialize(H5S_t **space, const uint8_t **p)
{
- unsigned rank; /* Rank of points */
- const uint8_t *pp; /* Local pointer for decoding */
- hsize_t start[H5O_LAYOUT_NDIMS]; /* Hyperslab start information */
- hsize_t block[H5O_LAYOUT_NDIMS]; /* Hyperslab block information */
- unsigned u; /* Local counting variable */
- herr_t ret_value = FAIL; /* Return value */
+ H5S_t *tmp_space = NULL; /* Pointer to actual dataspace to use,
+ either *space or a newly allocated one */
+ hsize_t dims[H5S_MAX_RANK]; /* Dimenion sizes */
+ hsize_t start[H5S_MAX_RANK]; /* hyperslab start information */
+ hsize_t block[H5S_MAX_RANK]; /* hyperslab block information */
+ uint32_t version; /* Version number */
+ uint8_t flags = 0; /* Flags */
+ uint8_t enc_size = 0; /* Encoded size of selection info */
+ unsigned rank; /* rank of points */
+ const uint8_t *pp; /* Local pointer for decoding */
+ unsigned u; /* Local counting variable */
+ herr_t ret_value=FAIL; /* return value */
FUNC_ENTER_STATIC
/* Check args */
- HDassert(space);
HDassert(p);
pp = (*p);
HDassert(pp);
- /* Deserialize slabs to select */
- /* (The header and rank have already beed decoded) */
- rank = space->extent.rank; /* Retrieve rank from space */
+ /* As part of the efforts to push all selection-type specific coding
+ to the callbacks, the coding for the allocation of a null dataspace
+ is moved from H5S_select_deserialize() in H5Sselect.c to here.
+ This is needed for decoding virtual layout in H5O__layout_decode() */
+ /* Allocate space if not provided */
+ if(!*space) {
+ if(NULL == (tmp_space = H5S_create(H5S_SIMPLE)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't create dataspace")
+ } /* end if */
+ else
+ tmp_space = *space;
+
+ /* Decode version */
+ UINT32DECODE(pp, version);
+
+ if(version >= (uint32_t)H5S_HYPER_VERSION_2) {
+ /* Decode flags */
+ flags = *(pp)++;
- /* If there is an unlimited dimension, only encode opt_unlim_diminfo */
- if(flags & H5S_SELECT_FLAG_UNLIM) {
- hsize_t stride[H5O_LAYOUT_NDIMS]; /* Hyperslab stride information */
- hsize_t count[H5O_LAYOUT_NDIMS]; /* Hyperslab count information */
+ if(version >= (uint32_t)H5S_HYPER_VERSION_3)
+ /* decode size of offset info */
+ enc_size = *(pp)++;
+ else {
+ /* Skip over the remainder of the header */
+ pp += 4;
+ enc_size = H5S_SELECT_INFO_ENC_SIZE_8;
+ } /* end else */
+
+ /* Check for unknown flags */
+ if(flags & ~H5S_SELECT_FLAG_BITS)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTLOAD, FAIL, "unknown flag for selection")
+ } /* end if */
+ else {
+ /* Skip over the remainder of the header */
+ pp += 8;
+ enc_size = H5S_SELECT_INFO_ENC_SIZE_4;
+ } /* end else */
+
+ /* Check encoded */
+ if(enc_size & ~H5S_SELECT_INFO_ENC_SIZE_BITS)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTLOAD, FAIL, "unknown size of point/offset info for selection")
+
+ /* Decode the rank of the point selection */
+ UINT32DECODE(pp,rank);
+
+ if(!*space) {
+ /* Patch the rank of the allocated dataspace */
+ (void)HDmemset(dims, 0, (size_t)rank * sizeof(dims[0]));
+ if(H5S_set_extent_simple(tmp_space, rank, dims, NULL) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't set dimensions")
+ } /* end if */
+ else
+ /* Verify the rank of the provided dataspace */
+ if(rank != tmp_space->extent.rank)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "rank of serialized selection does not match dataspace")
+
+ if(flags & H5S_HYPER_REGULAR) {
+ hsize_t stride[H5S_MAX_RANK]; /* Hyperslab stride information */
+ hsize_t count[H5S_MAX_RANK]; /* Hyperslab count information */
/* Sanity checks */
HDassert(H5S_UNLIMITED == HSIZE_UNDEF);
HDassert(version >= 2);
- /* Iterate over dimensions */
- for(u = 0; u < rank; u++) {
- /* Decode start/stride/block/count */
- UINT64DECODE(pp, start[u]);
- UINT64DECODE(pp, stride[u]);
- UINT64DECODE(pp, count[u]);
- UINT64DECODE(pp, block[u]);
- } /* end for */
+ /* Decode start/stride/block/count */
+ switch(enc_size) {
+ case H5S_SELECT_INFO_ENC_SIZE_2:
+ for(u = 0; u < tmp_space->extent.rank; u++) {
+ UINT16DECODE(pp, start[u]);
+ UINT16DECODE(pp, stride[u]);
+
+ UINT16DECODE(pp, count[u]);
+ if((uint16_t)count[u] == H5S_UINT16_MAX)
+ count[u] = H5S_UNLIMITED;
+
+ UINT16DECODE(pp, block[u]);
+ if((uint16_t)block[u] == H5S_UINT16_MAX)
+ block[u] = H5S_UNLIMITED;
+ } /* end for */
+ break;
+
+ case H5S_SELECT_INFO_ENC_SIZE_4:
+ for(u = 0; u < tmp_space->extent.rank; u++) {
+ UINT32DECODE(pp, start[u]);
+ UINT32DECODE(pp, stride[u]);
+
+ UINT32DECODE(pp, count[u]);
+ if((uint32_t)count[u] == H5S_UINT32_MAX)
+ count[u] = H5S_UNLIMITED;
+
+ UINT32DECODE(pp, block[u]);
+ if((uint32_t)block[u] == H5S_UINT32_MAX)
+ block[u] = H5S_UNLIMITED;
+ } /* end for */
+ break;
+
+ case H5S_SELECT_INFO_ENC_SIZE_8:
+ for(u = 0; u < tmp_space->extent.rank; u++) {
+ UINT64DECODE(pp, start[u]);
+ UINT64DECODE(pp, stride[u]);
+
+ UINT64DECODE(pp, count[u]);
+ if((uint64_t)count[u] == H5S_UINT64_MAX)
+ count[u] = H5S_UNLIMITED;
+
+ UINT64DECODE(pp, block[u]);
+ if((uint64_t)block[u] == H5S_UINT64_MAX)
+ block[u] = H5S_UNLIMITED;
+ } /* end for */
+ break;
+
+ default:
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unknown offset info size for hyperslab")
+ break;
+ } /* end switch */
/* Select the hyperslab to the current selection */
- if((ret_value = H5S_select_hyperslab(space, H5S_SELECT_SET, start, stride, count, block)) < 0)
+ if((ret_value = H5S_select_hyperslab(tmp_space, H5S_SELECT_SET, start, stride, count, block)) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't change selection")
} /* end if */
else {
const hsize_t *stride; /* Hyperslab stride information */
const hsize_t *count; /* Hyperslab count information */
- hsize_t end[H5O_LAYOUT_NDIMS]; /* Hyperslab end information */
- hsize_t *tstart; /* Temporary hyperslab pointers */
- hsize_t *tend; /* Temporary hyperslab pointers */
- hsize_t *tblock; /* Temporary hyperslab pointers */
- size_t num_elem; /* Number of elements in selection */
- unsigned v; /* Local counting variable */
+ hsize_t end[H5S_MAX_RANK]; /* Hyperslab end information */
+ hsize_t *tstart; /* Temporary hyperslab pointers */
+ hsize_t *tend; /* Temporary hyperslab pointers */
+ hsize_t *tblock; /* Temporary hyperslab pointers */
+ size_t num_elem; /* Number of elements in selection */
+ unsigned v; /* Local counting variable */
+
+ /* decode the number of blocks */
+ switch(enc_size) {
+ case H5S_SELECT_INFO_ENC_SIZE_2:
+ UINT16DECODE(pp, num_elem);
+ break;
- /* Decode the number of points */
- UINT32DECODE(pp, num_elem);
+ case H5S_SELECT_INFO_ENC_SIZE_4:
+ UINT32DECODE(pp, num_elem);
+ break;
+
+ case H5S_SELECT_INFO_ENC_SIZE_8:
+ UINT64DECODE(pp, num_elem);
+ break;
+
+ default:
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unknown offset info size for hyperslab")
+ break;
+ } /* end switch */
/* Set the count & stride for all blocks */
stride = count = H5S_hyper_ones_g;
/* Retrieve the coordinates from the buffer */
for(u = 0; u < num_elem; u++) {
- /* Decode the starting points */
- for(tstart = start, v = 0; v < rank; v++, tstart++)
- UINT32DECODE(pp, *tstart);
+ /* Decode the starting and ending points */
+ switch(enc_size) {
+ case H5S_SELECT_INFO_ENC_SIZE_2:
+ for(tstart = start, v = 0; v < rank; v++, tstart++)
+ UINT16DECODE(pp, *tstart);
+ for(tend = end, v = 0; v < rank; v++, tend++)
+ UINT16DECODE(pp, *tend);
+ break;
- /* Decode the ending points */
- for(tend = end, v = 0; v < rank; v++, tend++)
- UINT32DECODE(pp, *tend);
+ case H5S_SELECT_INFO_ENC_SIZE_4:
+ for(tstart = start,v = 0; v < rank; v++, tstart++)
+ UINT32DECODE(pp, *tstart);
+ for(tend = end, v = 0; v < rank; v++, tend++)
+ UINT32DECODE(pp, *tend);
+ break;
+
+ case H5S_SELECT_INFO_ENC_SIZE_8:
+ for(tstart = start, v = 0; v < rank; v++, tstart++)
+ UINT64DECODE(pp, *tstart);
+ for(tend = end, v = 0; v < rank; v++, tend++)
+ UINT64DECODE(pp, *tend);
+ break;
+
+ default:
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unknown offset info size for hyperslab")
+ break;
+ } /* end switch */
/* Change the ending points into blocks */
for(tblock = block, tstart = start, tend = end, v = 0; v < rank; v++, tstart++, tend++, tblock++)
*tblock = (*tend - *tstart) + 1;
/* Select or add the hyperslab to the current selection */
- if((ret_value = H5S_select_hyperslab(space, (u == 0 ? H5S_SELECT_SET : H5S_SELECT_OR), start, stride, count, block)) < 0)
+ if((ret_value = H5S_select_hyperslab(tmp_space, (u == 0 ? H5S_SELECT_SET : H5S_SELECT_OR), start, stride, count, block)) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't change selection")
} /* end for */
} /* end else */
@@ -2400,11 +4431,20 @@ H5S__hyper_deserialize(H5S_t *space, uint32_t H5_ATTR_UNUSED version, uint8_t fl
/* Update decoding pointer */
*p = pp;
+ /* Return space to the caller if allocated */
+ if(!*space)
+ *space = tmp_space;
+
done:
+ /* Free temporary space if not passed to caller (only happens on error) */
+ if(!*space && tmp_space)
+ if(H5S_close(tmp_space) < 0)
+ HDONE_ERROR(H5E_DATASPACE, H5E_CANTFREE, FAIL, "can't close dataspace")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S__hyper_deserialize() */
-
+
/*--------------------------------------------------------------------------
NAME
H5S__hyper_span_blocklist
@@ -2444,14 +4484,13 @@ H5S__hyper_span_blocklist(const H5S_hyper_span_info_t *spans, hsize_t start[],
hsize_t **buf)
{
const H5S_hyper_span_t *curr; /* Pointer to current hyperslab span */
- hsize_t u; /* Index variable */
herr_t ret_value = SUCCEED; /* return value */
FUNC_ENTER_STATIC
/* Sanity checks */
HDassert(spans);
- HDassert(rank < H5O_LAYOUT_NDIMS);
+ HDassert(rank < H5S_MAX_RANK);
HDassert(start);
HDassert(end);
HDassert(startblock);
@@ -2482,19 +4521,19 @@ H5S__hyper_span_blocklist(const H5S_hyper_span_info_t *spans, hsize_t start[],
/* Encode all the previous dimensions starting & ending points */
/* Copy previous starting points */
- for(u = 0; u < rank; u++, (*buf)++)
- HDmemcpy(*buf, &start[u], sizeof(hsize_t));
+ H5MM_memcpy(*buf, start, rank * sizeof(hsize_t));
+ (*buf) += rank;
/* Copy starting point for this span */
- HDmemcpy(*buf, &curr->low, sizeof(hsize_t));
+ **buf = curr->low;
(*buf)++;
/* Copy previous ending points */
- for(u = 0; u < rank; u++, (*buf)++)
- HDmemcpy(*buf, &end[u], sizeof(hsize_t));
+ H5MM_memcpy(*buf, end, rank * sizeof(hsize_t));
+ (*buf) += rank;
- /* Copy starting point for this span */
- HDmemcpy(*buf, &curr->high, sizeof(hsize_t));
+ /* Copy ending point for this span */
+ **buf = curr->high;
(*buf)++;
/* Decrement the number of blocks processed */
@@ -2510,7 +4549,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S__hyper_span_blocklist() */
-
+
/*--------------------------------------------------------------------------
NAME
H5S__get_select_hyper_blocklist
@@ -2542,7 +4581,8 @@ done:
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S__get_select_hyper_blocklist(H5S_t *space, hbool_t internal, hsize_t startblock, hsize_t numblocks, hsize_t *buf)
+H5S__get_select_hyper_blocklist(H5S_t *space, hsize_t startblock,
+ hsize_t numblocks, hsize_t *buf)
{
herr_t ret_value = SUCCEED; /* Return value */
@@ -2552,11 +4592,18 @@ H5S__get_select_hyper_blocklist(H5S_t *space, hbool_t internal, hsize_t startblo
HDassert(buf);
HDassert(space->select.sel_info.hslab->unlim_dim < 0);
+ /* Attempt to rebuild diminfo if it is invalid and has not been confirmed
+ * to be impossible.
+ */
+ if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_NO)
+ H5S__hyper_rebuild(space);
+
/* Check for a "regular" hyperslab selection */
- if(space->select.sel_info.hslab->diminfo_valid) {
+ if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) {
const H5S_hyper_dim_t *diminfo; /* Alias for dataspace's diminfo information */
- hsize_t tmp_count[H5O_LAYOUT_NDIMS]; /* Temporary hyperslab counts */
- hsize_t offset[H5O_LAYOUT_NDIMS]; /* Offset of element in dataspace */
+ hsize_t tmp_count[H5S_MAX_RANK]; /* Temporary hyperslab counts */
+ hsize_t offset[H5S_MAX_RANK]; /* Offset of element in dataspace */
+ hsize_t end[H5S_MAX_RANK]; /* End of elements in dataspace */
unsigned fast_dim; /* Rank of the fastest changing dimension for the dataspace */
unsigned ndims; /* Rank of the dataspace */
hbool_t done; /* Whether we are done with the iteration */
@@ -2567,31 +4614,25 @@ H5S__get_select_hyper_blocklist(H5S_t *space, hbool_t internal, hsize_t startblo
fast_dim = ndims - 1;
/* Check which set of dimension information to use */
- if(internal)
+ if(space->select.sel_info.hslab->unlim_dim >= 0)
/*
- * Use the "optimized dimension information" to pass back information
- * on the blocks set, not the "application information".
+ * There is an unlimited dimension so we must use diminfo.opt as
+ * it has been "clipped" to the current extent.
*/
- diminfo = space->select.sel_info.hslab->opt_diminfo;
+ diminfo = space->select.sel_info.hslab->diminfo.opt;
else
- if(space->select.sel_info.hslab->unlim_dim >= 0)
- /*
- * There is an unlimited dimension so we must use opt_diminfo as
- * it has been "clipped" to the current extent.
- */
- diminfo = space->select.sel_info.hslab->opt_diminfo;
- else
- /*
- * Use the "application dimension information" to pass back to
- * the user the blocks they set, not the optimized, internal
- * information.
- */
- diminfo = space->select.sel_info.hslab->app_diminfo;
+ /*
+ * Use the "application dimension information" to pass back to
+ * the user the blocks they set, not the optimized, internal
+ * information.
+ */
+ diminfo = space->select.sel_info.hslab->diminfo.app;
/* Build the tables of count sizes as well as the initial offset */
for(u = 0; u < ndims; u++) {
tmp_count[u] = diminfo[u].count;
offset[u] = diminfo[u].start;
+ end[u] = diminfo[u].start + (diminfo[u].block - 1);
} /* end for */
/* We're not done with the iteration */
@@ -2599,31 +4640,45 @@ H5S__get_select_hyper_blocklist(H5S_t *space, hbool_t internal, hsize_t startblo
/* Go iterate over the hyperslabs */
while(!done && numblocks > 0) {
- hsize_t temp_off; /* Offset in a given dimension */
+ /* Skip over initial blocks */
+ if(startblock > 0) {
+ /* Skip all blocks in row */
+ if(startblock >= tmp_count[fast_dim]) {
+ startblock -= tmp_count[fast_dim];
+ tmp_count[fast_dim] = 0;
+ } /* end if */
+ else {
+ /* Move the offset to the next sequence to start */
+ offset[fast_dim] += diminfo[fast_dim].stride * startblock;
+ end[fast_dim] += diminfo[fast_dim].stride * startblock;
+
+ /* Decrement the block count */
+ tmp_count[fast_dim] -= startblock;
+
+ /* Done with starting blocks */
+ startblock = 0;
+ } /* end else */
+ } /* end if */
/* Iterate over the blocks in the fastest dimension */
while(tmp_count[fast_dim] > 0 && numblocks > 0) {
+ /* Sanity check */
+ HDassert(startblock == 0);
- /* Check if we should copy this block information */
- if(startblock == 0) {
- /* Copy the starting location */
- HDmemcpy(buf, offset, sizeof(hsize_t) * ndims);
- buf += ndims;
+ /* Copy the starting location */
+ H5MM_memcpy(buf, offset, sizeof(hsize_t) * ndims);
+ buf += ndims;
- /* Compute the ending location */
- HDmemcpy(buf, offset, sizeof(hsize_t) * ndims);
- for(u = 0; u < ndims; u++)
- buf[u] += (diminfo[u].block - 1);
- buf += ndims;
+ /* Compute the ending location */
+ H5MM_memcpy(buf, end, sizeof(hsize_t) * ndims);
+ buf += ndims;
- /* Decrement the number of blocks to retrieve */
- numblocks--;
- } /* end if */
- else
- startblock--;
+ /* Decrement the number of blocks to retrieve */
+ numblocks--;
/* Move the offset to the next sequence to start */
offset[fast_dim] += diminfo[fast_dim].stride;
+ end[fast_dim] += diminfo[fast_dim].stride;
/* Decrement the block count */
tmp_count[fast_dim]--;
@@ -2646,28 +4701,29 @@ H5S__get_select_hyper_blocklist(H5S_t *space, hbool_t internal, hsize_t startblo
if(tmp_count[temp_dim] > 0)
break;
+ /* Reset the block count in this dimension */
+ tmp_count[temp_dim] = diminfo[temp_dim].count;
+
/* Check for getting out of iterator */
if(temp_dim == 0)
done = TRUE;
- /* Reset the block count in this dimension */
- tmp_count[temp_dim] = diminfo[temp_dim].count;
-
/* Wrapped a dimension, go up to next dimension */
temp_dim--;
} /* end while */
} /* end if */
- /* Re-compute offset array */
- for(u = 0; u < ndims; u++) {
- temp_off = diminfo[u].start + diminfo[u].stride * (diminfo[u].count - tmp_count[u]);
- offset[u] = temp_off;
- } /* end for */
+ /* Re-compute offset & end arrays */
+ if(!done)
+ for(u = 0; u < ndims; u++) {
+ offset[u] = diminfo[u].start + diminfo[u].stride * (diminfo[u].count - tmp_count[u]);
+ end[u] = offset[u] + (diminfo[u].block - 1);
+ } /* end for */
} /* end while */
} /* end if */
else {
- hsize_t start[H5O_LAYOUT_NDIMS]; /* Location of start of hyperslab */
- hsize_t end[H5O_LAYOUT_NDIMS]; /* Location of end of hyperslab */
+ hsize_t start[H5S_MAX_RANK]; /* Location of start of hyperslab */
+ hsize_t end[H5S_MAX_RANK]; /* Location of end of hyperslab */
ret_value = H5S__hyper_span_blocklist(space->select.sel_info.hslab->span_lst, start, end, (hsize_t)0, &startblock, &numblocks, &buf);
} /* end else */
@@ -2675,7 +4731,7 @@ H5S__get_select_hyper_blocklist(H5S_t *space, hbool_t internal, hsize_t startblo
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S__get_select_hyper_blocklist() */
-
+
/*--------------------------------------------------------------------------
NAME
H5Sget_select_hyper_blocklist
@@ -2688,7 +4744,7 @@ H5S__get_select_hyper_blocklist(H5S_t *space, hbool_t internal, hsize_t startblo
hsize_t numblocks; IN: Number of hyperslab blocks to get
hsize_t buf[]; OUT: List of hyperslab blocks selected
RETURNS
- Non-negative on success, negative on failure
+ Non-negative on success/Negative on failure
DESCRIPTION
Puts a list of the hyperslab blocks into the user's buffer. The blocks
start with the 'startblock'th block in the list of blocks and put
@@ -2728,7 +4784,7 @@ H5Sget_select_hyper_blocklist(hid_t spaceid, hsize_t startblock,
/* Go get the correct number of blocks */
if(numblocks > 0)
- ret_value = H5S__get_select_hyper_blocklist(space, 0, startblock, numblocks, buf);
+ ret_value = H5S__get_select_hyper_blocklist(space, startblock, numblocks, buf);
else
ret_value = SUCCEED; /* Successfully got 0 blocks... */
@@ -2736,77 +4792,7 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Sget_select_hyper_blocklist() */
-
-/*--------------------------------------------------------------------------
- NAME
- H5S_hyper_bounds_helper
- PURPOSE
- Gets the bounding box containing the selection.
- USAGE
- htri_t H5S_hyper_bounds_helper(spans, offset, rank);
- const H5S_hyper_span_info_t *spans; IN: Pointer to current hyperslab span tree
- const hssize_t *offset; IN: Pointer to offset array
- hsize_t rank; IN: Current rank looking at
- hsize_t *start; OUT: Start array bounds
- hsize_t *end; OUT: End array bounds
- RETURNS
- Non-negative on success, negative on failure
- DESCRIPTION
- Retrieves the bounding box containing the current selection and places
- it into the user's buffers. The start and end buffers must be large
- enough to hold the dataspace rank number of coordinates. The bounding box
- exactly contains the selection, ie. if a 2-D element selection is currently
- defined with the following points: (4,5), (6,8) (10,7), the bounding box
- with be (4, 5), (10, 8).
- The bounding box calculations _does_ include the current offset of the
- selection within the dataspace extent.
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
-static herr_t
-H5S_hyper_bounds_helper(const H5S_hyper_span_info_t *spans, const hssize_t *offset, hsize_t rank, hsize_t *start, hsize_t *end)
-{
- H5S_hyper_span_t *curr; /* Hyperslab information nodes */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT
- HDassert(spans);
- HDassert(offset);
- HDassert(rank < H5O_LAYOUT_NDIMS);
- HDassert(start);
- HDassert(end);
-
- /* Check each point to determine whether selection+offset is within extent */
- curr=spans->head;
- while(curr!=NULL) {
- /* Check for offset moving selection negative */
- if(((hssize_t)curr->low + offset[rank]) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "offset moves selection out of bounds")
-
- /* Check if the current span extends the bounding box */
- if((curr->low + (hsize_t)offset[rank]) < start[rank])
- start[rank] = curr->low + (hsize_t)offset[rank];
- if((curr->high + (hsize_t)offset[rank]) > end[rank])
- end[rank] = curr->high + (hsize_t)offset[rank];
-
- /* Recurse if this node has down spans */
- if(curr->down != NULL) {
- if(H5S_hyper_bounds_helper(curr->down, offset, (rank + 1), start, end) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADSELECT, FAIL, "failure in lower dimension")
- } /* end if */
-
- /* Advance to next node */
- curr = curr->next;
- } /* end while */
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5S_hyper_bounds_helper() */
-
-
/*--------------------------------------------------------------------------
NAME
H5S__hyper_bounds
@@ -2836,8 +4822,7 @@ done:
static herr_t
H5S__hyper_bounds(const H5S_t *space, hsize_t *start, hsize_t *end)
{
- unsigned rank; /* Dataspace rank */
- unsigned i; /* index variable */
+ const hsize_t *low_bounds, *high_bounds; /* Pointers to the correct pair of low & high bounds */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC
@@ -2847,43 +4832,48 @@ H5S__hyper_bounds(const H5S_t *space, hsize_t *start, hsize_t *end)
HDassert(start);
HDassert(end);
- /* Set the start and end arrays up */
- rank = space->extent.rank;
- for(i = 0; i < rank; i++) {
- start[i] = HSIZET_MAX;
- end[i] = 0;
- } /* end for */
+ /* Check which set of low & high bounds we should be using */
+ if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) {
+ low_bounds = space->select.sel_info.hslab->diminfo.low_bounds;
+ high_bounds = space->select.sel_info.hslab->diminfo.high_bounds;
+ } /* end if */
+ else {
+ low_bounds = space->select.sel_info.hslab->span_lst->low_bounds;
+ high_bounds = space->select.sel_info.hslab->span_lst->high_bounds;
+ } /* end else */
- /* Check for a "regular" hyperslab selection */
- if(space->select.sel_info.hslab->diminfo_valid) {
- const H5S_hyper_dim_t *diminfo = space->select.sel_info.hslab->opt_diminfo; /* local alias for diminfo */
+ /* Check for offset set */
+ if(space->select.offset_changed) {
+ unsigned u; /* Local index variable */
+
+ /* Loop over dimensions */
+ for(u = 0; u < space->extent.rank; u++) {
+ /* Sanity check */
+ HDassert(low_bounds[u] <= high_bounds[u]);
- /* Check each dimension */
- for(i = 0; i < rank; i++) {
/* Check for offset moving selection negative */
- if((space->select.offset[i] + (hssize_t)diminfo[i].start) < 0)
+ if(((hssize_t)low_bounds[u] + space->select.offset[u]) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "offset moves selection out of bounds")
- /* Compute the smallest location in this dimension */
- start[i] = diminfo[i].start + (hsize_t)space->select.offset[i];
-
- /* Compute the largest location in this dimension */
- if((int)i == space->select.sel_info.hslab->unlim_dim)
- end[i] = H5S_UNLIMITED;
+ /* Set the low & high bounds in this dimension */
+ start[u] = (hsize_t)((hssize_t)low_bounds[u] + space->select.offset[u]);
+ if((int)u == space->select.sel_info.hslab->unlim_dim)
+ end[u] = H5S_UNLIMITED;
else
- end[i] = diminfo[i].start + diminfo[i].stride * (diminfo[i].count - 1) + (diminfo[i].block - 1) + (hsize_t)space->select.offset[i];
+ end[u] = (hsize_t)((hssize_t)high_bounds[u] + space->select.offset[u]);
} /* end for */
} /* end if */
else {
- /* Call the recursive routine to get the bounds for the span tree */
- ret_value = H5S_hyper_bounds_helper(space->select.sel_info.hslab->span_lst, space->select.offset, (hsize_t)0, start, end);
- } /* end if */
+ /* Offset vector is still zeros, just copy low & high bounds */
+ H5MM_memcpy(start, low_bounds, sizeof(hsize_t) * space->extent.rank);
+ H5MM_memcpy(end, high_bounds, sizeof(hsize_t) * space->extent.rank);
+ } /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S__hyper_bounds() */
-
+
/*--------------------------------------------------------------------------
NAME
H5S__hyper_offset
@@ -2928,8 +4918,9 @@ H5S__hyper_offset(const H5S_t *space, hsize_t *offset)
dim_size = space->extent.size;
/* Check for a "regular" hyperslab selection */
- if(space->select.sel_info.hslab->diminfo_valid) {
- const H5S_hyper_dim_t *diminfo = space->select.sel_info.hslab->opt_diminfo; /* Local alias for diminfo */
+ /* (No need to rebuild the dimension info yet -QAK) */
+ if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) {
+ const H5S_hyper_dim_t *diminfo = space->select.sel_info.hslab->diminfo.opt; /* Local alias for diminfo */
/* Loop through starting coordinates, calculating the linear offset */
accum = 1;
@@ -2991,7 +4982,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S__hyper_offset() */
-
+
/*--------------------------------------------------------------------------
NAME
H5S__hyper_unlim_dim
@@ -3018,7 +5009,7 @@ H5S__hyper_unlim_dim(const H5S_t *space)
FUNC_LEAVE_NOAPI(space->select.sel_info.hslab->unlim_dim);
} /* end H5S__hyper_unlim_dim() */
-
+
/*--------------------------------------------------------------------------
NAME
H5S__hyper_num_elem_non_unlim
@@ -3060,7 +5051,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S__hyper_num_elem_non_unlim() */
-
+
/*--------------------------------------------------------------------------
NAME
H5S__hyper_is_contiguous
@@ -3079,7 +5070,7 @@ done:
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-static htri_t
+static H5_ATTR_PURE htri_t
H5S__hyper_is_contiguous(const H5S_t *space)
{
hbool_t small_contiguous, /* Flag for small contiguous block */
@@ -3092,8 +5083,9 @@ H5S__hyper_is_contiguous(const H5S_t *space)
HDassert(space);
/* Check for a "regular" hyperslab selection */
- if(space->select.sel_info.hslab->diminfo_valid) {
- const H5S_hyper_dim_t *diminfo=space->select.sel_info.hslab->opt_diminfo; /* local alias for diminfo */
+ /* (No need to rebuild the dimension info yet -QAK) */
+ if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) {
+ const H5S_hyper_dim_t *diminfo=space->select.sel_info.hslab->diminfo.opt; /* local alias for diminfo */
/*
* For a regular hyperslab to be contiguous, it must have only one
@@ -3109,8 +5101,8 @@ H5S__hyper_is_contiguous(const H5S_t *space)
*/
/* Initialize flags */
- large_contiguous = TRUE; /* assume true and reset if the dimensions don't match */
- small_contiguous = FALSE; /* assume false initially */
+ large_contiguous = TRUE; /* assume true and reset if the dimensions don't match */
+ small_contiguous = FALSE; /* assume false initially */
/* Check for a "large contigous" block */
for(u = 0; u < space->extent.rank; u++) {
@@ -3149,14 +5141,14 @@ H5S__hyper_is_contiguous(const H5S_t *space)
/*
* For a hyperslab to be contiguous, it must have only one block and
- * (either it's size must be the same as the dataspace extent's in all
- * but the slowest changing dimension
- * OR
- * block size must be 1 in all but the fastest changing dimension).
+ * either it's size must be the same as the dataspace extent's in all
+ * but the slowest changing dimension
+ * OR
+ * block size must be 1 in all but the fastest changing dimension.
*/
/* Initialize flags */
- large_contiguous = TRUE; /* assume true and reset if the dimensions don't match */
- small_contiguous = FALSE; /* assume false initially */
+ large_contiguous = TRUE; /* assume true and reset if the dimensions don't match */
+ small_contiguous = FALSE; /* assume false initially */
/* Get information for slowest changing information */
spans = space->select.sel_info.hslab->span_lst;
@@ -3245,7 +5237,7 @@ H5S__hyper_is_contiguous(const H5S_t *space)
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S__hyper_is_contiguous() */
-
+
/*--------------------------------------------------------------------------
NAME
H5S__hyper_is_single
@@ -3264,7 +5256,7 @@ H5S__hyper_is_contiguous(const H5S_t *space)
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-static htri_t
+static H5_ATTR_PURE htri_t
H5S__hyper_is_single(const H5S_t *space)
{
htri_t ret_value = TRUE; /* return value */
@@ -3274,7 +5266,10 @@ H5S__hyper_is_single(const H5S_t *space)
HDassert(space);
/* Check for a "single" hyperslab selection */
- if(space->select.sel_info.hslab->diminfo_valid) {
+ /* (No need to rebuild the dimension info yet, since the span-tree
+ * algorithm is fast -QAK)
+ */
+ if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) {
unsigned u; /* index variable */
/*
@@ -3283,10 +5278,9 @@ H5S__hyper_is_single(const H5S_t *space)
*/
/* Check for a single block */
- for(u = 0; u < space->extent.rank; u++) {
- if(space->select.sel_info.hslab->opt_diminfo[u].count > 1)
+ for(u = 0; u < space->extent.rank; u++)
+ if(space->select.sel_info.hslab->diminfo.opt[u].count > 1)
HGOTO_DONE(FALSE)
- } /* end for */
} /* end if */
else {
H5S_hyper_span_info_t *spans; /* Hyperslab span info node */
@@ -3316,7 +5310,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S__hyper_is_single() */
-
+
/*--------------------------------------------------------------------------
NAME
H5S__hyper_is_regular
@@ -3333,7 +5327,6 @@ done:
This is primarily used for reading the entire selection in one swoop.
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
- Doesn't check for "regular" hyperslab selections composed of spans
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
@@ -3347,8 +5340,14 @@ H5S__hyper_is_regular(const H5S_t *space)
/* Check args */
HDassert(space);
+ /* Attempt to rebuild diminfo if it is invalid and has not been confirmed
+ * to be impossible.
+ */
+ if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_NO)
+ H5S__hyper_rebuild((H5S_t *)space); /* Casting away const OK -NAF */
+
/* Only simple check for regular hyperslabs for now... */
- if(space->select.sel_info.hslab->diminfo_valid)
+ if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES)
ret_value = TRUE;
else
ret_value = FALSE;
@@ -3356,98 +5355,400 @@ H5S__hyper_is_regular(const H5S_t *space)
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S__hyper_is_regular() */
-
+
/*--------------------------------------------------------------------------
NAME
- H5S__hyper_release
+ H5S__hyper_spans_shape_same_helper
PURPOSE
- Release hyperslab selection information for a dataspace
+ Helper routine to check if two hyperslab span trees are the same shape
USAGE
- herr_t H5S__hyper_release(space)
- H5S_t *space; IN: Pointer to dataspace
+ hbool_t H5S__hyper_spans_shape_same_helper(span1, span2, offset, rest_zeros)
+ H5S_hyper_span_info_t *span_info1; IN: First span tree to compare
+ H5S_hyper_span_info_t *span_info2; IN: Second span tree to compare
+ hssize_t offset[]; IN: Offset between the span trees
+ hbool_t rest_zeros[]; IN: Array of flags which indicate
+ the rest of the offset[] array
+ is zero values.
RETURNS
- Non-negative on success/Negative on failure
+ TRUE (1) or FALSE (0) on success, can't fail
DESCRIPTION
- Releases all hyperslab selection information for a dataspace
+ Compare two hyperslab span trees to determine if they refer to a selection
+ with the same shape, with a possible (constant) offset between their
+ elements. Very similar to H5S__hyper_cmp_spans, except the selected
+ elements can be offset by a vector.
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
EXAMPLES
REVISION LOG
- * Robb Matzke, 1998-08-25
- * The fields which are freed are set to NULL to prevent them from being
- * freed again later. This fixes some allocation problems where
- * changing the hyperslab selection of one dataspace causes a core dump
- * when closing some other dataspace.
--------------------------------------------------------------------------*/
-static herr_t
-H5S__hyper_release(H5S_t *space)
+static H5_ATTR_PURE hbool_t
+H5S__hyper_spans_shape_same_helper(const H5S_hyper_span_info_t *span_info1,
+ const H5S_hyper_span_info_t *span_info2, hssize_t offset[],
+ hbool_t rest_zeros[])
{
- herr_t ret_value = SUCCEED;
+ hbool_t ret_value = TRUE; /* Return value */
+
+ FUNC_ENTER_PACKAGE_NOERR
+
+ /* Sanity checks */
+ HDassert(span_info1);
+ HDassert(span_info2);
+ HDassert(offset);
+ HDassert(rest_zeros);
+
+ /* Compare low & high bounds for this span list */
+ /* (Could compare lower dimensions also, but not certain if
+ * that's worth it. - QAK, 2019/01/23)
+ */
+ if((hsize_t)((hssize_t)span_info1->low_bounds[0] + offset[0]) != span_info2->low_bounds[0])
+ HGOTO_DONE(FALSE)
+ else if((hsize_t)((hssize_t)span_info1->high_bounds[0] + offset[0]) != span_info2->high_bounds[0])
+ HGOTO_DONE(FALSE)
+ else {
+ const H5S_hyper_span_t *span1;
+ const H5S_hyper_span_t *span2;
+
+ /* Get the pointers to the actual lists of spans */
+ span1 = span_info1->head;
+ span2 = span_info2->head;
+
+ /* Sanity checking */
+ HDassert(span1);
+ HDassert(span2);
+
+ /* infinite loop which must be broken out of */
+ while(1) {
+ /* Check for both spans being NULL */
+ if(span1 == NULL && span2 == NULL)
+ HGOTO_DONE(TRUE)
+
+ /* Check for one span being NULL */
+ if(span1 == NULL || span2 == NULL)
+ HGOTO_DONE(FALSE)
+
+ /* Check if the actual low & high span information is the same */
+ if((hsize_t)((hssize_t)span1->low + offset[0]) != span2->low || (hsize_t)((hssize_t)span1->high + offset[0]) != span2->high)
+ HGOTO_DONE(FALSE)
+
+ /* Check for down tree for this span */
+ if(span1->down != NULL || span2->down != NULL) {
+ /* If the rest of the span trees have a zero offset, use the faster comparison routine */
+ if(rest_zeros[0]) {
+ if(!H5S__hyper_cmp_spans(span1->down, span2->down))
+ HGOTO_DONE(FALSE)
+ else {
+ /* Keep going... */
+ } /* end else */
+ } /* end if */
+ else {
+ if(!H5S__hyper_spans_shape_same_helper(span1->down, span2->down, &offset[1], &rest_zeros[1]))
+ HGOTO_DONE(FALSE)
+ else {
+ /* Keep going... */
+ } /* end else */
+ } /* end else */
+ } /* end if */
+ else {
+ /* Keep going... */
+ } /* end else */
+
+ /* Advance to the next nodes in the span list */
+ span1 = span1->next;
+ span2 = span2->next;
+ } /* end while */
+ } /* end else */
+
+ /* Fall through, with default return value of 'TRUE' if spans were already visited */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S__hyper_spans_shape_same_helper() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S__hyper_spans_shape_same
+ PURPOSE
+ Check if two hyperslab span trees are the same shape
+ USAGE
+ hbool_t H5S__hyper_spans_shape_same(span1, span2)
+ H5S_hyper_span_info_t *span_info1; IN: First span tree to compare
+ H5S_hyper_span_info_t *span_info2; IN: Second span tree to compare
+ RETURNS
+ TRUE (1) or FALSE (0) on success, can't fail
+ DESCRIPTION
+ Compare two hyperslab span trees to determine if they refer to a selection
+ with the same shape. Very similar to H5S__hyper_cmp_spans, except the
+ selected elements can be offset by a vector.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static H5_ATTR_PURE hbool_t
+H5S__hyper_spans_shape_same(const H5S_hyper_span_info_t *span_info1,
+ const H5S_hyper_span_info_t *span_info2, unsigned ndims)
+{
+ const H5S_hyper_span_t *span1; /* Pointer to spans in first span tree */
+ const H5S_hyper_span_t *span2; /* Pointer to spans in second span tree */
+ hssize_t offset[H5S_MAX_RANK]; /* Offset vector for selections */
+ hbool_t rest_zeros[H5S_MAX_RANK]; /* Vector of flags to indicate when remaining offset is all zero */
+ hbool_t zero_offset; /* Whether the two selections have a non-zero offset */
+ unsigned u; /* Local index variable */
+ hbool_t ret_value = TRUE; /* Return value */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Sanity check */
+ HDassert(span_info1);
+ HDassert(span_info2);
+ HDassert(ndims > 0);
+
+ /* Initialize arrays */
+ HDmemset(offset, 0, sizeof(offset));
+ HDmemset(rest_zeros, 0, sizeof(rest_zeros));
+
+ /* Check for an offset between the two selections */
+ span1 = span_info1->head;
+ span2 = span_info2->head;
+ zero_offset = TRUE;
+ for(u = 0; u < ndims; u++) {
+ /* Check for offset in this dimension */
+ if(span1->low != span2->low) {
+ offset[u] = (hssize_t)span2->low - (hssize_t)span1->low;
+
+ /* Indicate that the offset vector is not all zeros */
+ if(zero_offset)
+ zero_offset = FALSE;
+ } /* end if */
+
+ /* Sanity check */
+ /* (Both span trees must have the same depth) */
+ HDassert((span1->down && span2->down) || (NULL == span1->down && NULL == span2->down));
+
+ /* Advance to next dimension */
+ if(span1->down) {
+ span1 = span1->down->head;
+ span2 = span2->down->head;
+ } /* end if */
+ } /* end for */
+
+ /* Check if there's a "tail" of all zeros in a non-zero offset vector */
+ if(!zero_offset) {
+ int i; /* Local index variable */
+
+ /* Find first non-zero offset, from the fastest dimension up */
+ for(i = (int)(ndims - 1); i >= 0; i--)
+ if(offset[i]) {
+ rest_zeros[i] = TRUE;
+ break;
+ } /* end if */
+
+ /* Sanity check */
+ /* (Must eventually have found a non-zero offset) */
+ HDassert(i >= 0);
+ } /* end if */
+
+ /* If the offset vector is all zero, we can use the faster span tree
+ * comparison routine. Otherwise, use a generalized version of that
+ * routine.
+ */
+ if(zero_offset)
+ ret_value = H5S__hyper_cmp_spans(span_info1, span_info2);
+ else
+ ret_value = H5S__hyper_spans_shape_same_helper(span_info1, span_info2, offset, rest_zeros);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S__hyper_spans_shape_same() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S__hyper_shape_same
+ PURPOSE
+ Check if a two hyperslab selections are the same shape
+ USAGE
+ htri_t H5S__hyper_shape_same(space1, space2)
+ const H5S_t *space1; IN: First dataspace to check
+ const H5S_t *space2; IN: Second dataspace to check
+ RETURNS
+ TRUE / FALSE / FAIL
+ DESCRIPTION
+ Checks to see if the current selection in each dataspace are the same
+ shape.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ Handles when both are regular in an efficient way, otherwise converts
+ both to span tree form (if necessary) and compares efficiently them in
+ that form.
+
+ Rank of space1 must always be >= to rank of space2.
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static htri_t
+H5S__hyper_shape_same(const H5S_t *space1, const H5S_t *space2)
+{
+ unsigned space1_rank; /* Number of dimensions of first dataspace */
+ unsigned space2_rank; /* Number of dimensions of second dataspace */
+ htri_t ret_value = TRUE; /* Return value */
FUNC_ENTER_STATIC
/* Check args */
- HDassert(space && H5S_SEL_HYPERSLABS == H5S_GET_SELECT_TYPE(space));
+ HDassert(space1);
+ HDassert(space2);
- /* Reset the number of points selected */
- space->select.num_elem = 0;
+ /* Get dataspace ranks */
+ space1_rank = space1->extent.rank;
+ space2_rank = space2->extent.rank;
- /* Release irregular hyperslab information */
- if(space->select.sel_info.hslab) {
- if(space->select.sel_info.hslab->span_lst != NULL)
- if(H5S__hyper_free_span_info(space->select.sel_info.hslab->span_lst) < 0)
- HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "failed to release hyperslab spans")
+ /* Sanity check */
+ HDassert(space1_rank >= space2_rank);
+ HDassert(space2_rank > 0);
+
+ /* Rebuild diminfo if it is invalid and has not been confirmed to be
+ * impossible */
+ if(space1->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_NO)
+ H5S__hyper_rebuild((H5S_t *)space1); /* Casting away const OK -QAK */
+ if(space2->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_NO)
+ H5S__hyper_rebuild((H5S_t *)space2); /* Casting away const OK -QAK */
+
+ /* If both are regular hyperslabs, compare their diminfo values */
+ if(space1->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES
+ && space2->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) {
+ int space1_dim; /* Current dimension in first dataspace */
+ int space2_dim; /* Current dimension in second dataspace */
+
+ /* Initialize dimensions */
+ space1_dim = (int)space1_rank - 1;
+ space2_dim = (int)space2_rank - 1;
+
+ /* Check that the shapes are the same in the common dimensions, and that
+ * block == 1 in all dimensions that appear only in space1.
+ */
+ while(space2_dim >= 0) {
+ if(space1->select.sel_info.hslab->diminfo.opt[space1_dim].stride !=
+ space2->select.sel_info.hslab->diminfo.opt[space2_dim].stride)
+ HGOTO_DONE(FALSE)
- /* Release space for the hyperslab selection information */
- space->select.sel_info.hslab = H5FL_FREE(H5S_hyper_sel_t, space->select.sel_info.hslab);
+ if(space1->select.sel_info.hslab->diminfo.opt[space1_dim].count !=
+ space2->select.sel_info.hslab->diminfo.opt[space2_dim].count)
+ HGOTO_DONE(FALSE)
+
+ if(space1->select.sel_info.hslab->diminfo.opt[space1_dim].block !=
+ space2->select.sel_info.hslab->diminfo.opt[space2_dim].block)
+ HGOTO_DONE(FALSE)
+
+ space1_dim--;
+ space2_dim--;
+ } /* end while */
+
+ while(space1_dim >= 0) {
+ if(space1->select.sel_info.hslab->diminfo.opt[space1_dim].block != 1)
+ HGOTO_DONE(FALSE)
+
+ space1_dim--;
+ } /* end while */
} /* end if */
+ /* If both aren't regular, use fast irregular comparison */
+ else {
+ H5S_hyper_span_info_t *spans1; /* Hyperslab spans for first dataspace */
+
+ /* Make certain that both selections have span trees */
+ if(NULL == space1->select.sel_info.hslab->span_lst)
+ if(H5S__hyper_generate_spans((H5S_t *)space1) < 0) /* Casting away const OK -QAK */
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "can't construct span tree for hyperslab selection")
+ if(NULL == space2->select.sel_info.hslab->span_lst)
+ if(H5S__hyper_generate_spans((H5S_t *)space2) < 0) /* Casting away const OK -QAK */
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "can't construct span tree for hyperslab selection")
+
+ /* If rank of space A is different (guaranteed greater) than
+ * rank of space B, walk down the span tree, verifying
+ * that the block size is 1 on the way down.
+ */
+ if(space1_rank > space2_rank) {
+ unsigned diff_rank = space1_rank - space2_rank; /* Difference in ranks */
+
+ /* Walk down the dimensions */
+ spans1 = space1->select.sel_info.hslab->span_lst;
+ while(diff_rank > 0) {
+ H5S_hyper_span_t *span; /* Span for this dimension */
+
+ /* Get pointer to first span in tree */
+ span = spans1->head;
+
+ /* Check for more spans in this dimension */
+ if(span->next)
+ HGOTO_DONE(FALSE)
+
+ /* Check for span size > 1 element */
+ if(span->low != span->high)
+ HGOTO_DONE(FALSE)
+
+ /* Walk down to the next dimension */
+ spans1 = span->down;
+ diff_rank--;
+ } /* end while */
+
+ /* Sanity check */
+ HDassert(spans1);
+ } /* end if */
+ else
+ spans1 = space1->select.sel_info.hslab->span_lst;
+
+ /* Compare the span trees */
+ ret_value = H5S__hyper_spans_shape_same(spans1, space2->select.sel_info.hslab->span_lst, space2_rank);
+ } /* end else */
+
+ /* Fall through with 'TRUE' value, if not set earlier */
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5S__hyper_release() */
+} /* end H5S__hyper_shape_same() */
+
-
/*--------------------------------------------------------------------------
NAME
- H5S__hyper_recover_span
+ H5S__hyper_release
PURPOSE
- Recover a generated span, if appropriate
+ Release hyperslab selection information for a dataspace
USAGE
- herr_t H5S__hyper_recover_span(recover, curr_span, next_span)
- unsigned *recover; IN/OUT: Pointer recover flag
- H5S_hyper_span_t **curr_span; IN/OUT: Pointer to current span in list
- H5S_hyper_span_t *next_span; IN: Pointer to next span
+ herr_t H5S__hyper_release(space)
+ H5S_t *space; IN: Pointer to dataspace
RETURNS
- Non-negative on success, negative on failure
+ Non-negative on success/Negative on failure
DESCRIPTION
- Check if the current span needs to be recovered and free it if so.
- Set the current span to the next span in any case.
+ Releases all hyperslab selection information for a dataspace
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S__hyper_recover_span(hbool_t *recover, H5S_hyper_span_t **curr_span, H5S_hyper_span_t *next_span)
+H5S__hyper_release(H5S_t *space)
{
FUNC_ENTER_STATIC_NOERR
- HDassert(recover);
- HDassert(curr_span);
+ /* Check args */
+ HDassert(space && H5S_SEL_HYPERSLABS == H5S_GET_SELECT_TYPE(space));
- /* Check if the span should be recovered */
- if(*recover) {
- H5S__hyper_free_span(*curr_span);
- *recover = FALSE;
- } /* end if */
+ /* Reset the number of points selected */
+ space->select.num_elem = 0;
- /* Set the current span to next span */
- *curr_span = next_span;
+ /* Release irregular hyperslab information */
+ if(space->select.sel_info.hslab) {
+ if(space->select.sel_info.hslab->span_lst != NULL)
+ H5S__hyper_free_span_info(space->select.sel_info.hslab->span_lst);
+
+ /* Release space for the hyperslab selection information */
+ space->select.sel_info.hslab = H5FL_FREE(H5S_hyper_sel_t, space->select.sel_info.hslab);
+ } /* end if */
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5S__hyper_recover_span() */
+} /* end H5S__hyper_release() */
+
-
/*--------------------------------------------------------------------------
NAME
H5S__hyper_coord_to_span
@@ -3458,7 +5759,7 @@ H5S__hyper_recover_span(hbool_t *recover, H5S_hyper_span_t **curr_span, H5S_hype
unsigned rank; IN: Number of dimensions of coordinate
hsize_t *coords; IN: Location of element
RETURNS
- Non-negative on success, negative on failure
+ Non-NULL pointer to new span tree on success, NULL on failure
DESCRIPTION
Create a span tree for a single element
GLOBAL VARIABLES
@@ -3480,14 +5781,20 @@ H5S__hyper_coord_to_span(unsigned rank, const hsize_t *coords)
/* Search for location to insert new element in tree */
if(rank > 1) {
- /* Allocate a span info node */
- if(NULL == (down = H5FL_CALLOC(H5S_hyper_span_info_t)))
+ /* Allocate a span info node for coordinates below this one */
+ if(NULL == (down = H5S__hyper_new_span_info(rank - 1)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, NULL, "can't allocate hyperslab span")
+ /* Set the low & high bounds for this span info node */
+ H5MM_memcpy(down->low_bounds, &coords[1], (rank - 1) * sizeof(hsize_t));
+ H5MM_memcpy(down->high_bounds, &coords[1], (rank - 1) * sizeof(hsize_t));
/* Build span tree for coordinates below this one */
if(NULL == (down->head = H5S__hyper_coord_to_span(rank - 1, &coords[1])))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, NULL, "can't allocate hyperslab span")
+
+ /* Update the tail pointer of the down dimension, and it's a single span element */
+ down->tail = down->head;
} /* end if */
/* Build span for this coordinate */
@@ -3504,17 +5811,18 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S__hyper_coord_to_span() */
-
+
/*--------------------------------------------------------------------------
NAME
H5S__hyper_add_span_element_helper
PURPOSE
- Add a single element to a span tree
+ Helper routine to add a single element to a span tree
USAGE
- herr_t H5S_hyper_add_span_element_helper(prev_span, span_tree, rank, coords)
+ herr_t H5S__hyper_add_span_element_helper(span_tree, rank, coords, first_dim_modified)
H5S_hyper_span_info_t *span_tree; IN/OUT: Pointer to span tree to append to
unsigned rank; IN: Number of dimensions of coordinates
- hsize_t *coords; IN: Location of element to add to span tree
+ hsize_t *coords; IN: Location of element to add to span tree
+ int *first_dim_modified; IN: Index of the first dimension modified
RETURNS
Non-negative on success, negative on failure
DESCRIPTION
@@ -3527,13 +5835,9 @@ done:
--------------------------------------------------------------------------*/
static herr_t
H5S__hyper_add_span_element_helper(H5S_hyper_span_info_t *span_tree,
- unsigned rank, const hsize_t *coords)
+ unsigned rank, const hsize_t *coords, int *first_dim_modified)
{
- H5S_hyper_span_info_t *tspan_info; /* Temporary pointer to span info */
- H5S_hyper_span_info_t *prev_span_info; /* Pointer to span info for level above current position */
- H5S_hyper_span_t *tmp_span; /* Temporary pointer to a span */
- H5S_hyper_span_t *tmp2_span; /* Another temporary pointer to a span */
- H5S_hyper_span_t *new_span; /* New span created for element */
+ H5S_hyper_span_t *tail_span; /* Pointer to the tail span of one dimension */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC
@@ -3542,173 +5846,203 @@ H5S__hyper_add_span_element_helper(H5S_hyper_span_info_t *span_tree,
HDassert(span_tree);
HDassert(rank > 0);
HDassert(coords);
+ HDassert(first_dim_modified);
/* Get pointer to last span in span tree */
- tspan_info=span_tree;
- if(span_tree->scratch)
- tmp_span=(H5S_hyper_span_t *)span_tree->scratch;
- else {
- tmp_span=span_tree->head;
- HDassert(tmp_span);
- span_tree->scratch=(H5S_hyper_span_info_t *)tmp_span;
- } /* end else */
-
- /* Find last span tree which includes a portion of the coordinate */
- prev_span_info=NULL;
- while(coords[0]>=tmp_span->low && coords[0]<=tmp_span->high) {
- /* Move rank & coordinate offset down a dimension */
- rank--;
- coords++;
+ tail_span = span_tree->tail;
+
+ /* Determine if tail span includes a portion of the coordinate */
+ /* (Should never happen with the lowest level in the span tree) */
+ if(coords[0] >= tail_span->low && coords[0] <= tail_span->high) {
+ H5S_hyper_span_t *prev_down_tail_span; /* Pointer to previous down spans' tail pointer */
+ hsize_t prev_down_tail_span_high; /* Value of previous down spans' tail's high value */
+
+ /* Retain into about down spans' tail */
+ prev_down_tail_span = tail_span->down->tail;
+ prev_down_tail_span_high = tail_span->down->tail->high;
+
+ /* Drop down a dimension */
+ HDassert(rank > 1);
+ if(H5S__hyper_add_span_element_helper(tail_span->down, rank - 1, &coords[1], first_dim_modified) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "can't insert coordinate into span tree")
+
+ /* Check & update high bounds for lower dimensions */
+ if(*first_dim_modified >= 0) {
+ unsigned first_dim; /* First dimension modified, relative to this span tree */
+ hbool_t first_dim_set = FALSE; /* Whether first dimension modified is set */
+ unsigned u; /* Local index variable */
- /* Remember the span tree we are descending into */
- prev_span_info=tspan_info;
- tspan_info=tmp_span->down;
+ /* Adjust first dimension modified to be relative to this span tree */
+ first_dim = (unsigned)(*first_dim_modified + 1);
- /* Get the last span in this span's 'down' tree */
- if(tspan_info->scratch)
- tmp_span=(H5S_hyper_span_t *)tspan_info->scratch;
- else {
- tmp_span=tspan_info->head;
- HDassert(tmp_span);
- tspan_info->scratch=(H5S_hyper_span_info_t *)tmp_span;
- } /* end else */
- } /* end while */
-
- /* Check if we made it all the way to the bottom span in the tree */
- if(rank>1) {
- /* Before we create another span at this level in the tree, check if
- * the last span's "down tree" was equal to any other spans in this
- * list of spans in the span tree.
- *
- * If so, release last span information and make last span merge into
- * previous span (if possible), or at least share their "down tree"
- * information.
- */
- tmp2_span=tspan_info->head;
- while(tmp2_span!=tmp_span) {
- if(H5S__hyper_cmp_spans(tmp2_span->down,tmp_span->down)==TRUE) {
- /* Check for merging into previous span */
- if(tmp2_span->high+1==tmp_span->low) {
- /* Release last span created */
- H5S__hyper_free_span(tmp_span);
+ /* Reset modified dimension, in case no bounds in this span tree change */
+ *first_dim_modified = -1;
- /* Increase size of previous span */
- tmp2_span->high++;
- tmp2_span->nelem++;
+ /* Iterate through coordinates */
+ for(u = first_dim; u < rank; u++) {
+ /* Check if coordinate is outside the bounds for this span tree */
+ if(coords[u] > span_tree->high_bounds[u]) {
+ /* Update high bounds for this tree */
+ span_tree->high_bounds[u] = coords[u];
- /* Reset the 'tmp_span' for the rest of this block's algorithm */
- tmp_span=tmp2_span;
+ /* Need to signal to higher dimensions if high bounds changed */
+ if(!first_dim_set) {
+ *first_dim_modified = (int)u;
+ first_dim_set = TRUE;
+ } /* end if */
} /* end if */
- /* Span is disjoint, but has the same "down tree" selection */
- else {
- /* Release "down tree" information */
- H5S__hyper_free_span_info(tmp_span->down);
+ } /* end for */
+ } /* end if */
- /* Point at earlier span's "down tree" */
- tmp_span->down=tmp2_span->down;
+ /* Check if previous tail span in down spans is different than current
+ * tail span, or if its high value changed, in which case we should
+ * check if the updated node can share down spans with other nodes.
+ */
+ if(tail_span->down->tail != prev_down_tail_span ||
+ prev_down_tail_span_high != tail_span->down->tail->high) {
+ H5S_hyper_span_t *stop_span; /* Pointer to span to stop at */
+ H5S_hyper_span_t *tmp_span; /* Temporary pointer to a span */
+ uint64_t op_gen; /* Operation generation value */
+
+ /* Determine which span to stop at */
+ if(tail_span->down->tail != prev_down_tail_span) {
+ /* Sanity check */
+ HDassert(prev_down_tail_span->next == tail_span->down->tail);
+
+ /* Set the span to stop at */
+ stop_span = prev_down_tail_span;
+ } /* end if */
+ else {
+ /* Sanity check */
+ HDassert(prev_down_tail_span_high != tail_span->down->tail->high);
- /* Increment reference count on shared "down tree" */
- tmp_span->down->count++;
- } /* end else */
+ /* Set the span to stop at */
+ stop_span = tail_span->down->tail;
+ } /* end else */
- /* Found span to merge into, break out now */
- break;
- } /* end if */
+ /* Acquire an operation generation value for this operation */
+ op_gen = H5S__hyper_get_op_gen();
- /* Advance to next span to check */
- tmp2_span=tmp2_span->next;
- } /* end while */
+ /* Check if the 'stop' span in the "down tree" is equal to any other
+ * spans in the list of spans in the span tree.
+ *
+ * If so, release last span information and make last span merge into
+ * previous span (if possible), or at least share their "down tree"
+ * information.
+ */
+ tmp_span = tail_span->down->head;
+ while(tmp_span != stop_span) {
+ hbool_t attempt_merge_spans = FALSE; /* Whether to merge spans */
- /* Make span tree for current coordinates */
- if(NULL == (new_span = H5S__hyper_coord_to_span(rank, coords)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span")
+ /* Different tests for when to run the 'merge' algorithm,
+ * depending whether there's "down trees" or not.
+ */
+ if(NULL == tmp_span->down) {
+ /* Spin through spans until we find the one before the 'stop' span */
+ if(tmp_span->next == stop_span)
+ attempt_merge_spans = TRUE;
+ } /* end if */
+ else {
+ /* Check if we've compared the 'stop' span's "down tree" to
+ * this span's "down tree" already.
+ */
+ if(tmp_span->down->op_gen != op_gen) {
+ if(H5S__hyper_cmp_spans(tmp_span->down, stop_span->down))
+ attempt_merge_spans = TRUE;
+
+ /* Remember that we visited this span's "down tree" already */
+ /* (Because it wasn't the same as the 'stop' span's down tree
+ * and we don't need to compare it again)
+ */
+ tmp_span->down->op_gen = op_gen;
+ } /* end if */
+ } /* end else */
- /* Add new span tree as span */
- HDassert(tmp_span);
- tmp_span->next=new_span;
+ /* Check for merging into previous span */
+ if(attempt_merge_spans) {
+ if(tmp_span->high + 1 == stop_span->low) {
+ /* Increase size of previous span */
+ tmp_span->high++;
- /* Make scratch pointer point to last span in list */
- HDassert(tspan_info);
- tspan_info->scratch=(H5S_hyper_span_info_t *)new_span;
+ /* Update pointers appropriately */
+ if(stop_span == prev_down_tail_span) {
+ /* Sanity check */
+ HDassert(stop_span->next == tail_span->down->tail);
- /* Set the proper 'pstride' for new span */
- new_span->pstride=new_span->low-tmp_span->low;
- } /* end if */
- else {
- /* Does new node adjoin existing node? */
- if(tmp_span->high+1==coords[0]) {
- tmp_span->high++;
- tmp_span->nelem++;
-
- /* Check if this span tree should now be merged with a level higher in the tree */
- if(prev_span_info!=NULL) {
- /* Before we create another span at this level in the tree, check if
- * the last span's "down tree" was equal to any other spans in this
- * list of spans in the span tree.
- *
- * If so, release last span information and make last span merge into
- * previous span (if possible), or at least share their "down tree"
- * information.
- */
- tmp2_span=prev_span_info->head;
- tmp_span=(H5S_hyper_span_t *)prev_span_info->scratch;
- while(tmp2_span!=tmp_span) {
- if(H5S__hyper_cmp_spans(tmp2_span->down,tmp_span->down)==TRUE) {
- /* Check for merging into previous span */
- if(tmp2_span->high+1==tmp_span->low) {
- /* Release last span created */
- H5S__hyper_free_span(tmp_span);
-
- /* Increase size of previous span */
- tmp2_span->high++;
- tmp2_span->nelem++;
-
- /* Update pointers */
- tmp2_span->next=NULL;
- prev_span_info->scratch=(H5S_hyper_span_info_t *)tmp2_span;
+ tmp_span->next = stop_span->next;
} /* end if */
- /* Span is disjoint, but has the same "down tree" selection */
else {
- /* Release "down tree" information */
- H5S__hyper_free_span_info(tmp_span->down);
-
- /* Point at earlier span's "down tree" */
- tmp_span->down=tmp2_span->down;
+ /* Sanity check */
+ HDassert(tmp_span->next == tail_span->down->tail);
- /* Increment reference count on shared "down tree" */
- tmp_span->down->count++;
+ tmp_span->next = NULL;
+ tail_span->down->tail = tmp_span;
} /* end else */
- /* Found span to merge into, break out now */
- break;
+ /* Release last span created */
+ H5S__hyper_free_span(stop_span);
} /* end if */
+ /* Span is disjoint, but has the same "down tree" selection */
+ /* (If it has a "down tree") */
+ else if(stop_span->down) {
+ /* Release "down tree" information */
+ H5S__hyper_free_span_info(stop_span->down);
- /* Advance to next span to check */
- tmp2_span=tmp2_span->next;
- } /* end while */
- } /* end if */
+ /* Point at earlier span's "down tree" */
+ stop_span->down = tmp_span->down;
+
+ /* Increment reference count on shared "down tree" */
+ stop_span->down->count++;
+ } /* end else */
+
+ /* Found span to merge into, break out now */
+ break;
+ } /* end if */
+
+ /* Advance to next span to check */
+ tmp_span = tmp_span->next;
+ } /* end while */
} /* end if */
- else {
- if(NULL == (new_span = H5S__hyper_new_span(coords[0], coords[0], NULL, NULL)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span")
+ } /* end if */
+ else {
+ unsigned u; /* Local index variable */
- /* Add new span tree as span */
- HDassert(tmp_span);
- tmp_span->next=new_span;
+ /* Check if we made it all the way to the bottom span list in the tree
+ * and the new coordinate adjoins the current tail span.
+ */
+ if(rank == 1 && (tail_span->high + 1) == coords[0])
+ /* Append element to current tail span */
+ tail_span->high++;
+ else {
+ H5S_hyper_span_t *new_span; /* New span created for element */
- /* Make scratch pointer point to last span in list */
- tspan_info->scratch=(H5S_hyper_span_info_t *)new_span;
+ /* Make span tree for current coordinate(s) */
+ if(NULL == (new_span = H5S__hyper_coord_to_span(rank, coords)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate hyperslab spans for coordinate")
- /* Set the proper 'pstride' for new span */
- new_span->pstride = new_span->low - tmp_span->low;
+ /* Add new span to span tree list */
+ tail_span->next = new_span;
+ span_tree->tail = new_span;
} /* end else */
+
+ /* Update high bound for current span tree */
+ HDassert(coords[0] > span_tree->high_bounds[0]);
+ span_tree->high_bounds[0] = coords[0];
+
+ /* Update high bounds for dimensions below this one */
+ for(u = 1; u < rank; u++)
+ if(coords[u] > span_tree->high_bounds[u])
+ span_tree->high_bounds[u] = coords[u];
+
+ /* Need to signal to higher dimensions that high bounds changed */
+ *first_dim_modified = 0;
} /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S__hyper_add_span_element_helper() */
-
+
/*--------------------------------------------------------------------------
NAME
H5S_hyper_add_span_element
@@ -3726,6 +6060,24 @@ done:
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
Assumes that the element is not already in the dataspace's selection
+
+ NOTE: There's also an assumption about the context of this function call -
+ This function is only called is only being called from H5D_chunk_mem_cb
+ in src/H5Dchunk.c, when the library is iterating over a memory
+ selection, so the coordinates passed to H5S_hyper_add_span_element will
+ always be in increasing order (according to a row-major (i.e. C, not
+ FORTRAN) scan) over the dataset. Therefore, for every input of
+ coordinates, only the last span element (i.e., the tail pointer) in
+ one dimension is checked against the input.
+
+ NOTE: This algorithm is definitely "correct" and tries to conserve memory
+ as much as possible, but it's doing a _lot_ of work that might be
+ better spent running a similar algorithm to "condense" the span tree
+ (possibly even back into a regular selection) just before the selection
+ is used for I/O on the chunk. I'm not going to spend the time on this
+ currently, but it does sound like a good direction to explore.
+ QAK, 2019/01/24
+
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
@@ -3745,9 +6097,13 @@ H5S_hyper_add_span_element(H5S_t *space, unsigned rank, const hsize_t *coords)
/* Check if this is the first element in the selection */
if(NULL == space->select.sel_info.hslab) {
/* Allocate a span info node */
- if(NULL == (head = H5FL_CALLOC(H5S_hyper_span_info_t)))
+ if(NULL == (head = H5S__hyper_new_span_info(rank)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate hyperslab span info")
+ /* Set the low & high bounds for this span info node */
+ H5MM_memcpy(head->low_bounds, coords, rank * sizeof(hsize_t));
+ H5MM_memcpy(head->high_bounds, coords, rank * sizeof(hsize_t));
+
/* Set the reference count */
head->count = 1;
@@ -3755,6 +6111,9 @@ H5S_hyper_add_span_element(H5S_t *space, unsigned rank, const hsize_t *coords)
if(NULL == (head->head = H5S__hyper_coord_to_span(rank, coords)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate hyperslab spans for coordinate")
+ /* Update the tail pointer of this newly created span in dimension "rank" */
+ head->tail = head->head;
+
/* Allocate selection info */
if(NULL == (space->select.sel_info.hslab = H5FL_MALLOC(H5S_hyper_sel_t)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate hyperslab selection")
@@ -3766,7 +6125,7 @@ H5S_hyper_add_span_element(H5S_t *space, unsigned rank, const hsize_t *coords)
space->select.type = H5S_sel_hyper;
/* Reset "regular" hyperslab flag */
- space->select.sel_info.hslab->diminfo_valid = FALSE;
+ space->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_NO;
/* Set unlim_dim */
space->select.sel_info.hslab->unlim_dim = -1;
@@ -3775,7 +6134,10 @@ H5S_hyper_add_span_element(H5S_t *space, unsigned rank, const hsize_t *coords)
space->select.num_elem = 1;
} /* end if */
else {
- if(H5S__hyper_add_span_element_helper(space->select.sel_info.hslab->span_lst, rank, coords) < 0)
+ int first_dim_modified = -1; /* Index of first dimension modified */
+
+ /* Add the element to the current set of spans */
+ if(H5S__hyper_add_span_element_helper(space->select.sel_info.hslab->span_lst, rank, coords, &first_dim_modified) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert coordinate into span tree")
/* Increment # of elements in selection */
@@ -3790,242 +6152,21 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_hyper_add_span_element() */
-
-/*--------------------------------------------------------------------------
- NAME
- H5S_hyper_reset_scratch
- PURPOSE
- Reset the scratch information for span tree
- USAGE
- herr_t H5S_hyper_reset_scratch(space)
- H5S_t *space; IN/OUT: Pointer to dataspace to reset scratch pointers
- RETURNS
- Non-negative on success, negative on failure
- DESCRIPTION
- Resets the "scratch" pointers used for various tasks in computing hyperslab
- spans.
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
-herr_t
-H5S_hyper_reset_scratch(H5S_t *space)
-{
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(FAIL)
-
- HDassert(space);
-
- /* Check if there are spans in the span tree */
- if(space->select.sel_info.hslab->span_lst != NULL)
- /* Reset the scratch pointers for the next routine which needs them */
- H5S__hyper_span_scratch(space->select.sel_info.hslab->span_lst);
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5S_hyper_reset_scratch() */
-
-
-/*--------------------------------------------------------------------------
- NAME
- H5S_hyper_convert
- PURPOSE
- Convert a compatible selection to span tree form
- USAGE
- herr_t H5S_hyper_convert(space)
- H5S_t *space; IN/OUT: Pointer to dataspace to convert
- RETURNS
- Non-negative on success, negative on failure
- DESCRIPTION
- Converts a compatible selection (currently only "all" selections) to the
- span-tree form of a hyperslab selection. (Point and "none" selection aren't
- currently supported and hyperslab selection always have the span-tree form
- available).
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
-herr_t
-H5S_hyper_convert(H5S_t *space)
-{
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(FAIL)
-
- HDassert(space);
-
- /* Check the type of selection */
- switch(H5S_GET_SELECT_TYPE(space)) {
- case H5S_SEL_ALL: /* All elements selected in dataspace */
- /* Convert current "all" selection to "real" hyperslab selection */
- {
- const hsize_t *tmp_start; /* Temporary start information */
- const hsize_t *tmp_stride; /* Temporary stride information */
- const hsize_t *tmp_count; /* Temporary count information */
- const hsize_t *tmp_block; /* Temporary block information */
-
- /* Set up temporary information for the dimensions */
- tmp_start = H5S_hyper_zeros_g;
- tmp_stride = tmp_count = H5S_hyper_ones_g;
- tmp_block = space->extent.size;
-
- /* Convert to hyperslab selection */
- if(H5S_select_hyperslab(space,H5S_SELECT_SET,tmp_start,tmp_stride,tmp_count,tmp_block)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't convert selection")
- } /* end case */
- break;
-
- case H5S_SEL_HYPERSLABS: /* Hyperslab selection */
- break;
-
- case H5S_SEL_NONE: /* No elements selected in dataspace */
- case H5S_SEL_POINTS: /* Point selection */
- case H5S_SEL_ERROR: /* Selection error */
- case H5S_SEL_N: /* Selection count */
- default:
- HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "can't convert to span tree selection")
- } /* end switch */
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5S_hyper_convert() */
-
-#ifdef LATER
-
-/*--------------------------------------------------------------------------
- NAME
- H5S_hyper_intersect_helper
- PURPOSE
- Helper routine to detect intersections in span trees
- USAGE
- htri_t H5S_hyper_intersect_helper(spans1, spans2)
- H5S_hyper_span_info_t *spans1; IN: First span tree to operate with
- H5S_hyper_span_info_t *spans2; IN: Second span tree to operate with
- RETURNS
- Non-negative on success, negative on failure
- DESCRIPTION
- Quickly detect intersections between two span trees
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
-static htri_t
-H5S_hyper_intersect_helper (H5S_hyper_span_info_t *spans1, H5S_hyper_span_info_t *spans2)
-{
- H5S_hyper_span_t *curr1; /* Pointer to current span in 1st span tree */
- H5S_hyper_span_t *curr2; /* Pointer to current span in 2nd span tree */
- htri_t status; /* Status from recursive call */
- htri_t ret_value=FALSE; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT
-
- /* Sanity check */
- HDassert((spans1 && spans2) || (spans1 == NULL && spans2 == NULL));
-
- /* "NULL" span trees compare as overlapping */
- if(spans1==NULL && spans2==NULL)
- HGOTO_DONE(TRUE);
-
- /* Get the span lists for each span in this tree */
- curr1=spans1->head;
- curr2=spans2->head;
-
- /* Iterate over the spans in each tree */
- while(curr1!=NULL && curr2!=NULL) {
- /* Check for 1st span entirely before 2nd span */
- if(curr1->high<curr2->low)
- curr1=curr1->next;
- /* Check for 2nd span entirely before 1st span */
- else if(curr2->high<curr1->low)
- curr2=curr2->next;
- /* Spans must overlap */
- else {
- /* Recursively check spans in next dimension down */
- if((status=H5S_hyper_intersect_helper(curr1->down,curr2->down))<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADSELECT, FAIL, "can't perform hyperslab intersection check")
-
- /* If there is a span intersection in the down dimensions, the span trees overlap */
- if(status==TRUE)
- HGOTO_DONE(TRUE);
-
- /* No intersection in down dimensions, advance to next span */
- if(curr1->high<curr2->high)
- curr1=curr1->next;
- else
- curr2=curr2->next;
- } /* end else */
- } /* end while */
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_hyper_intersect_helper() */
-
-
-/*--------------------------------------------------------------------------
- NAME
- H5S_hyper_intersect
- PURPOSE
- Detect intersections in span trees
- USAGE
- htri_t H5S_hyper_intersect(space1, space2)
- H5S_t *space1; IN: First dataspace to operate on span tree
- H5S_t *space2; IN: Second dataspace to operate on span tree
- RETURNS
- Non-negative on success, negative on failure
- DESCRIPTION
- Quickly detect intersections between two span trees
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
-htri_t
-H5S_hyper_intersect (H5S_t *space1, H5S_t *space2)
-{
- htri_t ret_value=FAIL; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT
-
- /* Sanity check */
- HDassert(space1);
- HDassert(space2);
-
- /* Check that the space selections both have span trees */
- if(space1->select.sel_info.hslab->span_lst==NULL ||
- space2->select.sel_info.hslab->span_lst==NULL)
- HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "dataspace does not have span tree")
-
- /* Check that the dataspaces are both the same rank */
- if(space1->extent.rank!=space2->extent.rank)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "dataspace ranks don't match")
-
- /* Perform the span-by-span intersection check */
- if((ret_value=H5S_hyper_intersect_helper(space1->select.sel_info.hslab->span_lst,space2->select.sel_info.hslab->span_lst))<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADSELECT, FAIL, "can't perform hyperslab intersection check")
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_hyper_intersect() */
-#endif /* LATER */
-
-
/*--------------------------------------------------------------------------
NAME
H5S__hyper_intersect_block_helper
PURPOSE
Helper routine to detect intersections in span trees
USAGE
- htri_t H5S_hyper_intersect_block_helper(spans, start, end)
+ hbool_t H5S__hyper_intersect_block_helper(spans, start, end)
H5S_hyper_span_info_t *spans; IN: First span tree to operate with
- hssize_t *offset; IN: Selection offset coordinate
+ unsigned rank; IN: Number of dimensions for span tree
hsize_t *start; IN: Starting coordinate for block
hsize_t *end; IN: Ending coordinate for block
+ uint64_t op_gen; IN: Operation generation
RETURN
- Non-negative on success, negative on failure
+ Non-negative (TRUE/FALSE) on success, can't fail
DESCRIPTION
Quickly detect intersections between span tree and block
GLOBAL VARIABLES
@@ -4034,10 +6175,9 @@ done:
REVISION LOG
--------------------------------------------------------------------------*/
static hbool_t
-H5S__hyper_intersect_block_helper(const H5S_hyper_span_info_t *spans,
- const hsize_t *start, const hsize_t *end)
+H5S__hyper_intersect_block_helper(H5S_hyper_span_info_t *spans,
+ unsigned rank, const hsize_t *start, const hsize_t *end, uint64_t op_gen)
{
- H5S_hyper_span_t *curr; /* Pointer to current span in 1st span tree */
hbool_t ret_value = FALSE; /* Return value */
FUNC_ENTER_STATIC_NOERR
@@ -4047,37 +6187,52 @@ H5S__hyper_intersect_block_helper(const H5S_hyper_span_info_t *spans,
HDassert(start);
HDassert(end);
- /* Get the span list for spans in this tree */
- curr = spans->head;
+ /* Check if we've already visited this span tree */
+ if(spans->op_gen != op_gen) {
+ H5S_hyper_span_t *curr; /* Pointer to current span in 1st span tree */
+ unsigned u; /* Local index variable */
- /* Iterate over the spans in the tree */
- while(curr != NULL) {
- /* Check for span entirely before block */
- if(curr->high < *start)
- /* Advance to next span in this dimension */
- curr = curr->next;
- /* If this span is past the end of the block, then we're done in this dimension */
- else if(curr->low > *end)
- HGOTO_DONE(FALSE)
- /* block & span overlap */
- else {
- if(curr->down == NULL)
- HGOTO_DONE(TRUE)
- else {
- hbool_t status; /* Status from recursive call */
-
- /* Recursively check spans in next dimension down */
- status = H5S__hyper_intersect_block_helper(curr->down, start + 1, end + 1);
+ /* Verify that there is a possibility of an overlap by checking the block
+ * against the low & high bounds for the span tree.
+ */
+ for(u = 0; u < rank; u++)
+ if(start[u] > spans->high_bounds[u] || end[u] < spans->low_bounds[u])
+ HGOTO_DONE(FALSE)
- /* If there is a span intersection in the down dimensions, the span trees overlap */
- if(status == TRUE)
- HGOTO_DONE(TRUE);
+ /* Get the span list for spans in this tree */
+ curr = spans->head;
- /* No intersection in down dimensions, advance to next span */
+ /* Iterate over the spans in the tree */
+ while(curr != NULL) {
+ /* Check for span entirely before block */
+ if(curr->high < *start)
+ /* Advance to next span in this dimension */
curr = curr->next;
+ /* If this span is past the end of the block, then we're done in this dimension */
+ else if(curr->low > *end)
+ HGOTO_DONE(FALSE)
+ /* block & span overlap */
+ else {
+ /* If this is the bottom dimension, then the span tree overlaps the block */
+ if(curr->down == NULL)
+ HGOTO_DONE(TRUE)
+ /* Recursively check spans in next dimension down */
+ else {
+ /* If there is an intersection in the "down" dimensions,
+ * the span trees overlap.
+ */
+ if(H5S__hyper_intersect_block_helper(curr->down, rank - 1, start + 1, end + 1, op_gen))
+ HGOTO_DONE(TRUE)
+
+ /* No intersection in down dimensions, advance to next span */
+ curr = curr->next;
+ } /* end else */
} /* end else */
- } /* end else */
- } /* end while */
+ } /* end while */
+
+ /* Set the tree's operation generation */
+ spans->op_gen = op_gen;
+ } /* end if */
/* Fall through with 'FALSE' return value */
@@ -4085,56 +6240,137 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S__hyper_intersect_block_helper() */
-
+
/*--------------------------------------------------------------------------
NAME
- H5S_hyper_intersect_block
+ H5S__hyper_intersect_block
PURPOSE
- Detect intersections in span trees
+ Detect intersections of selection with block
USAGE
- htri_t H5S_hyper_intersect_block(space, start, end)
- H5S_t *space; IN: First dataspace to operate on span tree
- hssize_t *start; IN: Starting coordinate for block
- hssize_t *end; IN: Ending coordinate for block
+ htri_t H5S__hyper_intersect_block(space, start, end)
+ const H5S_t *space; IN: Dataspace with selection to use
+ const hsize_t *start; IN: Starting coordinate for block
+ const hsize_t *end; IN: Ending coordinate for block
RETURNS
- Non-negative on success, negative on failure
+ Non-negative TRUE / FALSE on success, negative on failure
DESCRIPTION
- Quickly detect intersections between span tree and block
+ Quickly detect intersections between both regular hyperslabs and span trees
+ with a block
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
+ Does not use selection offset.
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-htri_t
-H5S_hyper_intersect_block(H5S_t *space, const hsize_t *start, const hsize_t *end)
+static htri_t
+H5S__hyper_intersect_block(const H5S_t *space, const hsize_t *start, const hsize_t *end)
{
htri_t ret_value = FAIL; /* Return value */
- FUNC_ENTER_NOAPI(FAIL)
+ FUNC_ENTER_STATIC
/* Sanity check */
HDassert(space);
+ HDassert(H5S_SEL_HYPERSLABS == H5S_GET_SELECT_TYPE(space));
HDassert(start);
HDassert(end);
- /* Check for 'all' selection, instead of a hyperslab selection */
- /* (Technically, this shouldn't be in the "hyperslab" routines...) */
- if(H5S_GET_SELECT_TYPE(space) == H5S_SEL_ALL)
- HGOTO_DONE(TRUE);
+ /* Attempt to rebuild diminfo if it is invalid and has not been confirmed
+ * to be impossible.
+ */
+ if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_NO)
+ H5S__hyper_rebuild((H5S_t *)space); /* Casting away const OK -QAK */
- /* Check that the space selection has a span tree */
- if(NULL == space->select.sel_info.hslab->span_lst)
- if(H5S__hyper_generate_spans(space) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "dataspace does not have span tree")
+ /* Check for regular hyperslab intersection */
+ if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) {
+ hbool_t single_block; /* Whether the regular selection is a single block */
+ unsigned u; /* Local index variable */
+
+ /* Check for a single block */
+ /* For a regular hyperslab to be single, it must have only one block
+ * (i.e. count == 1 in all dimensions).
+ */
+ single_block = TRUE;
+ for(u = 0; u < space->extent.rank; u++)
+ if(space->select.sel_info.hslab->diminfo.opt[u].count > 1)
+ single_block = FALSE;
+
+ /* Single blocks have already been "compared" above, in the low / high
+ * bound checking, so just return TRUE if we've reached here - they
+ * would have been rejected earlier, if they didn't intersect.
+ */
+ if(single_block)
+ HGOTO_DONE(TRUE)
+ else {
+ /* Loop over the dimensions, checking for an intersection */
+ for(u = 0; u < space->extent.rank; u++) {
+ /* If the block's start is <= the hyperslab start, they intersect */
+ /* (So, if the start is > the hyperslab start, check more conditions) */
+ if(start[u] > space->select.sel_info.hslab->diminfo.opt[u].start) {
+ hsize_t adj_start; /* Start coord, adjusted for hyperslab selection parameters */
+ hsize_t nstride; /* Number of strides into the selection */
+
+ /* Adjust start coord for selection's 'start' offset */
+ adj_start = start[u] - space->select.sel_info.hslab->diminfo.opt[u].start;
+
+ /* Compute # of strides into the selection */
+ if(space->select.sel_info.hslab->diminfo.opt[u].count > 1)
+ nstride = adj_start / space->select.sel_info.hslab->diminfo.opt[u].stride;
+ else
+ nstride = 0;
+
+ /* Sanity check */
+ HDassert(nstride <= space->select.sel_info.hslab->diminfo.opt[u].count);
+
+ /* "Rebase" the adjusted start coord into the same range
+ * range of values as the selections's first block.
+ */
+ adj_start -= nstride * space->select.sel_info.hslab->diminfo.opt[u].stride;
+
+ /* If the adjusted start doesn't fall within the first hyperslab
+ * span, check for the block overlapping with the next one.
+ */
+ if(adj_start >= space->select.sel_info.hslab->diminfo.opt[u].block) {
+ hsize_t adj_end; /* End coord, adjusted for hyperslab selection parameters */
- /* Perform the span-by-span intersection check */
- ret_value = H5S__hyper_intersect_block_helper(space->select.sel_info.hslab->span_lst, start, end);
+ /* Adjust end coord for selection's 'start' offset */
+ adj_end = end[u] - space->select.sel_info.hslab->diminfo.opt[u].start;
+
+ /* "Rebase" the adjusted end coord into the same range
+ * range of values as the selections's first block.
+ */
+ adj_end -= nstride * space->select.sel_info.hslab->diminfo.opt[u].stride;
+
+ /* If block doesn't extend over beginning of next span,
+ * it doesn't intersect.
+ */
+ if(adj_end < space->select.sel_info.hslab->diminfo.opt[u].stride)
+ HGOTO_DONE(FALSE)
+ } /* end if */
+ } /* end if */
+ } /* end for */
+
+ /* If we've looped through all dimensions and none of them didn't
+ * overlap, then all of them do, so we report TRUE.
+ */
+ HGOTO_DONE(TRUE)
+ } /* end else */
+ } /* end if */
+ else {
+ uint64_t op_gen; /* Operation generation value */
+
+ /* Acquire an operation generation value for this operation */
+ op_gen = H5S__hyper_get_op_gen();
+
+ /* Perform the span-by-span intersection check */
+ ret_value = H5S__hyper_intersect_block_helper(space->select.sel_info.hslab->span_lst, space->extent.rank, start, end, op_gen);
+ } /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5S_hyper_intersect_block() */
+} /* end H5S__hyper_intersect_block() */
+
-
/*--------------------------------------------------------------------------
NAME
H5S__hyper_adjust_u_helper
@@ -4143,7 +6379,9 @@ done:
USAGE
void H5S__hyper_adjust_u_helper(spans, offset)
H5S_hyper_span_info_t *spans; IN: Span tree to operate with
+ unsigned rank; IN: Number of dimensions for span tree
const hsize_t *offset; IN: Offset to subtract
+ uint64_t op_gen; IN: Operation generation
RETURNS
None
DESCRIPTION
@@ -4154,23 +6392,26 @@ done:
REVISION LOG
--------------------------------------------------------------------------*/
static void
-H5S__hyper_adjust_u_helper(H5S_hyper_span_info_t *spans,
- const hsize_t *offset)
+H5S__hyper_adjust_u_helper(H5S_hyper_span_info_t *spans, unsigned rank,
+ const hsize_t *offset, uint64_t op_gen)
{
FUNC_ENTER_STATIC_NOERR
/* Sanity checks */
HDassert(spans);
- HDassert(spans->scratch == (H5S_hyper_span_info_t *)~((size_t)NULL) ||
- spans->scratch == NULL);
HDassert(offset);
- /* Check if we've already set this down span tree */
- if(spans->scratch != (H5S_hyper_span_info_t *)~((size_t)NULL)) {
+ /* Check if we've already set this span tree */
+ if(spans->op_gen != op_gen) {
H5S_hyper_span_t *span; /* Pointer to current span in span tree */
+ unsigned u; /* Local index variable */
- /* Set the tree's scratch pointer */
- spans->scratch = (H5S_hyper_span_info_t *)~((size_t)NULL);
+ /* Adjust the span tree's low & high bounds */
+ for(u = 0; u < rank; u++) {
+ HDassert(spans->low_bounds[u] >= offset[u]);
+ spans->low_bounds[u] -= offset[u];
+ spans->high_bounds[u] -= offset[u];
+ } /* end for */
/* Iterate over the spans in tree */
span = spans->head;
@@ -4182,17 +6423,20 @@ H5S__hyper_adjust_u_helper(H5S_hyper_span_info_t *spans,
/* Recursively adjust spans in next dimension down */
if(span->down != NULL)
- H5S__hyper_adjust_u_helper(span->down, offset + 1);
+ H5S__hyper_adjust_u_helper(span->down, rank - 1, offset + 1, op_gen);
/* Advance to next span in this dimension */
span = span->next;
} /* end while */
+
+ /* Set the tree's operation generation */
+ spans->op_gen = op_gen;
} /* end if */
FUNC_LEAVE_NOAPI_VOID
} /* end H5S__hyper_adjust_u_helper() */
-
+
/*--------------------------------------------------------------------------
NAME
H5S__hyper_adjust_u
@@ -4221,36 +6465,44 @@ H5S__hyper_adjust_u(H5S_t *space, const hsize_t *offset)
HDassert(offset);
/* Subtract the offset from the "regular" coordinates, if they exist */
- if(space->select.sel_info.hslab->diminfo_valid) {
+ /* (No need to rebuild the dimension info yet -QAK) */
+ if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) {
unsigned u; /* Local index variable */
for(u = 0; u < space->extent.rank; u++) {
- HDassert(space->select.sel_info.hslab->opt_diminfo[u].start >= offset[u]);
- space->select.sel_info.hslab->opt_diminfo[u].start -= offset[u];
+ HDassert(space->select.sel_info.hslab->diminfo.opt[u].start >= offset[u]);
+ space->select.sel_info.hslab->diminfo.opt[u].start -= offset[u];
+
+ /* Adjust the low & high bounds */
+ HDassert(space->select.sel_info.hslab->diminfo.low_bounds[u] >= offset[u]);
+ space->select.sel_info.hslab->diminfo.low_bounds[u] -= offset[u];
+ space->select.sel_info.hslab->diminfo.high_bounds[u] -= offset[u];
} /* end for */
} /* end if */
/* Subtract the offset from the span tree coordinates, if they exist */
if(space->select.sel_info.hslab->span_lst) {
- H5S__hyper_adjust_u_helper(space->select.sel_info.hslab->span_lst, offset);
+ uint64_t op_gen; /* Operation generation value */
- /* Reset the scratch pointers for the next routine which needs them */
- H5S__hyper_span_scratch(space->select.sel_info.hslab->span_lst);
+ /* Acquire an operation generation value for this operation */
+ op_gen = H5S__hyper_get_op_gen();
+
+ H5S__hyper_adjust_u_helper(space->select.sel_info.hslab->span_lst, space->extent.rank, offset, op_gen);
} /* end if */
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5S__hyper_adjust_u() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5S__hyper_project_scalar
+ * Function: H5S__hyper_project_scalar
*
- * Purpose: Projects a single element hyperslab selection into a scalar
+ * Purpose: Projects a single element hyperslab selection into a scalar
* dataspace
*
- * Return: non-negative on success, negative on failure.
+ * Return: Non-negative on success, negative on failure.
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* Sunday, July 18, 2010
*
*-------------------------------------------------------------------------
@@ -4267,12 +6519,20 @@ H5S__hyper_project_scalar(const H5S_t *space, hsize_t *offset)
HDassert(offset);
/* Check for a "regular" hyperslab selection */
- if(space->select.sel_info.hslab->diminfo_valid) {
- const H5S_hyper_dim_t *diminfo = space->select.sel_info.hslab->opt_diminfo; /* Alias for dataspace's diminfo information */
+ /* (No need to rebuild the dimension info yet -QAK) */
+ if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) {
+ const H5S_hyper_dim_t *diminfo = space->select.sel_info.hslab->diminfo.opt; /* Alias for dataspace's diminfo information */
unsigned u; /* Counter */
/* Build the table of the initial offset */
for(u = 0; u < space->extent.rank; u++) {
+ /* Sanity check diminfo */
+ HDassert(1 == diminfo[u].count);
+ HDassert(1 == diminfo[u].block);
+
+ /* Sanity check bounds, while we're here */
+ HDassert(diminfo[u].start == space->select.sel_info.hslab->diminfo.low_bounds[u]);
+
/* Keep the offset for later */
block[u] = diminfo[u].start;
} /* end for */
@@ -4284,17 +6544,22 @@ H5S__hyper_project_scalar(const H5S_t *space, hsize_t *offset)
/* Advance down selected spans */
curr = space->select.sel_info.hslab->span_lst->head;
curr_dim = 0;
- while(curr) {
- /* Sanity check for more than one span */
+ while(1) {
+ /* Sanity checks */
HDassert(NULL == curr->next);
HDassert(curr->low == curr->high);
+ HDassert(curr_dim < space->extent.rank);
/* Save the location of the selection in current dimension */
block[curr_dim] = curr->low;
/* Advance down to next dimension */
- curr = curr->down->head;
- curr_dim++;
+ if(curr->down) {
+ curr = curr->down->head;
+ curr_dim++;
+ } /* end if */
+ else
+ break;
} /* end while */
} /* end else */
@@ -4304,16 +6569,16 @@ H5S__hyper_project_scalar(const H5S_t *space, hsize_t *offset)
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5S__hyper_project_scalar() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5S__hyper_project_simple_lower
+ * Function: H5S__hyper_project_simple_lower
*
- * Purpose: Projects a hyperslab selection onto/into a simple dataspace
+ * Purpose: Projects a hyperslab selection onto/into a simple dataspace
* of a lower rank
*
- * Return: non-negative on success, negative on failure.
+ * Return: Non-negative on success, negative on failure.
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* Sunday, July 18, 2010
*
*-------------------------------------------------------------------------
@@ -4351,16 +6616,16 @@ H5S__hyper_project_simple_lower(const H5S_t *base_space, H5S_t *new_space)
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5S__hyper_project_simple_lower() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5S__hyper_project_simple_higher
+ * Function: H5S__hyper_project_simple_higher
*
- * Purpose: Projects a hyperslab selection onto/into a simple dataspace
+ * Purpose: Projects a hyperslab selection onto/into a simple dataspace
* of a higher rank
*
- * Return: non-negative on success, negative on failure.
+ * Return: Non-negative on success, negative on failure.
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* Sunday, July 18, 2010
*
*-------------------------------------------------------------------------
@@ -4369,7 +6634,9 @@ static herr_t
H5S__hyper_project_simple_higher(const H5S_t *base_space, H5S_t *new_space)
{
H5S_hyper_span_t *prev_span = NULL; /* Pointer to previous list of spans */
+ unsigned delta_rank; /* Difference in dataspace ranks */
unsigned curr_dim; /* Current dimension being operated on */
+ unsigned u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC
@@ -4382,15 +6649,15 @@ H5S__hyper_project_simple_higher(const H5S_t *base_space, H5S_t *new_space)
/* Create nodes until reaching the correct # of dimensions */
new_space->select.sel_info.hslab->span_lst = NULL;
curr_dim = 0;
- while(curr_dim < (new_space->extent.rank - base_space->extent.rank)) {
+ delta_rank = (new_space->extent.rank - base_space->extent.rank);
+ while(curr_dim < delta_rank) {
H5S_hyper_span_info_t *new_span_info; /* Pointer to list of spans */
H5S_hyper_span_t *new_span; /* Temporary hyperslab span */
/* Allocate a new span_info node */
- if(NULL == (new_span_info = H5FL_CALLOC(H5S_hyper_span_info_t))) {
+ if(NULL == (new_span_info = H5S__hyper_new_span_info(new_space->extent.rank))) {
if(prev_span)
- if(H5S__hyper_free_span(prev_span) < 0)
- HERROR(H5E_DATASPACE, H5E_CANTFREE, "can't free hyperslab span");
+ H5S__hyper_free_span(prev_span);
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate hyperslab span info")
} /* end if */
@@ -4402,13 +6669,24 @@ H5S__hyper_project_simple_higher(const H5S_t *base_space, H5S_t *new_space)
if(NULL == (new_span = H5S__hyper_new_span((hsize_t)0, (hsize_t)0, NULL, NULL))) {
HDassert(new_span_info);
if(!prev_span)
- (void)H5FL_FREE(H5S_hyper_span_info_t, new_span_info);
+ (void)H5FL_ARR_FREE(hbounds_t, new_span_info);
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate hyperslab span")
} /* end if */
/* Set the span_info information */
new_span_info->count = 1;
new_span_info->head = new_span;
+ new_span_info->tail = new_span;
+
+ /* Set the bounding box */
+ for(u = 0; u < delta_rank; u++) {
+ new_span_info->low_bounds[u] = 0;
+ new_span_info->high_bounds[u] = 0;
+ } /* end for */
+ for(; u < new_space->extent.rank; u++) {
+ new_span_info->low_bounds[u] = base_space->select.sel_info.hslab->span_lst->low_bounds[u - delta_rank];
+ new_span_info->high_bounds[u] = base_space->select.sel_info.hslab->span_lst->high_bounds[u - delta_rank];
+ } /* end for */
/* Attach to new space, if top span info */
if(NULL == new_space->select.sel_info.hslab->span_lst)
@@ -4430,31 +6708,31 @@ H5S__hyper_project_simple_higher(const H5S_t *base_space, H5S_t *new_space)
done:
if(ret_value < 0 && new_space->select.sel_info.hslab->span_lst) {
if(new_space->select.sel_info.hslab->span_lst->head)
- if(H5S__hyper_free_span(new_space->select.sel_info.hslab->span_lst->head) < 0)
- HDONE_ERROR(H5E_DATASPACE, H5E_CANTFREE, FAIL, "can't free hyperslab span")
+ H5S__hyper_free_span(new_space->select.sel_info.hslab->span_lst->head);
- new_space->select.sel_info.hslab->span_lst = H5FL_FREE(H5S_hyper_span_info_t, new_space->select.sel_info.hslab->span_lst);
+ new_space->select.sel_info.hslab->span_lst = (H5S_hyper_span_info_t *)H5FL_ARR_FREE(hbounds_t, new_space->select.sel_info.hslab->span_lst);
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S__hyper_project_simple_higher() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5S__hyper_project_simple
+ * Function: H5S__hyper_project_simple
*
- * Purpose: Projects a hyperslab selection onto/into a simple dataspace
+ * Purpose: Projects a hyperslab selection onto/into a simple dataspace
* of a different rank
*
- * Return: non-negative on success, negative on failure.
+ * Return: Non-negative on success, negative on failure.
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* Sunday, July 18, 2010
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5S__hyper_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *offset)
+H5S__hyper_project_simple(const H5S_t *base_space, H5S_t *new_space,
+ hsize_t *offset)
{
herr_t ret_value = SUCCEED; /* Return value */
@@ -4477,15 +6755,16 @@ H5S__hyper_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *of
new_space->select.sel_info.hslab->unlim_dim = -1;
/* Check for a "regular" hyperslab selection */
- if(base_space->select.sel_info.hslab->diminfo_valid) {
+ /* (No need to rebuild the dimension info yet -QAK) */
+ if(base_space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) {
unsigned base_space_dim; /* Current dimension in the base dataspace */
unsigned new_space_dim; /* Current dimension in the new dataspace */
+ unsigned u; /* Local index variable */
/* Check if the new space's rank is < or > base space's rank */
if(new_space->extent.rank < base_space->extent.rank) {
- const H5S_hyper_dim_t *opt_diminfo = base_space->select.sel_info.hslab->opt_diminfo; /* Alias for dataspace's diminfo information */
+ const H5S_hyper_dim_t *opt_diminfo = base_space->select.sel_info.hslab->diminfo.opt; /* Alias for dataspace's diminfo information */
hsize_t block[H5S_MAX_RANK]; /* Block selected in base dataspace */
- unsigned u; /* Local index variable */
/* Compute the offset for the down-projection */
HDmemset(block, 0, sizeof(block));
@@ -4505,15 +6784,15 @@ H5S__hyper_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *of
/* Set the diminfo information for the higher dimensions */
for(new_space_dim = 0; new_space_dim < (new_space->extent.rank - base_space->extent.rank); new_space_dim++) {
- new_space->select.sel_info.hslab->app_diminfo[new_space_dim].start = 0;
- new_space->select.sel_info.hslab->app_diminfo[new_space_dim].stride = 1;
- new_space->select.sel_info.hslab->app_diminfo[new_space_dim].count = 1;
- new_space->select.sel_info.hslab->app_diminfo[new_space_dim].block = 1;
-
- new_space->select.sel_info.hslab->opt_diminfo[new_space_dim].start = 0;
- new_space->select.sel_info.hslab->opt_diminfo[new_space_dim].stride = 1;
- new_space->select.sel_info.hslab->opt_diminfo[new_space_dim].count = 1;
- new_space->select.sel_info.hslab->opt_diminfo[new_space_dim].block = 1;
+ new_space->select.sel_info.hslab->diminfo.app[new_space_dim].start = 0;
+ new_space->select.sel_info.hslab->diminfo.app[new_space_dim].stride = 1;
+ new_space->select.sel_info.hslab->diminfo.app[new_space_dim].count = 1;
+ new_space->select.sel_info.hslab->diminfo.app[new_space_dim].block = 1;
+
+ new_space->select.sel_info.hslab->diminfo.opt[new_space_dim].start = 0;
+ new_space->select.sel_info.hslab->diminfo.opt[new_space_dim].stride = 1;
+ new_space->select.sel_info.hslab->diminfo.opt[new_space_dim].count = 1;
+ new_space->select.sel_info.hslab->diminfo.opt[new_space_dim].block = 1;
} /* end for */
/* Start at beginning of base space's dimension info */
@@ -4522,31 +6801,37 @@ H5S__hyper_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *of
/* Copy the diminfo */
while(base_space_dim < base_space->extent.rank) {
- new_space->select.sel_info.hslab->app_diminfo[new_space_dim].start =
- base_space->select.sel_info.hslab->app_diminfo[base_space_dim].start;
- new_space->select.sel_info.hslab->app_diminfo[new_space_dim].stride =
- base_space->select.sel_info.hslab->app_diminfo[base_space_dim].stride;
- new_space->select.sel_info.hslab->app_diminfo[new_space_dim].count =
- base_space->select.sel_info.hslab->app_diminfo[base_space_dim].count;
- new_space->select.sel_info.hslab->app_diminfo[new_space_dim].block =
- base_space->select.sel_info.hslab->app_diminfo[base_space_dim].block;
-
- new_space->select.sel_info.hslab->opt_diminfo[new_space_dim].start =
- base_space->select.sel_info.hslab->opt_diminfo[base_space_dim].start;
- new_space->select.sel_info.hslab->opt_diminfo[new_space_dim].stride =
- base_space->select.sel_info.hslab->opt_diminfo[base_space_dim].stride;
- new_space->select.sel_info.hslab->opt_diminfo[new_space_dim].count =
- base_space->select.sel_info.hslab->opt_diminfo[base_space_dim].count;
- new_space->select.sel_info.hslab->opt_diminfo[new_space_dim].block =
- base_space->select.sel_info.hslab->opt_diminfo[base_space_dim].block;
+ new_space->select.sel_info.hslab->diminfo.app[new_space_dim].start =
+ base_space->select.sel_info.hslab->diminfo.app[base_space_dim].start;
+ new_space->select.sel_info.hslab->diminfo.app[new_space_dim].stride =
+ base_space->select.sel_info.hslab->diminfo.app[base_space_dim].stride;
+ new_space->select.sel_info.hslab->diminfo.app[new_space_dim].count =
+ base_space->select.sel_info.hslab->diminfo.app[base_space_dim].count;
+ new_space->select.sel_info.hslab->diminfo.app[new_space_dim].block =
+ base_space->select.sel_info.hslab->diminfo.app[base_space_dim].block;
+
+ new_space->select.sel_info.hslab->diminfo.opt[new_space_dim].start =
+ base_space->select.sel_info.hslab->diminfo.opt[base_space_dim].start;
+ new_space->select.sel_info.hslab->diminfo.opt[new_space_dim].stride =
+ base_space->select.sel_info.hslab->diminfo.opt[base_space_dim].stride;
+ new_space->select.sel_info.hslab->diminfo.opt[new_space_dim].count =
+ base_space->select.sel_info.hslab->diminfo.opt[base_space_dim].count;
+ new_space->select.sel_info.hslab->diminfo.opt[new_space_dim].block =
+ base_space->select.sel_info.hslab->diminfo.opt[base_space_dim].block;
/* Advance to next dimensions */
base_space_dim++;
new_space_dim++;
} /* end for */
+ /* Update the bounding box */
+ for(u = 0; u < new_space->extent.rank; u++) {
+ new_space->select.sel_info.hslab->diminfo.low_bounds[u] = new_space->select.sel_info.hslab->diminfo.opt[u].start;
+ new_space->select.sel_info.hslab->diminfo.high_bounds[u] = new_space->select.sel_info.hslab->diminfo.low_bounds[u] + new_space->select.sel_info.hslab->diminfo.opt[u].stride * (new_space->select.sel_info.hslab->diminfo.opt[u].count - 1) + (new_space->select.sel_info.hslab->diminfo.opt[u].block - 1);
+ } /* end for */
+
/* Indicate that the dimension information is valid */
- new_space->select.sel_info.hslab->diminfo_valid = TRUE;
+ new_space->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_YES;
/* Indicate that there's no slab information */
new_space->select.sel_info.hslab->span_lst = NULL;
@@ -4591,8 +6876,8 @@ H5S__hyper_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *of
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't project hyperslab selection into less dimensions")
} /* end else */
- /* Indicate that the dimension information is not valid */
- new_space->select.sel_info.hslab->diminfo_valid = FALSE;
+ /* Copy the status of the dimension information */
+ new_space->select.sel_info.hslab->diminfo_valid = base_space->select.sel_info.hslab->diminfo_valid;
} /* end else */
/* Number of elements selected will be the same */
@@ -4605,7 +6890,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S__hyper_project_simple() */
-
+
/*--------------------------------------------------------------------------
NAME
H5S__hyper_adjust_s_helper
@@ -4614,7 +6899,9 @@ done:
USAGE
void H5S__hyper_adjust_s_helper(spans, offset)
H5S_hyper_span_info_t *spans; IN: Span tree to operate with
+ unsigned rank; IN: Number of dimensions for span tree
const hssize_t *offset; IN: Offset to subtract
+ uint64_t op_gen; IN: Operation generation
RETURNS
None
DESCRIPTION
@@ -4625,23 +6912,26 @@ done:
REVISION LOG
--------------------------------------------------------------------------*/
static void
-H5S__hyper_adjust_s_helper(H5S_hyper_span_info_t *spans,
- const hssize_t *offset)
+H5S__hyper_adjust_s_helper(H5S_hyper_span_info_t *spans, unsigned rank,
+ const hssize_t *offset, uint64_t op_gen)
{
FUNC_ENTER_STATIC_NOERR
/* Sanity checks */
HDassert(spans);
- HDassert(spans->scratch == (H5S_hyper_span_info_t *)~((size_t)NULL) ||
- spans->scratch == NULL);
HDassert(offset);
- /* Check if we've already set this down span tree */
- if(spans->scratch != (H5S_hyper_span_info_t *)~((size_t)NULL)) {
+ /* Check if we've already set this span tree */
+ if(spans->op_gen != op_gen) {
H5S_hyper_span_t *span; /* Pointer to current span in span tree */
+ unsigned u; /* Local index variable */
- /* Set the tree's scratch pointer */
- spans->scratch = (H5S_hyper_span_info_t *)~((size_t)NULL);
+ /* Adjust the span tree's low & high bounds */
+ for(u = 0; u < rank; u++) {
+ HDassert((hssize_t)spans->low_bounds[u] >= offset[u]);
+ spans->low_bounds[u] = (hsize_t)((hssize_t)spans->low_bounds[u] - offset[u]);
+ spans->high_bounds[u] = (hsize_t)((hssize_t)spans->high_bounds[u] - offset[u]);
+ } /* end for */
/* Iterate over the spans in tree */
span = spans->head;
@@ -4653,17 +6943,20 @@ H5S__hyper_adjust_s_helper(H5S_hyper_span_info_t *spans,
/* Recursively adjust spans in next dimension down */
if(span->down != NULL)
- H5S__hyper_adjust_s_helper(span->down, offset + 1);
+ H5S__hyper_adjust_s_helper(span->down, rank - 1, offset + 1, op_gen);
/* Advance to next span in this dimension */
span = span->next;
} /* end while */
+
+ /* Set the tree's operation generation */
+ spans->op_gen = op_gen;
} /* end if */
FUNC_LEAVE_NOAPI_VOID
} /* end H5S__hyper_adjust_s_helper() */
-
+
/*--------------------------------------------------------------------------
NAME
H5S_hyper_adjust_s
@@ -4685,6 +6978,8 @@ H5S__hyper_adjust_s_helper(H5S_hyper_span_info_t *spans,
herr_t
H5S_hyper_adjust_s(H5S_t *space, const hssize_t *offset)
{
+ hbool_t non_zero_offset = FALSE; /* Whether any offset is non-zero */
+ unsigned u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
@@ -4693,29 +6988,86 @@ H5S_hyper_adjust_s(H5S_t *space, const hssize_t *offset)
HDassert(space);
HDassert(offset);
- /* Subtract the offset from the "regular" coordinates, if they exist */
- if(space->select.sel_info.hslab->diminfo_valid) {
- unsigned u; /* Local index variable */
+ /* Check for an all-zero offset vector */
+ for(u = 0; u < space->extent.rank; u++)
+ if(0 != offset[u]) {
+ non_zero_offset = TRUE;
+ break;
+ } /* end if */
- for(u = 0; u < space->extent.rank; u++) {
- HDassert((hssize_t)space->select.sel_info.hslab->opt_diminfo[u].start >= offset[u]);
- space->select.sel_info.hslab->opt_diminfo[u].start = (hsize_t)((hssize_t)space->select.sel_info.hslab->opt_diminfo[u].start - offset[u]);
- } /* end for */
- } /* end if */
+ /* Only perform operation if the offset is non-zero */
+ if(non_zero_offset) {
+ /* Subtract the offset from the "regular" coordinates, if they exist */
+ /* (No need to rebuild the dimension info yet -QAK) */
+ if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) {
+ for(u = 0; u < space->extent.rank; u++) {
+ HDassert((hssize_t)space->select.sel_info.hslab->diminfo.opt[u].start >= offset[u]);
+ space->select.sel_info.hslab->diminfo.opt[u].start = (hsize_t)((hssize_t)space->select.sel_info.hslab->diminfo.opt[u].start - offset[u]);
- /* Subtract the offset from the span tree coordinates, if they exist */
- if(space->select.sel_info.hslab->span_lst) {
- H5S__hyper_adjust_s_helper(space->select.sel_info.hslab->span_lst, offset);
+ /* Adjust the low & high bounds */
+ HDassert((hssize_t)space->select.sel_info.hslab->diminfo.low_bounds[u] >= offset[u]);
+ space->select.sel_info.hslab->diminfo.low_bounds[u] = (hsize_t)((hssize_t)space->select.sel_info.hslab->diminfo.low_bounds[u] - offset[u]);
+ space->select.sel_info.hslab->diminfo.high_bounds[u] = (hsize_t)((hssize_t)space->select.sel_info.hslab->diminfo.high_bounds[u] - offset[u]);
+ } /* end for */
+ } /* end if */
+
+ /* Subtract the offset from the span tree coordinates, if they exist */
+ if(space->select.sel_info.hslab->span_lst) {
+ uint64_t op_gen; /* Operation generation value */
+
+ /* Acquire an operation generation value for this operation */
+ op_gen = H5S__hyper_get_op_gen();
- /* Reset the scratch pointers for the next routine which needs them */
- H5S__hyper_span_scratch(space->select.sel_info.hslab->span_lst);
+ H5S__hyper_adjust_s_helper(space->select.sel_info.hslab->span_lst, space->extent.rank, offset, op_gen);
+ } /* end if */
} /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_hyper_adjust_s() */
-
+/*--------------------------------------------------------------------------
+ NAME
+ H5Shyper_adjust_s
+ PURPOSE
+ Adjust a hyperslab selection by subtracting an offset
+ USAGE
+ herr_t H5Shyper_adjust_s(space_id,offset)
+ hid_t space_id; IN: ID of the dataspace to adjust
+ const hssize_t *offset; IN: Offset to subtract
+ RETURNS
+ Non-negative on success, negative on failure
+ DESCRIPTION
+ Moves a hyperslab selection by subtracting an offset from it.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5Shyper_adjust_s(hid_t space_id, const hssize_t *offset)
+{
+ H5S_t *space;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE2("e", "i*Hs", space_id, offset);
+
+ if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "not a dataspace")
+ if(H5S_GET_SELECT_TYPE(space) != H5S_SEL_HYPERSLABS)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a hyperslab selection")
+ if(NULL == offset)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "NULL offset pointer")
+
+ if(H5S_hyper_adjust_s(space, offset) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't adjust selection")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Shyper_adjust_s() */
+
+
/*--------------------------------------------------------------------------
NAME
H5S_hyper_normalize_offset
@@ -4723,11 +7075,11 @@ done:
"Normalize" a hyperslab selection by adjusting it's coordinates by the
amount of the selection offset.
USAGE
- hbool_t H5S_hyper_normalize_offset(space, old_offset)
+ htri_t H5S_hyper_normalize_offset(space, old_offset)
H5S_t *space; IN/OUT: Pointer to dataspace to move
hssize_t *old_offset; OUT: Pointer to space to store old offset
RETURNS
- TRUE if space has been normalized, FALSE if not
+ TRUE/FALSE for hyperslab selection, FAIL on error
DESCRIPTION
Copies the current selection offset into the array provided, then
inverts the selection offset, subtracts the offset from the hyperslab
@@ -4740,7 +7092,7 @@ done:
htri_t
H5S_hyper_normalize_offset(H5S_t *space, hssize_t *old_offset)
{
- htri_t ret_value = FALSE; /* Return value */
+ htri_t ret_value = FALSE; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
@@ -4773,7 +7125,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_hyper_normalize_offset() */
-
+
/*--------------------------------------------------------------------------
NAME
H5S_hyper_denormalize_offset
@@ -4811,25 +7163,24 @@ H5S_hyper_denormalize_offset(H5S_t *space, const hssize_t *old_offset)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't adjust selection")
/* Copy the selection offset over */
- HDmemcpy(space->select.offset, old_offset, sizeof(hssize_t) * space->extent.rank);
+ H5MM_memcpy(space->select.offset, old_offset, sizeof(hssize_t) * space->extent.rank);
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_hyper_denormalize_offset() */
-
+
/*--------------------------------------------------------------------------
NAME
H5S__hyper_append_span
PURPOSE
Create a new span and append to span list
USAGE
- herr_t H5S__hyper_append_span(prev_span, span_tree, low, high, down, next)
- H5S_hyper_span_t **prev_span; IN/OUT: Pointer to previous span in list
+ herr_t H5S__hyper_append_span(span_tree, ndims, low, high, down)
H5S_hyper_span_info_t **span_tree; IN/OUT: Pointer to span tree to append to
- hsize_t low, high; IN: Low and high bounds for new span node
+ unsigned ndims; IN: Number of dimension for span
+ hsize_t low, high; IN: Low and high bounds for new span node
H5S_hyper_span_info_t *down; IN: Down span tree for new node
- H5S_hyper_span_t *next; IN: Next span for new node
RETURNS
Non-negative on success, negative on failure
DESCRIPTION
@@ -4841,95 +7192,140 @@ done:
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S__hyper_append_span(H5S_hyper_span_t **prev_span,
- H5S_hyper_span_info_t **span_tree, hsize_t low, hsize_t high, H5S_hyper_span_info_t *down, H5S_hyper_span_t *next)
+H5S__hyper_append_span(H5S_hyper_span_info_t **span_tree, unsigned ndims,
+ hsize_t low, hsize_t high, H5S_hyper_span_info_t *down)
{
H5S_hyper_span_t *new_span = NULL;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC
- HDassert(prev_span);
+ /* Sanity check */
HDassert(span_tree);
/* Check for adding first node to merged spans */
- if(*prev_span == NULL) {
+ if(*span_tree == NULL) {
/* Allocate new span node to append to list */
- if(NULL == (new_span = H5S__hyper_new_span(low, high, down, next)))
+ if(NULL == (new_span = H5S__hyper_new_span(low, high, down, NULL)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate hyperslab span")
- /* Make first node in span list */
-
- /* Check that we haven't already allocated a span tree */
- HDassert(*span_tree == NULL);
+ /* Make new span the first node in span list */
/* Allocate a new span_info node */
- if(NULL == (*span_tree = H5FL_CALLOC(H5S_hyper_span_info_t)))
+ if(NULL == (*span_tree = H5S__hyper_new_span_info(ndims)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate hyperslab span")
/* Set the span tree's basic information */
(*span_tree)->count = 1;
(*span_tree)->head = new_span;
+ (*span_tree)->tail = new_span;
+
+ /* Set low & high bounds for new span tree */
+ (*span_tree)->low_bounds[0] = low;
+ (*span_tree)->high_bounds[0] = high;
+ if(down) {
+ /* Sanity check */
+ HDassert(ndims > 1);
- /* Update previous merged span */
- *prev_span = new_span;
+ H5MM_memcpy(&((*span_tree)->low_bounds[1]), down->low_bounds, sizeof(hsize_t) * (ndims - 1));
+ H5MM_memcpy(&((*span_tree)->high_bounds[1]), down->high_bounds, sizeof(hsize_t) * (ndims - 1));
+ } /* end if */
} /* end if */
/* Merge or append to existing merged spans list */
else {
+ htri_t down_cmp = (-1); /* Comparison value for down spans */
+
/* Check if span can just extend the previous merged span */
- if((((*prev_span)->high + 1) == low) &&
- H5S__hyper_cmp_spans(down, (*prev_span)->down)==TRUE) {
+ if((((*span_tree)->tail->high + 1) == low) &&
+ (down_cmp = H5S__hyper_cmp_spans(down, (*span_tree)->tail->down))) {
/* Extend previous merged span to include new high bound */
- (*prev_span)->high = high;
- (*prev_span)->nelem += (high - low) + 1;
+ (*span_tree)->tail->high = high;
+
+ /* Extend span tree's high bound in this dimension */
+ /* (No need to update lower dimensions, since this span shares them with previous span) */
+ (*span_tree)->high_bounds[0] = high;
} /* end if */
else {
- /* Allocate new span node to append to list */
- if(NULL == (new_span = H5S__hyper_new_span(low, high, down, next)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span")
+ H5S_hyper_span_info_t *new_down; /* Down pointer for new span node */
+
+ /* Sanity check */
+ /* (If down_cmp was set to TRUE above, we won't be in this branch) */
+ HDassert(down_cmp != TRUE);
/* Check if there is actually a down span */
- if(new_span->down) {
+ if(down) {
/* Check if the down spans for the new span node are the same as the previous span node */
- if(H5S__hyper_cmp_spans(new_span->down, (*prev_span)->down)) {
- /* Release the down span for the new node */
- H5S__hyper_free_span_info(new_span->down);
-
- /* Point the new node's down span at the previous node's down span */
- new_span->down = (*prev_span)->down;
+ /* (Uses the 'down span comparison' from earlier, if already computed) */
+ if(down_cmp < 0 && (down_cmp = H5S__hyper_cmp_spans(down, (*span_tree)->tail->down)))
+ /* Share the previous span's down span tree */
+ new_down = (*span_tree)->tail->down;
+ else
+ new_down = down;
+ } /* end if */
+ else
+ new_down = NULL;
- /* Increment the reference count to the shared down span */
- new_span->down->count++;
+ /* Allocate new span node to append to list */
+ if(NULL == (new_span = H5S__hyper_new_span(low, high, new_down, NULL)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate hyperslab span")
+
+ /* Update the high bounds for current dimension */
+ (*span_tree)->high_bounds[0] = high;
+
+ /* Update low & high bounds in lower dimensions, if there are any */
+ if(down) {
+ /* Sanity checks */
+ HDassert(ndims > 1);
+ HDassert(down_cmp >= 0);
+
+ /* Check if we are sharing down spans with a previous node */
+ /* (Only need to check for bounds changing if down spans aren't shared) */
+ if(down_cmp == FALSE) {
+ unsigned u; /* Local index variable */
+
+ /* Loop over lower dimensions, checking & updating low & high bounds */
+ for(u = 0; u < (ndims - 1); u++) {
+ if(down->low_bounds[u] < (*span_tree)->low_bounds[u + 1])
+ (*span_tree)->low_bounds[u + 1] = down->low_bounds[u];
+ if(down->high_bounds[u] > (*span_tree)->high_bounds[u + 1])
+ (*span_tree)->high_bounds[u + 1] = down->high_bounds[u];
+ } /* end for */
} /* end if */
} /* end if */
- /* Indicate elements from previous span */
- new_span->pstride = low - (*prev_span)->low;
-
/* Append to end of merged spans list */
- (*prev_span)->next = new_span;
- *prev_span = new_span;
+ (*span_tree)->tail->next = new_span;
+ (*span_tree)->tail = new_span;
} /* end else */
} /* end else */
done:
if(ret_value < 0)
- if(new_span && H5S__hyper_free_span(new_span) < 0)
- HDONE_ERROR(H5E_DATASPACE, H5E_CANTFREE, FAIL, "failed to release new hyperslab span")
+ if(new_span)
+ H5S__hyper_free_span(new_span);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S__hyper_append_span() */
-
+
/*--------------------------------------------------------------------------
NAME
H5S__hyper_clip_spans
PURPOSE
Clip a new span tree against the current spans in the hyperslab selection
USAGE
- herr_t H5S__hyper_clip_spans(span_a, span_b, a_not_b, a_and_b, b_not_a)
+ herr_t H5S__hyper_clip_spans(span_a, span_b, selector, curr_dim, dim_size,
+ span_a_b_bounds[4], all_clips_bound,
+ a_not_b, a_and_b, b_not_a)
H5S_hyper_span_t *a_spans; IN: Span tree 'a' to clip with.
H5S_hyper_span_t *b_spans; IN: Span tree 'b' to clip with.
+ unsigned selector; IN: The parameter deciding which output is needed
+ (only considering the last three bits ABC:
+ If A is set, then a_not_b is needed;
+ If B is set, then a_and_b is needed;
+ If C is set, then b_not_a is needed;
+ )
+ unsigned ndims; IN: Number of dimensions of this span tree
H5S_hyper_span_t **a_not_b; OUT: Span tree of 'a' hyperslab spans which
doesn't overlap with 'b' hyperslab
spans.
@@ -4943,9 +7339,10 @@ done:
DESCRIPTION
Clip one span tree ('a') against another span tree ('b'). Creates span
trees for the area defined by the 'a' span tree which does not overlap the
- 'b' span tree, the area defined by the overlap of the 'a' hyperslab span
- tree and the 'b' span tree, and the area defined by the 'b' hyperslab span
- tree which does not overlap the 'a' span tree.
+ 'b' span tree ("a not b"), the area defined by the overlap of the 'a'
+ hyperslab span tree and the 'b' span tree ("a and b"), and the area defined
+ by the 'b' hyperslab span tree which does not overlap the 'a' span
+ tree ("b not a").
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
EXAMPLES
@@ -4953,20 +7350,14 @@ done:
--------------------------------------------------------------------------*/
static herr_t
H5S__hyper_clip_spans(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_spans,
+ unsigned selector, unsigned ndims,
H5S_hyper_span_info_t **a_not_b, H5S_hyper_span_info_t **a_and_b,
H5S_hyper_span_info_t **b_not_a)
{
- H5S_hyper_span_t *span_a; /* Pointer to a node in span tree 'a' */
- H5S_hyper_span_t *span_b; /* Pointer to a node in span tree 'b' */
- H5S_hyper_span_t *tmp_span; /* Temporary pointer to new span */
- H5S_hyper_span_t *last_a_not_b; /* Pointer to previous node in span tree 'a_not_b' */
- H5S_hyper_span_t *last_a_and_b; /* Pointer to previous node in span tree 'a_and_b' */
- H5S_hyper_span_t *last_b_not_a; /* Pointer to previous node in span tree 'b_not_a' */
- H5S_hyper_span_info_t *down_a_not_b; /* Temporary pointer to a_not_b span tree of down spans for overlapping nodes */
- H5S_hyper_span_info_t *down_a_and_b; /* Temporary pointer to a_and_b span tree of down spans for overlapping nodes */
- H5S_hyper_span_info_t *down_b_not_a; /* Temporary pointer to b_and_a span tree of down spans for overlapping nodes */
- hbool_t recover_a, recover_b; /* Flags to indicate when to recover temporary spans */
- herr_t ret_value = SUCCEED; /* Return value */
+ hbool_t need_a_not_b; /* Whether to generate a_not_b list */
+ hbool_t need_a_and_b; /* Whether to generate a_and_b list */
+ hbool_t need_b_not_a; /* Whether to generate b_not_a list */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC
@@ -4977,6 +7368,11 @@ H5S__hyper_clip_spans(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s
HDassert(a_and_b);
HDassert(b_not_a);
+ /* Set which list(s) to be generated, based on selector */
+ need_a_not_b = ((selector & H5S_HYPER_COMPUTE_A_NOT_B) != 0);
+ need_a_and_b = ((selector & H5S_HYPER_COMPUTE_A_AND_B) != 0);
+ need_b_not_a = ((selector & H5S_HYPER_COMPUTE_B_NOT_A) != 0);
+
/* Check if both span trees are not defined */
if(a_spans == NULL && b_spans == NULL) {
*a_not_b = NULL;
@@ -4987,38 +7383,56 @@ H5S__hyper_clip_spans(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s
else if(a_spans == NULL) {
*a_not_b = NULL;
*a_and_b = NULL;
- if(NULL == (*b_not_a = H5S__hyper_copy_span(b_spans)))
- HGOTO_ERROR(H5E_INTERNAL, H5E_CANTCOPY, FAIL, "can't copy hyperslab span tree")
+ if(need_b_not_a) {
+ if(NULL == (*b_not_a = H5S__hyper_copy_span(b_spans, ndims)))
+ HGOTO_ERROR(H5E_INTERNAL, H5E_CANTCOPY, FAIL, "can't copy hyperslab span tree")
+ } /* end if */
+ else
+ *b_not_a = NULL;
} /* end if */
/* If span 'b' is not defined, but 'a' is, copy 'a' and set the other return span trees to empty */
else if(b_spans == NULL) {
- if(NULL == (*a_not_b = H5S__hyper_copy_span(a_spans)) )
- HGOTO_ERROR(H5E_INTERNAL, H5E_CANTCOPY, FAIL, "can't copy hyperslab span tree")
*a_and_b = NULL;
*b_not_a = NULL;
+ if(need_a_not_b) {
+ if(NULL == (*a_not_b = H5S__hyper_copy_span(a_spans, ndims)))
+ HGOTO_ERROR(H5E_INTERNAL, H5E_CANTCOPY, FAIL, "can't copy hyperslab span tree")
+ } /* end if */
+ else
+ *a_not_b = NULL;
} /* end if */
/* If span 'a' and 'b' are both defined, calculate the proper span trees */
else {
/* Check if both span trees completely overlap */
if(H5S__hyper_cmp_spans(a_spans, b_spans)) {
*a_not_b = NULL;
- if(NULL == (*a_and_b = H5S__hyper_copy_span(a_spans)))
- HGOTO_ERROR(H5E_INTERNAL, H5E_CANTCOPY, FAIL, "can't copy hyperslab span tree")
*b_not_a = NULL;
+ if(need_a_and_b) {
+ if(NULL == (*a_and_b = H5S__hyper_copy_span(a_spans, ndims)))
+ HGOTO_ERROR(H5E_INTERNAL, H5E_CANTCOPY, FAIL, "can't copy hyperslab span tree")
+ } /* end if */
+ else
+ *a_and_b = NULL;
} /* end if */
else {
+ H5S_hyper_span_t *span_a; /* Pointer to a node in span tree 'a' */
+ H5S_hyper_span_t *span_b; /* Pointer to a node in span tree 'b' */
+ hbool_t recover_a, recover_b; /* Flags to indicate when to recover temporary spans */
+
/* Get the pointers to the new and old span lists */
span_a = a_spans->head;
span_b = b_spans->head;
- /* Reset the pointers to the previous spans */
- last_a_not_b = last_a_and_b = last_b_not_a = NULL;
-
/* No spans to recover yet */
recover_a = recover_b = FALSE;
/* Work through the list of spans in the new list */
while(span_a != NULL && span_b != NULL) {
+ H5S_hyper_span_info_t *down_a_not_b; /* Temporary pointer to a_not_b span tree of down spans for overlapping nodes */
+ H5S_hyper_span_info_t *down_a_and_b; /* Temporary pointer to a_and_b span tree of down spans for overlapping nodes */
+ H5S_hyper_span_info_t *down_b_not_a; /* Temporary pointer to b_and_a span tree of down spans for overlapping nodes */
+ H5S_hyper_span_t *tmp_span; /* Temporary pointer to new span */
+
/* Check if span 'a' is completely before span 'b' */
/* AAAAAAA */
/* <-----------------------------------> */
@@ -5027,11 +7441,12 @@ H5S__hyper_clip_spans(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s
/* Copy span 'a' and add to a_not_b list */
/* Merge/add span 'a' with/to a_not_b list */
- if(H5S__hyper_append_span(&last_a_not_b, a_not_b, span_a->low, span_a->high, span_a->down, NULL) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+ if(need_a_not_b)
+ if(H5S__hyper_append_span(a_not_b, ndims, span_a->low, span_a->high, span_a->down) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
/* Advance span 'a', leave span 'b' */
- H5S__hyper_recover_span(&recover_a, &span_a, span_a->next);
+ H5S_HYPER_ADVANCE_SPAN(recover_a, span_a, span_a->next);
} /* end if */
/* Check if span 'a' overlaps only the lower bound */
/* of span 'b' , up to the upper bound of span 'b' */
@@ -5042,8 +7457,9 @@ H5S__hyper_clip_spans(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s
/* Split span 'a' into two parts at the low bound of span 'b' */
/* Merge/add lower part of span 'a' with/to a_not_b list */
- if(H5S__hyper_append_span(&last_a_not_b, a_not_b, span_a->low, span_b->low - 1, span_a->down, NULL) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+ if(need_a_not_b)
+ if(H5S__hyper_append_span(a_not_b, ndims, span_a->low, span_b->low - 1, span_a->down) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
/* Check for overlaps between upper part of span 'a' and lower part of span 'b' */
@@ -5053,8 +7469,9 @@ H5S__hyper_clip_spans(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s
/* If there are no down spans, just add the overlapping area to the a_and_b list */
if(span_a->down == NULL) {
/* Merge/add overlapped part with/to a_and_b list */
- if(H5S__hyper_append_span(&last_a_and_b, a_and_b, span_b->low, span_a->high, NULL, NULL) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+ if(need_a_and_b)
+ if(H5S__hyper_append_span(a_and_b, ndims, span_b->low, span_a->high, NULL) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
} /* end if */
/* If there are down spans, check for the overlap in them and add to each appropriate list */
else {
@@ -5064,14 +7481,20 @@ H5S__hyper_clip_spans(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s
down_b_not_a = NULL;
/* Check for overlaps in the 'down spans' of span 'a' & 'b' */
- if(H5S__hyper_clip_spans(span_a->down,span_b->down,&down_a_not_b,&down_a_and_b,&down_b_not_a)<0)
+ /** Note: since the bound box of remaining dimensions
+ * has been updated in the following clip function (via
+ * all_clips_bounds), there's no need updating the bound box
+ * after each append call in the following codes */
+ if(H5S__hyper_clip_spans(span_a->down, span_b->down, selector, ndims - 1, &down_a_not_b, &down_a_and_b, &down_b_not_a) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL, "can't clip hyperslab information")
/* Check for additions to the a_not_b list */
if(down_a_not_b) {
+ HDassert(need_a_not_b == TRUE);
+
/* Merge/add overlapped part with/to a_not_b list */
- if(H5S__hyper_append_span(&last_a_not_b,a_not_b,span_b->low,span_a->high,down_a_not_b,NULL)==FAIL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+ if(H5S__hyper_append_span(a_not_b, ndims, span_b->low, span_a->high, down_a_not_b) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
/* Release the down span tree generated */
H5S__hyper_free_span_info(down_a_not_b);
@@ -5079,9 +7502,11 @@ H5S__hyper_clip_spans(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s
/* Check for additions to the a_and_b list */
if(down_a_and_b) {
+ HDassert(need_a_and_b == TRUE);
+
/* Merge/add overlapped part with/to a_and_b list */
- if(H5S__hyper_append_span(&last_a_and_b,a_and_b,span_b->low,span_a->high,down_a_and_b,NULL)==FAIL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+ if(H5S__hyper_append_span(a_and_b, ndims, span_b->low, span_a->high, down_a_and_b) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
/* Release the down span tree generated */
H5S__hyper_free_span_info(down_a_and_b);
@@ -5089,9 +7514,11 @@ H5S__hyper_clip_spans(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s
/* Check for additions to the b_not_a list */
if(down_b_not_a) {
+ HDassert(need_b_not_a == TRUE);
+
/* Merge/add overlapped part with/to b_not_a list */
- if(H5S__hyper_append_span(&last_b_not_a,b_not_a,span_b->low,span_a->high,down_b_not_a,NULL)==FAIL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+ if(H5S__hyper_append_span(b_not_a, ndims, span_b->low, span_a->high, down_b_not_a) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
/* Release the down span tree generated */
H5S__hyper_free_span_info(down_b_not_a);
@@ -5101,23 +7528,23 @@ H5S__hyper_clip_spans(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s
/* Split off upper part of span 'b' at upper span of span 'a' */
/* Check if there is actually an upper part of span 'b' to split off */
- if(span_a->high<span_b->high) {
+ if(span_a->high < span_b->high) {
/* Allocate new span node for upper part of span 'b' */
if(NULL == (tmp_span = H5S__hyper_new_span(span_a->high + 1, span_b->high, span_b->down, span_b->next)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span")
+ HGOTO_ERROR(H5E_DATASPACE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span")
/* Advance span 'a' */
- H5S__hyper_recover_span(&recover_a,&span_a,span_a->next);
+ H5S_HYPER_ADVANCE_SPAN(recover_a, span_a, span_a->next);
/* Make upper part of span 'b' into new span 'b' */
- H5S__hyper_recover_span(&recover_b,&span_b,tmp_span);
+ H5S_HYPER_ADVANCE_SPAN(recover_b, span_b, tmp_span);
recover_b = TRUE;
} /* end if */
/* No upper part of span 'b' to split */
else {
/* Advance both 'a' and 'b' */
- H5S__hyper_recover_span(&recover_a,&span_a,span_a->next);
- H5S__hyper_recover_span(&recover_b,&span_b,span_b->next);
+ H5S_HYPER_ADVANCE_SPAN(recover_a, span_a, span_a->next);
+ H5S_HYPER_ADVANCE_SPAN(recover_b, span_b, span_b->next);
} /* end else */
} /* end if */
/* Check if span 'a' overlaps the lower & upper bound */
@@ -5129,8 +7556,9 @@ H5S__hyper_clip_spans(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s
/* Split off lower part of span 'a' at lower span of span 'b' */
/* Merge/add lower part of span 'a' with/to a_not_b list */
- if(H5S__hyper_append_span(&last_a_not_b,a_not_b,span_a->low,span_b->low-1,span_a->down,NULL)==FAIL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+ if(need_a_not_b)
+ if(H5S__hyper_append_span(a_not_b, ndims, span_a->low, span_b->low - 1, span_a->down) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
/* Check for overlaps between middle part of span 'a' and span 'b' */
@@ -5140,8 +7568,9 @@ H5S__hyper_clip_spans(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s
/* If there are no down spans, just add the overlapping area to the a_and_b list */
if(span_a->down == NULL) {
/* Merge/add overlapped part with/to a_and_b list */
- if(H5S__hyper_append_span(&last_a_and_b,a_and_b,span_b->low,span_b->high,NULL,NULL)==FAIL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+ if(need_a_and_b)
+ if(H5S__hyper_append_span(a_and_b, ndims, span_b->low, span_b->high, NULL) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
} /* end if */
/* If there are down spans, check for the overlap in them and add to each appropriate list */
else {
@@ -5151,14 +7580,16 @@ H5S__hyper_clip_spans(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s
down_b_not_a = NULL;
/* Check for overlaps in the 'down spans' of span 'a' & 'b' */
- if(H5S__hyper_clip_spans(span_a->down,span_b->down,&down_a_not_b,&down_a_and_b,&down_b_not_a)<0)
+ if(H5S__hyper_clip_spans(span_a->down, span_b->down, selector, ndims - 1, &down_a_not_b, &down_a_and_b, &down_b_not_a) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL, "can't clip hyperslab information")
/* Check for additions to the a_not_b list */
if(down_a_not_b) {
+ HDassert(need_a_not_b == TRUE);
+
/* Merge/add overlapped part with/to a_not_b list */
- if(H5S__hyper_append_span(&last_a_not_b,a_not_b,span_b->low,span_b->high,down_a_not_b,NULL)==FAIL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+ if(H5S__hyper_append_span(a_not_b, ndims, span_b->low, span_b->high, down_a_not_b) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
/* Release the down span tree generated */
H5S__hyper_free_span_info(down_a_not_b);
@@ -5166,9 +7597,11 @@ H5S__hyper_clip_spans(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s
/* Check for additions to the a_and_b list */
if(down_a_and_b) {
+ HDassert(need_a_and_b == TRUE);
+
/* Merge/add overlapped part with/to a_and_b list */
- if(H5S__hyper_append_span(&last_a_and_b,a_and_b,span_b->low,span_b->high,down_a_and_b,NULL)==FAIL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+ if(H5S__hyper_append_span(a_and_b, ndims, span_b->low, span_b->high, down_a_and_b) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
/* Release the down span tree generated */
H5S__hyper_free_span_info(down_a_and_b);
@@ -5176,9 +7609,11 @@ H5S__hyper_clip_spans(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s
/* Check for additions to the b_not_a list */
if(down_b_not_a) {
+ HDassert(need_b_not_a == TRUE);
+
/* Merge/add overlapped part with/to b_not_a list */
- if(H5S__hyper_append_span(&last_b_not_a,b_not_a,span_b->low,span_b->high,down_b_not_a,NULL)==FAIL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+ if(H5S__hyper_append_span(b_not_a, ndims, span_b->low, span_b->high, down_b_not_a) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
/* Release the down span tree generated */
H5S__hyper_free_span_info(down_b_not_a);
@@ -5192,11 +7627,11 @@ H5S__hyper_clip_spans(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s
HGOTO_ERROR(H5E_DATASPACE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span")
/* Make upper part of span 'a' the new span 'a' */
- H5S__hyper_recover_span(&recover_a,&span_a,tmp_span);
+ H5S_HYPER_ADVANCE_SPAN(recover_a, span_a, tmp_span);
recover_a = TRUE;
/* Advance span 'b' */
- H5S__hyper_recover_span(&recover_b,&span_b,span_b->next);
+ H5S_HYPER_ADVANCE_SPAN(recover_b, span_b, span_b->next);
} /* end if */
/* Check if span 'a' is entirely within span 'b' */
/* AAAAA */
@@ -5208,8 +7643,9 @@ H5S__hyper_clip_spans(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s
/* Check if there is actually a lower part of span 'b' to split off */
if(span_a->low > span_b->low) {
/* Merge/add lower part of span 'b' with/to b_not_a list */
- if(H5S__hyper_append_span(&last_b_not_a,b_not_a,span_b->low,span_a->low-1,span_b->down,NULL)==FAIL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+ if(need_b_not_a)
+ if(H5S__hyper_append_span(b_not_a, ndims, span_b->low, span_a->low - 1, span_b->down) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
} /* end if */
else {
/* Keep going, nothing to split off */
@@ -5223,8 +7659,9 @@ H5S__hyper_clip_spans(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s
/* If there are no down spans, just add the overlapping area to the a_and_b list */
if(span_a->down == NULL) {
/* Merge/add overlapped part with/to a_and_b list */
- if(H5S__hyper_append_span(&last_a_and_b,a_and_b,span_a->low,span_a->high,NULL,NULL)==FAIL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+ if(need_a_and_b)
+ if(H5S__hyper_append_span(a_and_b, ndims, span_a->low, span_a->high, NULL) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
} /* end if */
/* If there are down spans, check for the overlap in them and add to each appropriate list */
else {
@@ -5234,34 +7671,40 @@ H5S__hyper_clip_spans(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s
down_b_not_a = NULL;
/* Check for overlaps in the 'down spans' of span 'a' & 'b' */
- if(H5S__hyper_clip_spans(span_a->down,span_b->down,&down_a_not_b,&down_a_and_b,&down_b_not_a)<0)
+ if(H5S__hyper_clip_spans(span_a->down, span_b->down, selector, ndims - 1, &down_a_not_b, &down_a_and_b, &down_b_not_a) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL, "can't clip hyperslab information")
/* Check for additions to the a_not_b list */
if(down_a_not_b) {
+ HDassert(need_a_not_b == TRUE);
+
/* Merge/add overlapped part with/to a_not_b list */
- if(H5S__hyper_append_span(&last_a_not_b,a_not_b,span_a->low,span_a->high,down_a_not_b,NULL)==FAIL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+ if(H5S__hyper_append_span(a_not_b, ndims, span_a->low, span_a->high, down_a_not_b) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
/* Release the down span tree generated */
H5S__hyper_free_span_info(down_a_not_b);
} /* end if */
/* Check for additions to the a_and_b list */
- if(down_a_and_b!=NULL) {
+ if(down_a_and_b) {
+ HDassert(need_a_and_b == TRUE);
+
/* Merge/add overlapped part with/to a_and_b list */
- if(H5S__hyper_append_span(&last_a_and_b,a_and_b,span_a->low,span_a->high,down_a_and_b,NULL)==FAIL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+ if(H5S__hyper_append_span(a_and_b, ndims, span_a->low, span_a->high, down_a_and_b) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
/* Release the down span tree generated */
H5S__hyper_free_span_info(down_a_and_b);
} /* end if */
/* Check for additions to the b_not_a list */
- if(down_b_not_a!=NULL) {
+ if(down_b_not_a) {
+ HDassert(need_b_not_a == TRUE);
+
/* Merge/add overlapped part with/to b_not_a list */
- if(H5S__hyper_append_span(&last_b_not_a,b_not_a,span_a->low,span_a->high,down_b_not_a,NULL)==FAIL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+ if(H5S__hyper_append_span(b_not_a, ndims, span_a->low, span_a->high, down_b_not_a) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
/* Release the down span tree generated */
H5S__hyper_free_span_info(down_b_not_a);
@@ -5269,24 +7712,24 @@ H5S__hyper_clip_spans(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s
} /* end else */
/* Check if there is actually an upper part of span 'b' to split off */
- if(span_a->high<span_b->high) {
+ if(span_a->high < span_b->high) {
/* Split off upper part of span 'b' at upper span of span 'a' */
/* Allocate new span node for upper part of spans 'a' */
if(NULL == (tmp_span = H5S__hyper_new_span(span_a->high + 1, span_b->high, span_b->down, span_b->next)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span")
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate hyperslab span")
/* And advance span 'a' */
- H5S__hyper_recover_span(&recover_a,&span_a,span_a->next);
+ H5S_HYPER_ADVANCE_SPAN(recover_a, span_a, span_a->next);
/* Make upper part of span 'b' the new span 'b' */
- H5S__hyper_recover_span(&recover_b,&span_b,tmp_span);
- recover_b=1;
+ H5S_HYPER_ADVANCE_SPAN(recover_b, span_b, tmp_span);
+ recover_b = TRUE;
} /* end if */
else {
/* Advance both span 'a' & span 'b' */
- H5S__hyper_recover_span(&recover_a,&span_a,span_a->next);
- H5S__hyper_recover_span(&recover_b,&span_b,span_b->next);
+ H5S_HYPER_ADVANCE_SPAN(recover_a, span_a, span_a->next);
+ H5S_HYPER_ADVANCE_SPAN(recover_b, span_b, span_b->next);
} /* end else */
} /* end if */
/* Check if span 'a' overlaps only the upper bound */
@@ -5294,14 +7737,15 @@ H5S__hyper_clip_spans(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s
/* AAAAAAAAAA */
/* <-----------------------------------> */
/* BBBBBBBBBB */
- else if((span_a->low>=span_b->low && span_a->low<=span_b->high) && span_a->high>span_b->high) {
+ else if((span_a->low >= span_b->low && span_a->low <= span_b->high) && span_a->high > span_b->high) {
/* Check if there is actually a lower part of span 'b' to split off */
- if(span_a->low>span_b->low) {
+ if(span_a->low > span_b->low) {
/* Split off lower part of span 'b' at lower span of span 'a' */
/* Merge/add lower part of span 'b' with/to b_not_a list */
- if(H5S__hyper_append_span(&last_b_not_a,b_not_a,span_b->low,span_a->low-1,span_b->down,NULL)==FAIL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+ if(need_b_not_a)
+ if(H5S__hyper_append_span(b_not_a, ndims, span_b->low, span_a->low - 1, span_b->down) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
} /* end if */
else {
/* Keep going, nothing to split off */
@@ -5315,8 +7759,9 @@ H5S__hyper_clip_spans(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s
/* If there are no down spans, just add the overlapping area to the a_and_b list */
if(span_a->down == NULL) {
/* Merge/add overlapped part with/to a_and_b list */
- if(H5S__hyper_append_span(&last_a_and_b,a_and_b,span_a->low,span_b->high,NULL,NULL)==FAIL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+ if(need_a_and_b)
+ if(H5S__hyper_append_span(a_and_b, ndims, span_a->low, span_b->high, NULL) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
} /* end if */
/* If there are down spans, check for the overlap in them and add to each appropriate list */
else {
@@ -5326,24 +7771,28 @@ H5S__hyper_clip_spans(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s
down_b_not_a = NULL;
/* Check for overlaps in the 'down spans' of span 'a' & 'b' */
- if(H5S__hyper_clip_spans(span_a->down,span_b->down,&down_a_not_b,&down_a_and_b,&down_b_not_a)<0)
+ if(H5S__hyper_clip_spans(span_a->down, span_b->down, selector, ndims - 1, &down_a_not_b, &down_a_and_b, &down_b_not_a) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL, "can't clip hyperslab information")
/* Check for additions to the a_not_b list */
if(down_a_not_b) {
+ HDassert(need_a_not_b == TRUE);
+
/* Merge/add overlapped part with/to a_not_b list */
- if(H5S__hyper_append_span(&last_a_not_b,a_not_b,span_a->low,span_b->high,down_a_not_b,NULL)==FAIL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+ if(H5S__hyper_append_span(a_not_b, ndims, span_a->low, span_b->high, down_a_not_b) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
/* Release the down span tree generated */
H5S__hyper_free_span_info(down_a_not_b);
} /* end if */
/* Check for additions to the a_and_b list */
- if(down_a_and_b!=NULL) {
+ if(down_a_and_b) {
+ HDassert(need_a_and_b == TRUE);
+
/* Merge/add overlapped part with/to a_and_b list */
- if(H5S__hyper_append_span(&last_a_and_b,a_and_b,span_a->low,span_b->high,down_a_and_b,NULL)==FAIL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+ if(H5S__hyper_append_span(a_and_b, ndims, span_a->low, span_b->high, down_a_and_b) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
/* Release the down span tree generated */
H5S__hyper_free_span_info(down_a_and_b);
@@ -5351,9 +7800,11 @@ H5S__hyper_clip_spans(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s
/* Check for additions to the b_not_a list */
if(down_b_not_a) {
+ HDassert(need_b_not_a == TRUE);
+
/* Merge/add overlapped part with/to b_not_a list */
- if(H5S__hyper_append_span(&last_b_not_a,b_not_a,span_a->low,span_b->high,down_b_not_a,NULL)==FAIL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+ if(H5S__hyper_append_span(b_not_a, ndims, span_a->low, span_b->high, down_b_not_a) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
/* Release the down span tree generated */
H5S__hyper_free_span_info(down_b_not_a);
@@ -5364,14 +7815,14 @@ H5S__hyper_clip_spans(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s
/* Allocate new span node for upper part of span 'a' */
if(NULL == (tmp_span = H5S__hyper_new_span(span_b->high + 1, span_a->high, span_a->down, span_a->next)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span")
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate hyperslab span")
/* Make upper part of span 'a' into new span 'a' */
- H5S__hyper_recover_span(&recover_a,&span_a,tmp_span);
- recover_a=1;
+ H5S_HYPER_ADVANCE_SPAN(recover_a, span_a, tmp_span);
+ recover_a = TRUE;
/* Advance span 'b' */
- H5S__hyper_recover_span(&recover_b,&span_b,span_b->next);
+ H5S_HYPER_ADVANCE_SPAN(recover_b, span_b, span_b->next);
} /* end if */
/* span 'a' must be entirely above span 'b' */
/* AAAAA */
@@ -5381,40 +7832,70 @@ H5S__hyper_clip_spans(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s
/* Copy span 'b' and add to b_not_a list */
/* Merge/add span 'b' with/to b_not_a list */
- if(H5S__hyper_append_span(&last_b_not_a,b_not_a,span_b->low,span_b->high,span_b->down,NULL)==FAIL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+ if(need_b_not_a)
+ if(H5S__hyper_append_span(b_not_a, ndims, span_b->low, span_b->high, span_b->down) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
/* Advance span 'b', leave span 'a' */
- H5S__hyper_recover_span(&recover_b,&span_b,span_b->next);
+ H5S_HYPER_ADVANCE_SPAN(recover_b, span_b, span_b->next);
} /* end else */
} /* end while */
/* Clean up 'a' spans which haven't been covered yet */
if(span_a != NULL && span_b == NULL) {
- while(span_a != NULL) {
- /* Copy span 'a' and add to a_not_b list */
-
- /* Merge/add span 'a' with/to a_not_b list */
- if(H5S__hyper_append_span(&last_a_not_b,a_not_b,span_a->low,span_a->high,span_a->down,NULL)==FAIL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+ /* Check if need to merge/add 'a' spans with/to a_not_b list */
+ if(need_a_not_b) {
+ /* (This loop, and the similar one below for 'b' spans,
+ * could be replaced with an optimized routine that quickly
+ * appended the remaining spans to the 'not' list, but
+ * until it looks like it's taking a lot of time for an
+ * important use case, it's been left generic, and similar
+ * to other code above. -QAK, 2019/02/01)
+ */
+ while(span_a != NULL) {
+ /* Copy span 'a' and add to a_not_b list */
+ if(H5S__hyper_append_span(a_not_b, ndims, span_a->low, span_a->high, span_a->down) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
- /* Advance to the next 'a' span */
- H5S__hyper_recover_span(&recover_a,&span_a,span_a->next);
- } /* end while */
+ /* Advance to the next 'a' span */
+ H5S_HYPER_ADVANCE_SPAN(recover_a, span_a, span_a->next);
+ } /* end while */
+ } /* end if */
+ else {
+ /* Free the span, if it's generated */
+ if(recover_a)
+ H5S__hyper_free_span(span_a);
+ } /* end else */
} /* end if */
/* Clean up 'b' spans which haven't been covered yet */
else if(span_a == NULL && span_b != NULL) {
- while(span_b != NULL) {
- /* Copy span 'b' and add to b_not_a list */
-
- /* Merge/add span 'b' with/to b_not_a list */
- if(H5S__hyper_append_span(&last_b_not_a,b_not_a,span_b->low,span_b->high,span_b->down,NULL)==FAIL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+ /* Check if need to merge/add 'b' spans with/to b_not_a list */
+ if(need_b_not_a) {
+ /* (This loop, and the similar one above for 'a' spans,
+ * could be replaced with an optimized routine that quickly
+ * appended the remaining spans to the 'not' list, but
+ * until it looks like it's taking a lot of time for an
+ * important use case, it's been left generic, and similar
+ * to other code above. -QAK, 2019/02/01)
+ */
+ while(span_b != NULL) {
+ /* Copy span 'b' and add to b_not_a list */
+ if(H5S__hyper_append_span(b_not_a, ndims, span_b->low, span_b->high, span_b->down) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
- /* Advance to the next 'b' span */
- H5S__hyper_recover_span(&recover_b,&span_b,span_b->next);
- } /* end while */
+ /* Advance to the next 'b' span */
+ H5S_HYPER_ADVANCE_SPAN(recover_b, span_b, span_b->next);
+ } /* end while */
+ } /* end if */
+ else {
+ /* Free the span, if it's generated */
+ if(recover_b)
+ H5S__hyper_free_span(span_b);
+ } /* end else */
} /* end if */
+ else
+ /* Sanity check */
+ HDassert(span_a == NULL && span_b == NULL);
} /* end else */
} /* end else */
@@ -5422,7 +7903,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S__hyper_clip_spans() */
-
+
/*--------------------------------------------------------------------------
NAME
H5S__hyper_merge_spans_helper
@@ -5434,6 +7915,7 @@ done:
together
H5S_hyper_span_info_t *b_spans; IN: Second hyperslab spans to merge
together
+ unsigned ndims; IN: Number of dimensions of this span tree
RETURNS
Pointer to span tree containing the merged spans on success, NULL on failure
DESCRIPTION
@@ -5441,19 +7923,15 @@ done:
the merged set.
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
+ Handles merging span trees that overlap.
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
static H5S_hyper_span_info_t *
-H5S__hyper_merge_spans_helper(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_spans)
+H5S__hyper_merge_spans_helper(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_spans,
+ unsigned ndims)
{
H5S_hyper_span_info_t *merged_spans = NULL; /* Pointer to the merged span tree */
- H5S_hyper_span_info_t *tmp_spans; /* Pointer to temporary new span tree */
- H5S_hyper_span_t *tmp_span; /* Pointer to temporary new span */
- H5S_hyper_span_t *span_a; /* Pointer to current span 'a' working on */
- H5S_hyper_span_t *span_b; /* Pointer to current span 'b' working on */
- H5S_hyper_span_t *prev_span_merge; /* Pointer to previous merged span */
- hbool_t recover_a, recover_b; /* Flags to indicate when to recover temporary spans */
H5S_hyper_span_info_t *ret_value = NULL; /* Return value */
FUNC_ENTER_STATIC
@@ -5467,34 +7945,38 @@ H5S__hyper_merge_spans_helper(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_inf
merged_spans = NULL;
else {
/* Copy one of the span trees to return */
- if(NULL == (merged_spans = H5S__hyper_copy_span(a_spans)))
+ if(NULL == (merged_spans = H5S__hyper_copy_span(a_spans, ndims)))
HGOTO_ERROR(H5E_INTERNAL, H5E_CANTCOPY, NULL, "can't copy hyperslab span tree")
} /* end else */
} /* end if */
else {
+ H5S_hyper_span_t *span_a; /* Pointer to current span 'a' working on */
+ H5S_hyper_span_t *span_b; /* Pointer to current span 'b' working on */
+ hbool_t recover_a, recover_b; /* Flags to indicate when to recover temporary spans */
+
/* Get the pointers to the 'a' and 'b' span lists */
span_a = a_spans->head;
span_b = b_spans->head;
- /* Set the pointer to the previous spans */
- prev_span_merge = NULL;
-
/* No spans to recover yet */
recover_a = recover_b = FALSE;
/* Work through the list of spans in the new list */
while(span_a != NULL && span_b != NULL) {
+ H5S_hyper_span_info_t *tmp_spans; /* Pointer to temporary new span tree */
+ H5S_hyper_span_t *tmp_span; /* Pointer to temporary new span */
+
/* Check if the 'a' span is completely before 'b' span */
/* AAAAAAA */
/* <-----------------------------------> */
/* BBBBBBBBBB */
if(span_a->high < span_b->low) {
/* Merge/add span 'a' with/to the merged spans */
- if(H5S__hyper_append_span(&prev_span_merge,&merged_spans,span_a->low,span_a->high,span_a->down,NULL)==FAIL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
+ if(H5S__hyper_append_span(&merged_spans, ndims, span_a->low, span_a->high, span_a->down) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
/* Advance span 'a' */
- H5S__hyper_recover_span(&recover_a,&span_a,span_a->next);
+ H5S_HYPER_ADVANCE_SPAN(recover_a, span_a, span_a->next);
} /* end if */
/* Check if span 'a' overlaps only the lower bound */
/* of span 'b', up to the upper bound of span 'b' */
@@ -5505,20 +7987,20 @@ H5S__hyper_merge_spans_helper(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_inf
/* Check if span 'a' and span 'b' down spans are equal */
if(H5S__hyper_cmp_spans(span_a->down, span_b->down)) {
/* Merge/add copy of span 'a' with/to merged spans */
- if(H5S__hyper_append_span(&prev_span_merge,&merged_spans,span_a->low,span_a->high,span_a->down,NULL)==FAIL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
+ if(H5S__hyper_append_span(&merged_spans, ndims, span_a->low, span_a->high, span_a->down) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
} /* end if */
else {
/* Merge/add lower part of span 'a' with/to merged spans */
- if(H5S__hyper_append_span(&prev_span_merge,&merged_spans,span_a->low,span_b->low-1,span_a->down,NULL)==FAIL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
+ if(H5S__hyper_append_span(&merged_spans, ndims, span_a->low, span_b->low - 1, span_a->down) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
/* Get merged span tree for overlapped section */
- tmp_spans = H5S__hyper_merge_spans_helper(span_a->down,span_b->down);
+ tmp_spans = H5S__hyper_merge_spans_helper(span_a->down, span_b->down, ndims - 1);
/* Merge/add overlapped section to merged spans */
- if(H5S__hyper_append_span(&prev_span_merge,&merged_spans,span_b->low,span_a->high,tmp_spans,NULL)==FAIL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
+ if(H5S__hyper_append_span(&merged_spans, ndims, span_b->low, span_a->high, tmp_spans) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
/* Release merged span tree for overlapped section */
H5S__hyper_free_span_info(tmp_spans);
@@ -5529,20 +8011,20 @@ H5S__hyper_merge_spans_helper(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_inf
/* Copy upper part of span 'b' as new span 'b' */
/* Allocate new span node to append to list */
- if((tmp_span = H5S__hyper_new_span(span_a->high+1,span_b->high,span_b->down,span_b->next))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate hyperslab span")
+ if(NULL == (tmp_span = H5S__hyper_new_span(span_a->high + 1, span_b->high, span_b->down, span_b->next)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, NULL, "can't allocate hyperslab span")
/* Advance span 'a' */
- H5S__hyper_recover_span(&recover_a,&span_a,span_a->next);
+ H5S_HYPER_ADVANCE_SPAN(recover_a, span_a, span_a->next);
/* Set new span 'b' to tmp_span */
- H5S__hyper_recover_span(&recover_b,&span_b,tmp_span);
+ H5S_HYPER_ADVANCE_SPAN(recover_b, span_b, tmp_span);
recover_b = TRUE;
} /* end if */
else {
/* Advance both span 'a' & 'b' */
- H5S__hyper_recover_span(&recover_a,&span_a,span_a->next);
- H5S__hyper_recover_span(&recover_b,&span_b,span_b->next);
+ H5S_HYPER_ADVANCE_SPAN(recover_a, span_a, span_a->next);
+ H5S_HYPER_ADVANCE_SPAN(recover_b, span_b, span_b->next);
} /* end else */
} /* end if */
/* Check if span 'a' overlaps the lower & upper bound */
@@ -5554,20 +8036,20 @@ H5S__hyper_merge_spans_helper(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_inf
/* Check if span 'a' and span 'b' down spans are equal */
if(H5S__hyper_cmp_spans(span_a->down, span_b->down)) {
/* Merge/add copy of lower & middle parts of span 'a' to merged spans */
- if(H5S__hyper_append_span(&prev_span_merge,&merged_spans,span_a->low,span_b->high,span_a->down,NULL)==FAIL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
+ if(H5S__hyper_append_span(&merged_spans, ndims, span_a->low, span_b->high, span_a->down) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
} /* end if */
else {
/* Merge/add lower part of span 'a' to merged spans */
- if(H5S__hyper_append_span(&prev_span_merge,&merged_spans,span_a->low,span_b->low-1,span_a->down,NULL)==FAIL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
+ if(H5S__hyper_append_span(&merged_spans, ndims, span_a->low, span_b->low - 1, span_a->down) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
/* Get merged span tree for overlapped section */
- tmp_spans = H5S__hyper_merge_spans_helper(span_a->down,span_b->down);
+ tmp_spans = H5S__hyper_merge_spans_helper(span_a->down, span_b->down, ndims - 1);
/* Merge/add overlapped section to merged spans */
- if(H5S__hyper_append_span(&prev_span_merge,&merged_spans,span_b->low,span_b->high,tmp_spans,NULL)==FAIL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
+ if(H5S__hyper_append_span(&merged_spans, ndims, span_b->low, span_b->high, tmp_spans) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
/* Release merged span tree for overlapped section */
H5S__hyper_free_span_info(tmp_spans);
@@ -5580,11 +8062,11 @@ H5S__hyper_merge_spans_helper(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_inf
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, NULL, "can't allocate hyperslab span")
/* Set new span 'a' to tmp_span */
- H5S__hyper_recover_span(&recover_a,&span_a,tmp_span);
+ H5S_HYPER_ADVANCE_SPAN(recover_a, span_a, tmp_span);
recover_a = TRUE;
/* Advance span 'b' */
- H5S__hyper_recover_span(&recover_b,&span_b,span_b->next);
+ H5S_HYPER_ADVANCE_SPAN(recover_b, span_b, span_b->next);
} /* end if */
/* Check if span 'a' is entirely within span 'b' */
/* AAAAA */
@@ -5594,26 +8076,26 @@ H5S__hyper_merge_spans_helper(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_inf
/* Check if span 'a' and span 'b' down spans are equal */
if(H5S__hyper_cmp_spans(span_a->down, span_b->down)) {
/* Merge/add copy of lower & middle parts of span 'b' to merged spans */
- if(H5S__hyper_append_span(&prev_span_merge,&merged_spans,span_b->low,span_a->high,span_a->down,NULL)==FAIL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
+ if(H5S__hyper_append_span(&merged_spans, ndims, span_b->low, span_a->high, span_a->down) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
} /* end if */
else {
/* Check if there is a lower part of span 'b' */
if(span_a->low > span_b->low) {
/* Merge/add lower part of span 'b' to merged spans */
- if(H5S__hyper_append_span(&prev_span_merge,&merged_spans,span_b->low,span_a->low-1,span_b->down,NULL)==FAIL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
+ if(H5S__hyper_append_span(&merged_spans, ndims, span_b->low, span_a->low - 1, span_b->down) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
} /* end if */
else {
/* No lower part of span 'b' , keep going... */
} /* end else */
/* Get merged span tree for overlapped section */
- tmp_spans = H5S__hyper_merge_spans_helper(span_a->down,span_b->down);
+ tmp_spans = H5S__hyper_merge_spans_helper(span_a->down, span_b->down, ndims - 1);
/* Merge/add overlapped section to merged spans */
- if(H5S__hyper_append_span(&prev_span_merge,&merged_spans,span_a->low,span_a->high,tmp_spans,NULL)==FAIL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
+ if(H5S__hyper_append_span(&merged_spans, ndims, span_a->low, span_a->high, tmp_spans) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
/* Release merged span tree for overlapped section */
H5S__hyper_free_span_info(tmp_spans);
@@ -5628,16 +8110,16 @@ H5S__hyper_merge_spans_helper(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_inf
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, NULL, "can't allocate hyperslab span")
/* Advance span 'a' */
- H5S__hyper_recover_span(&recover_a,&span_a,span_a->next);
+ H5S_HYPER_ADVANCE_SPAN(recover_a, span_a, span_a->next);
/* Set new span 'b' to tmp_span */
- H5S__hyper_recover_span(&recover_b,&span_b,tmp_span);
+ H5S_HYPER_ADVANCE_SPAN(recover_b, span_b, tmp_span);
recover_b = TRUE;
} /* end if */
else {
/* Advance both spans */
- H5S__hyper_recover_span(&recover_a,&span_a,span_a->next);
- H5S__hyper_recover_span(&recover_b,&span_b,span_b->next);
+ H5S_HYPER_ADVANCE_SPAN(recover_a, span_a, span_a->next);
+ H5S_HYPER_ADVANCE_SPAN(recover_b, span_b, span_b->next);
} /* end else */
} /* end if */
/* Check if span 'a' overlaps only the upper bound */
@@ -5649,26 +8131,26 @@ H5S__hyper_merge_spans_helper(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_inf
/* Check if span 'a' and span 'b' down spans are equal */
if(H5S__hyper_cmp_spans(span_a->down, span_b->down)) {
/* Merge/add copy of span 'b' to merged spans if so */
- if(H5S__hyper_append_span(&prev_span_merge,&merged_spans,span_b->low,span_b->high,span_b->down,NULL)==FAIL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
+ if(H5S__hyper_append_span(&merged_spans, ndims, span_b->low, span_b->high, span_b->down) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
} /* end if */
else {
/* Check if there is a lower part of span 'b' */
if(span_a->low > span_b->low) {
/* Merge/add lower part of span 'b' to merged spans */
- if(H5S__hyper_append_span(&prev_span_merge,&merged_spans,span_b->low,span_a->low-1,span_b->down,NULL)==FAIL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
+ if(H5S__hyper_append_span(&merged_spans, ndims, span_b->low, span_a->low - 1, span_b->down) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
} /* end if */
else {
/* No lower part of span 'b' , keep going... */
} /* end else */
/* Get merged span tree for overlapped section */
- tmp_spans = H5S__hyper_merge_spans_helper(span_a->down,span_b->down);
+ tmp_spans = H5S__hyper_merge_spans_helper(span_a->down, span_b->down, ndims - 1);
/* Merge/add overlapped section to merged spans */
- if(H5S__hyper_append_span(&prev_span_merge,&merged_spans,span_a->low,span_b->high,tmp_spans,NULL)==FAIL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
+ if(H5S__hyper_append_span(&merged_spans, ndims, span_a->low, span_b->high, tmp_spans) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
/* Release merged span tree for overlapped section */
H5S__hyper_free_span_info(tmp_spans);
@@ -5681,11 +8163,11 @@ H5S__hyper_merge_spans_helper(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_inf
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, NULL, "can't allocate hyperslab span")
/* Set new span 'a' to tmp_span */
- H5S__hyper_recover_span(&recover_a,&span_a,tmp_span);
+ H5S_HYPER_ADVANCE_SPAN(recover_a, span_a, tmp_span);
recover_a = TRUE;
/* Advance span 'b' */
- H5S__hyper_recover_span(&recover_b,&span_b,span_b->next);
+ H5S_HYPER_ADVANCE_SPAN(recover_b, span_b, span_b->next);
} /* end if */
/* Span 'a' must be entirely above span 'b' */
/* AAAAA */
@@ -5693,11 +8175,11 @@ H5S__hyper_merge_spans_helper(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_inf
/* BBBBBBBBBB */
else {
/* Merge/add span 'b' with the merged spans */
- if(H5S__hyper_append_span(&prev_span_merge,&merged_spans,span_b->low,span_b->high,span_b->down,NULL)==FAIL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
+ if(H5S__hyper_append_span(&merged_spans, ndims, span_b->low, span_b->high, span_b->down) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
/* Advance span 'b' */
- H5S__hyper_recover_span(&recover_b,&span_b,span_b->next);
+ H5S_HYPER_ADVANCE_SPAN(recover_b, span_b, span_b->next);
} /* end else */
} /* end while */
@@ -5705,11 +8187,11 @@ H5S__hyper_merge_spans_helper(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_inf
if(span_a != NULL && span_b == NULL) {
while(span_a != NULL) {
/* Merge/add all 'a' spans into the merged spans */
- if(H5S__hyper_append_span(&prev_span_merge,&merged_spans,span_a->low,span_a->high,span_a->down,NULL)==FAIL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
+ if(H5S__hyper_append_span(&merged_spans, ndims, span_a->low, span_a->high, span_a->down) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
/* Advance to next 'a' span, until all processed */
- H5S__hyper_recover_span(&recover_a,&span_a,span_a->next);
+ H5S_HYPER_ADVANCE_SPAN(recover_a, span_a, span_a->next);
} /* end while */
} /* end if */
@@ -5717,11 +8199,11 @@ H5S__hyper_merge_spans_helper(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_inf
if(span_a == NULL && span_b != NULL) {
while(span_b != NULL) {
/* Merge/add all 'b' spans into the merged spans */
- if(H5S__hyper_append_span(&prev_span_merge,&merged_spans,span_b->low,span_b->high,span_b->down,NULL)==FAIL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
+ if(H5S__hyper_append_span(&merged_spans, ndims, span_b->low, span_b->high, span_b->down) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, NULL, "can't allocate hyperslab span")
/* Advance to next 'b' span, until all processed */
- H5S__hyper_recover_span(&recover_b,&span_b,span_b->next);
+ H5S_HYPER_ADVANCE_SPAN(recover_b, span_b, span_b->next);
} /* end while */
} /* end if */
} /* end else */
@@ -5731,13 +8213,13 @@ H5S__hyper_merge_spans_helper(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_inf
done:
if(ret_value == NULL)
- if(merged_spans && H5S__hyper_free_span_info(merged_spans) < 0)
- HDONE_ERROR(H5E_INTERNAL, H5E_CANTFREE, NULL, "failed to release merged hyperslab spans")
+ if(merged_spans)
+ H5S__hyper_free_span_info(merged_spans);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S__hyper_merge_spans_helper() */
-
+
/*--------------------------------------------------------------------------
NAME
H5S__hyper_merge_spans
@@ -5749,44 +8231,37 @@ done:
selection.
H5S_hyper_span_t *new_spans; IN: Span tree of new spans to add to
hyperslab selection
- hbool_t can_own; IN: Flag to indicate that it is OK to point
- directly to the new spans, instead of
- copying them.
RETURNS
non-negative on success, negative on failure
DESCRIPTION
- Add a set of hyperslab spans to an existing hyperslab selection. The
- new spans are required to be non-overlapping with the existing spans in
- the dataspace's current hyperslab selection.
+ Add a set of hyperslab spans to an existing hyperslab selection.
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S__hyper_merge_spans(H5S_t *space, H5S_hyper_span_info_t *new_spans, hbool_t can_own)
+H5S__hyper_merge_spans(H5S_t *space, H5S_hyper_span_info_t *new_spans)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ herr_t ret_value = SUCCEED; /* Return value */
- /* Check args */
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
HDassert(space);
HDassert(new_spans);
/* If this is the first span tree in the hyperslab selection, just use it */
if(space->select.sel_info.hslab->span_lst == NULL) {
- if(can_own)
- space->select.sel_info.hslab->span_lst = new_spans;
- else
- space->select.sel_info.hslab->span_lst = H5S__hyper_copy_span(new_spans);
+ space->select.sel_info.hslab->span_lst = new_spans;
+ space->select.sel_info.hslab->span_lst->count++;
} /* end if */
else {
H5S_hyper_span_info_t *merged_spans;
/* Get the merged spans */
- merged_spans = H5S__hyper_merge_spans_helper(space->select.sel_info.hslab->span_lst, new_spans);
-
- /* Sanity checking since we started with some spans, we should still have some after the merge */
- HDassert(merged_spans);
+ if(NULL == (merged_spans = H5S__hyper_merge_spans_helper(space->select.sel_info.hslab->span_lst, new_spans, space->extent.rank)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTMERGE, FAIL, "can't merge hyperslab spans")
/* Free the previous spans */
H5S__hyper_free_span_info(space->select.sel_info.hslab->span_lst);
@@ -5795,18 +8270,20 @@ H5S__hyper_merge_spans(H5S_t *space, H5S_hyper_span_info_t *new_spans, hbool_t c
space->select.sel_info.hslab->span_lst = merged_spans;
} /* end else */
- FUNC_LEAVE_NOAPI(SUCCEED)
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S__hyper_merge_spans() */
-
+
/*--------------------------------------------------------------------------
NAME
- H5S__hyper_spans_nelem
+ H5S__hyper_spans_nelem_helper
PURPOSE
Count the number of elements in a span tree
USAGE
- hsize_t H5S__hyper_spans_nelem(spans)
+ hsize_t H5S__hyper_spans_nelem_helper(spans, op_gen)
const H5S_hyper_span_info_t *spans; IN: Hyperslan span tree to count elements of
+ uint64_t op_gen; IN: Operation generation
RETURNS
Number of elements in span tree on success; negative on failure
DESCRIPTION
@@ -5817,34 +8294,145 @@ H5S__hyper_merge_spans(H5S_t *space, H5S_hyper_span_info_t *new_spans, hbool_t c
REVISION LOG
--------------------------------------------------------------------------*/
static hsize_t
-H5S__hyper_spans_nelem(const H5S_hyper_span_info_t *spans)
+H5S__hyper_spans_nelem_helper(H5S_hyper_span_info_t *spans, uint64_t op_gen)
{
hsize_t ret_value = 0; /* Return value */
FUNC_ENTER_STATIC_NOERR
- /* Count the number of elements in the span tree */
- if(spans != NULL) {
+ /* Sanity check */
+ HDassert(spans);
+
+ /* Check if the span tree was already counted */
+ if(spans->op_gen == op_gen)
+ /* Just return the # of elements in the already counted span tree */
+ ret_value = spans->u.nelmts;
+ else { /* Count the number of elements in the span tree */
const H5S_hyper_span_t *span; /* Hyperslab span */
span = spans->head;
- while(span != NULL) {
- /* If there are down spans, multiply the size of this span by the total down span elements */
- if(span->down != NULL)
- ret_value += span->nelem * H5S__hyper_spans_nelem(span->down);
- /* If there are no down spans, just count the elements in this span */
- else
- ret_value += span->nelem;
+ if(NULL == span->down) {
+ while(span != NULL) {
+ /* Compute # of elements covered */
+ ret_value += (span->high - span->low) + 1;
- /* Advance to next span */
- span = span->next;
- } /* end while */
+ /* Advance to next span */
+ span = span->next;
+ } /* end while */
+ } /* end if */
+ else {
+ while(span != NULL) {
+ hsize_t nelmts; /* # of elements covered by current span */
+
+ /* Compute # of elements covered */
+ nelmts = (span->high - span->low) + 1;
+
+ /* Multiply the size of this span by the total down span elements */
+ ret_value += nelmts * H5S__hyper_spans_nelem_helper(span->down, op_gen);
+
+ /* Advance to next span */
+ span = span->next;
+ } /* end while */
+ } /* end else */
+
+ /* Set the operation generation for this span tree, to avoid re-computing */
+ spans->op_gen = op_gen;
+
+ /* Hold a copy of the # of elements */
+ spans->u.nelmts = ret_value;
} /* end else */
FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S__hyper_spans_nelem_helper() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S__hyper_spans_nelem
+ PURPOSE
+ Count the number of elements in a span tree
+ USAGE
+ hsize_t H5S__hyper_spans_nelem(spans)
+ const H5S_hyper_span_info_t *spans; IN: Hyperslan span tree to count elements of
+ RETURNS
+ Number of elements in span tree on success; negative on failure
+ DESCRIPTION
+ Counts the number of elements described by the spans in a span tree.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static hsize_t
+H5S__hyper_spans_nelem(H5S_hyper_span_info_t *spans)
+{
+ uint64_t op_gen; /* Operation generation value */
+ hsize_t ret_value = 0; /* Return value */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Sanity check */
+ HDassert(spans);
+
+ /* Acquire an operation generation value for this operation */
+ op_gen = H5S__hyper_get_op_gen();
+
+ /* Count the number of elements in the span tree */
+ ret_value = H5S__hyper_spans_nelem_helper(spans, op_gen);
+
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S__hyper_spans_nelem() */
-
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S__hyper_add_disjoint_spans
+ PURPOSE
+ Add new hyperslab spans to existing hyperslab selection in the case the
+ new hyperslab spans don't overlap with the existing hyperslab selection
+ USAGE
+ herr_t H5S__hyper_add_disjoint_spans(space, new_spans)
+ H5S_t *space; IN: Dataspace to add new spans to hyperslab
+ selection.
+ H5S_hyper_span_t *new_spans; IN: Span tree of new spans to add to
+ hyperslab selection
+ RETURNS
+ Non-negative on success, negative on failure
+ DESCRIPTION
+ Add a set of hyperslab spans to an existing hyperslab selection. The
+ new spans are required not to overlap with the existing spans in the
+ dataspace's current hyperslab selection in terms of bound box.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static herr_t
+H5S__hyper_add_disjoint_spans(H5S_t *space, H5S_hyper_span_info_t *new_spans)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check args */
+ HDassert(space);
+ HDassert(new_spans);
+
+ /* Update the number of elements in the selection */
+ space->select.num_elem += H5S__hyper_spans_nelem(new_spans);
+
+ /* Add the new spans to the existing selection in the dataspace */
+ if(H5S__hyper_merge_spans(space, new_spans) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't merge hyperslabs")
+
+ /* Free the memory space for new spans */
+ H5S__hyper_free_span_info(new_spans);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S__hyper_add_disjoint_spans */
+
+
/*--------------------------------------------------------------------------
NAME
H5S__hyper_make_spans
@@ -5852,12 +8440,12 @@ H5S__hyper_spans_nelem(const H5S_hyper_span_info_t *spans)
Create a span tree
USAGE
H5S_hyper_span_t *H5S__hyper_make_spans(rank, start, stride, count, block)
- unsigned rank; IN: # of dimensions of the space
- const hsize_t *start; IN: Starting location of the hyperslabs
- const hsize_t *stride; IN: Stride from the beginning of one block to
+ unsigned rank; IN: # of dimensions of the space
+ const hsize_t *start; IN: Starting location of the hyperslabs
+ const hsize_t *stride; IN: Stride from the beginning of one block to
the next
- const hsize_t *count; IN: Number of blocks
- const hsize_t *block; IN: Size of hyperslab block
+ const hsize_t *count; IN: Number of blocks
+ const hsize_t *block; IN: Size of hyperslab block
RETURNS
Pointer to new span tree on success, NULL on failure
DESCRIPTION
@@ -5877,9 +8465,7 @@ H5S__hyper_make_spans(unsigned rank, const hsize_t *start, const hsize_t *stride
H5S_hyper_span_info_t *down = NULL; /* Pointer to spans in next dimension down */
H5S_hyper_span_t *last_span; /* Current position in hyperslab span list */
H5S_hyper_span_t *head = NULL; /* Head of new hyperslab span list */
- hsize_t stride_iter; /* Iterator over the stride values */
int i; /* Counters */
- unsigned u; /* Counters */
H5S_hyper_span_info_t *ret_value = NULL; /* Return value */
FUNC_ENTER_STATIC
@@ -5893,6 +8479,9 @@ H5S__hyper_make_spans(unsigned rank, const hsize_t *start, const hsize_t *stride
/* Start creating spans in fastest changing dimension */
for(i = (int)(rank - 1); i >= 0; i--) {
+ hsize_t curr_low, curr_high; /* Current low & high values */
+ hsize_t dim_stride; /* Current dim's stride */
+ unsigned u; /* Local index variable */
/* Sanity check */
if(0 == count[i])
@@ -5903,8 +8492,10 @@ H5S__hyper_make_spans(unsigned rank, const hsize_t *start, const hsize_t *stride
last_span = NULL;
/* Generate all the span segments for this dimension */
- for(u = 0, stride_iter = 0; u < count[i]; u++, stride_iter += stride[i])
- {
+ curr_low = start[i];
+ curr_high = start[i] + (block[i] - 1);
+ dim_stride = stride[i];
+ for(u = 0; u < count[i]; u++, curr_low += dim_stride, curr_high += dim_stride) {
H5S_hyper_span_t *span; /* New hyperslab span */
/* Allocate a span node */
@@ -5912,12 +8503,14 @@ H5S__hyper_make_spans(unsigned rank, const hsize_t *start, const hsize_t *stride
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, NULL, "can't allocate hyperslab span")
/* Set the span's basic information */
- span->low = start[i] + stride_iter;
- span->high = span->low + (block[i] - 1);
- span->nelem = block[i];
- span->pstride = stride[i];
+ span->low = curr_low;
+ span->high = curr_high;
span->next = NULL;
+ /* Set the information for the next dimension down's spans */
+ /* (Will be NULL for fastest changing dimension) */
+ span->down = down;
+
/* Append to the list of spans in this dimension */
if(head == NULL)
head = span;
@@ -5926,23 +8519,32 @@ H5S__hyper_make_spans(unsigned rank, const hsize_t *start, const hsize_t *stride
/* Move current pointer */
last_span = span;
-
- /* Set the information for the next dimension down's spans, if appropriate */
- if(down != NULL) {
- span->down = down;
- down->count++; /* Increment reference count for shared span */
- } /* end if */
- else
- span->down = NULL;
} /* end for */
+ /* Increment ref. count of shared span */
+ if(down != NULL)
+ down->count = (unsigned)count[i];
+
/* Allocate a span info node */
- if(NULL == (down = H5FL_CALLOC(H5S_hyper_span_info_t)))
+ if(NULL == (down = H5S__hyper_new_span_info(rank)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, NULL, "can't allocate hyperslab span")
/* Keep the pointer to the next dimension down's completed list */
down->head = head;
+ /* Keep the tail pointer to the next dimension down's completed list */
+ down->tail = last_span;
+
+ /* Set the low & high bounds for this dimension */
+ down->low_bounds[0] = down->head->low;
+ down->high_bounds[0] = down->tail->high;
+
+ /* Copy bounds from lower dimensions */
+ /* (head & tail pointers share lower dimensions, so using either is OK) */
+ if(head->down) {
+ H5MM_memcpy(&down->low_bounds[1], &head->down->low_bounds[0], sizeof(hsize_t) * ((rank - 1) - (unsigned)i));
+ H5MM_memcpy(&down->high_bounds[1], &head->down->high_bounds[0], sizeof(hsize_t) * ((rank - 1) - (unsigned)i));
+ } /* end if */
} /* end for */
/* Indicate that there is a pointer to this tree */
@@ -5963,7 +8565,7 @@ done:
do {
if(down) {
head = down->head;
- down = H5FL_FREE(H5S_hyper_span_info_t, down);
+ down = (H5S_hyper_span_info_t *)H5FL_ARR_FREE(hbounds_t, down);
} /* end if */
down = head->down;
@@ -5979,7 +8581,225 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S__hyper_make_spans() */
-
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S__hyper_update_diminfo
+ PURPOSE
+ Attempt to update optimized hyperslab information quickly. (It can be
+ recovered with regular selection). If this algorithm cannot determine
+ the optimized dimension info quickly, this function will simply mark it
+ as invalid and unknown if it can be built (H5S_DIMINFO_VALID_NO), so
+ H5S__hyper_rebuild can be run later to determine for sure.
+ USAGE
+ herr_t H5S__hyper_update_diminfo(space, op, new_hyper_diminfo)
+ H5S_t *space; IN: Dataspace to check
+ H5S_seloper_t op; IN: The operation being performed on the
+ selection
+ const H5S_hyper_dim_t new_hyper_diminfo; IN: The new selection that
+ is being combined with
+ the current
+ RETURNS
+ >=0 on success, <0 on failure
+ DESCRIPTION
+ Examine the span tree for a hyperslab selection and rebuild
+ the start/stride/count/block information for the selection, if possible.
+
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static herr_t
+H5S__hyper_update_diminfo(H5S_t *space, H5S_seloper_t op,
+ const H5S_hyper_dim_t *new_hyper_diminfo)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Check args */
+ HDassert(space);
+ HDassert(new_hyper_diminfo);
+
+ /* Check for conditions that prevent us from using the fast algorithm here */
+ /* (and instead require H5S__hyper_rebuild) */
+ if(!((op == H5S_SELECT_OR) || (op == H5S_SELECT_XOR))
+ || space->select.sel_info.hslab->diminfo_valid != H5S_DIMINFO_VALID_YES
+ || !space->select.sel_info.hslab->span_lst->head)
+ space->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_NO;
+ else {
+ H5S_hyper_dim_t tmp_diminfo[H5S_MAX_RANK]; /* Temporary dimension info */
+ hbool_t found_nonidentical_dim = FALSE;
+ unsigned curr_dim;
+
+ /* Copy current diminfo.opt values */
+ H5MM_memcpy(tmp_diminfo, space->select.sel_info.hslab->diminfo.opt, sizeof(tmp_diminfo));
+
+ /* Loop over dimensions */
+ for(curr_dim = 0; curr_dim < space->extent.rank; curr_dim++) {
+ /* Check for this being identical */
+ if((tmp_diminfo[curr_dim].start != new_hyper_diminfo[curr_dim].start)
+ || (tmp_diminfo[curr_dim].stride != new_hyper_diminfo[curr_dim].stride)
+ || (tmp_diminfo[curr_dim].count != new_hyper_diminfo[curr_dim].count)
+ || (tmp_diminfo[curr_dim].block != new_hyper_diminfo[curr_dim].block)) {
+ hsize_t high_start, high_count, high_block; /* The start, count & block values for the higher block */
+
+ /* Dimension is not identical */
+ /* Check if we already found a nonidentical dim - only one is
+ * allowed */
+ if(found_nonidentical_dim) {
+ space->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_NO;
+ break;
+ } /* end if */
+
+ /* Check that strides are the same, or count is 1 for one of the
+ * slabs */
+ if((tmp_diminfo[curr_dim].stride != new_hyper_diminfo[curr_dim].stride)
+ && (tmp_diminfo[curr_dim].count > 1)
+ && (new_hyper_diminfo[curr_dim].count > 1)) {
+ space->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_NO;
+ break;
+ } /* end if */
+
+ /* Patch tmp_diminfo.stride if its count is 1 */
+ if((tmp_diminfo[curr_dim].count == 1)
+ && (new_hyper_diminfo[curr_dim].count > 1))
+ tmp_diminfo[curr_dim].stride = new_hyper_diminfo[curr_dim].stride;
+
+ /* Determine lowest start, and set tmp_diminfo.start, count and
+ * block to use the lowest, and high_start, high_count and
+ * high_block to use the highest
+ */
+ if(tmp_diminfo[curr_dim].start < new_hyper_diminfo[curr_dim].start) {
+ high_start = new_hyper_diminfo[curr_dim].start;
+ high_count = new_hyper_diminfo[curr_dim].count;
+ high_block = new_hyper_diminfo[curr_dim].block;
+ } /* end if */
+ else {
+ high_start = tmp_diminfo[curr_dim].start;
+ tmp_diminfo[curr_dim].start = new_hyper_diminfo[curr_dim].start;
+ high_count = tmp_diminfo[curr_dim].count;
+ tmp_diminfo[curr_dim].count = new_hyper_diminfo[curr_dim].count;
+ high_block = tmp_diminfo[curr_dim].block;
+ tmp_diminfo[curr_dim].block = new_hyper_diminfo[curr_dim].block;
+ } /* end else */
+
+ /* If count is 1 for both slabs, take different actions */
+ if((tmp_diminfo[curr_dim].count == 1) && (high_count == 1)) {
+ /* Check for overlap */
+ if((tmp_diminfo[curr_dim].start + tmp_diminfo[curr_dim].block)
+ > high_start) {
+ /* Check operation type */
+ if(op == H5S_SELECT_OR)
+ /* Merge blocks */
+ tmp_diminfo[curr_dim].block = ((high_start + high_block)
+ >= (tmp_diminfo[curr_dim].start + tmp_diminfo[curr_dim].block))
+ ? (high_start + high_block - tmp_diminfo[curr_dim].start)
+ : tmp_diminfo[curr_dim].block;
+ else {
+ /* Block values must be the same */
+ if(tmp_diminfo[curr_dim].block != high_block) {
+ space->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_NO;
+ break;
+ } /* end if */
+
+ /* XOR - overlap creates 2 blocks */
+ tmp_diminfo[curr_dim].stride = high_block;
+ tmp_diminfo[curr_dim].count = 2;
+ tmp_diminfo[curr_dim].block = high_start - tmp_diminfo[curr_dim].start;
+ } /* end else */
+ } /* end if */
+ else if((tmp_diminfo[curr_dim].start + tmp_diminfo[curr_dim].block)
+ == high_start)
+ /* Blocks border, merge them */
+ tmp_diminfo[curr_dim].block += high_block;
+ else {
+ /* Distinct blocks */
+ /* Block values must be the same */
+ if(tmp_diminfo[curr_dim].block != high_block) {
+ space->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_NO;
+ break;
+ } /* end if */
+
+ /* Create strided selection */
+ tmp_diminfo[curr_dim].stride = high_start - tmp_diminfo[curr_dim].start;
+ tmp_diminfo[curr_dim].count = 2;
+ } /* end else */
+ } /* end if */
+ else {
+ /* Check if block values are the same */
+ if(tmp_diminfo[curr_dim].block != new_hyper_diminfo[curr_dim].block) {
+ space->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_NO;
+ break;
+ } /* end if */
+
+ /* Check phase of strides */
+ if((tmp_diminfo[curr_dim].start % tmp_diminfo[curr_dim].stride)
+ != (new_hyper_diminfo[curr_dim].start % tmp_diminfo[curr_dim].stride)) {
+ space->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_NO;
+ break;
+ } /* end if */
+
+ /* Check operation type */
+ if(op == H5S_SELECT_OR) {
+ /* Make sure the slabs border or overlap */
+ if(high_start > (tmp_diminfo[curr_dim].start
+ + (tmp_diminfo[curr_dim].count
+ * tmp_diminfo[curr_dim].stride))) {
+ space->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_NO;
+ break;
+ } /* end if */
+ } /* end if */
+ else
+ /* XOR: Make sure the slabs border */
+ if(high_start != (tmp_diminfo[curr_dim].start
+ + (tmp_diminfo[curr_dim].count
+ * tmp_diminfo[curr_dim].stride))) {
+ space->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_NO;
+ break;
+ } /* end if */
+
+ /* Set count for combined selection */
+ tmp_diminfo[curr_dim].count = ((high_start
+ - tmp_diminfo[curr_dim].start)
+ / tmp_diminfo[curr_dim].stride) + high_count;
+ } /* end else */
+
+ /* Indicate that we found a nonidentical dim */
+ found_nonidentical_dim = TRUE;
+ } /* end if */
+ } /* end for */
+
+ /* Check if we succeeded, if so, set the new diminfo values */
+ if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES)
+ for(curr_dim = 0; curr_dim < space->extent.rank; curr_dim++) {
+ hsize_t tmp_high_bound;
+
+ /* Set the new diminfo values */
+ space->select.sel_info.hslab->diminfo.app[curr_dim].start = space->select.sel_info.hslab->diminfo.opt[curr_dim].start = tmp_diminfo[curr_dim].start;
+ HDassert(tmp_diminfo[curr_dim].stride > 0);
+ space->select.sel_info.hslab->diminfo.app[curr_dim].stride = space->select.sel_info.hslab->diminfo.opt[curr_dim].stride = tmp_diminfo[curr_dim].stride;
+ HDassert(tmp_diminfo[curr_dim].count > 0);
+ space->select.sel_info.hslab->diminfo.app[curr_dim].count = space->select.sel_info.hslab->diminfo.opt[curr_dim].count = tmp_diminfo[curr_dim].count;
+ HDassert(tmp_diminfo[curr_dim].block > 0);
+ space->select.sel_info.hslab->diminfo.app[curr_dim].block = space->select.sel_info.hslab->diminfo.opt[curr_dim].block = tmp_diminfo[curr_dim].block;
+
+ /* Check for updating the low & high bounds */
+ if(tmp_diminfo[curr_dim].start < space->select.sel_info.hslab->diminfo.low_bounds[curr_dim])
+ space->select.sel_info.hslab->diminfo.low_bounds[curr_dim] = tmp_diminfo[curr_dim].start;
+ tmp_high_bound = tmp_diminfo[curr_dim].start +
+ (tmp_diminfo[curr_dim].block - 1) +
+ (tmp_diminfo[curr_dim].stride * (tmp_diminfo[curr_dim].count - 1));
+ if(tmp_high_bound > space->select.sel_info.hslab->diminfo.low_bounds[curr_dim])
+ space->select.sel_info.hslab->diminfo.high_bounds[curr_dim] = tmp_high_bound;
+ } /* end for */
+ } /* end else */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S__hyper_update_diminfo() */
+
+
/*--------------------------------------------------------------------------
NAME
H5S__hyper_rebuild_helper
@@ -5991,6 +8811,7 @@ done:
const H5S_hyper_span_t *span; IN: Portion of span tree to check
H5S_hyper_dim_t span_slab[]; OUT: Rebuilt section of hyperslab description
unsigned rank; IN: Current dimension to work on
+ uint64_t op_gen; IN: Operation generation
RETURNS
TRUE/FALSE for hyperslab selection rebuilt
DESCRIPTION
@@ -6005,114 +8826,91 @@ done:
KY, 2005/9/22
--------------------------------------------------------------------------*/
static hbool_t
-H5S__hyper_rebuild_helper(const H5S_hyper_span_t *span, H5S_hyper_dim_t span_slab_info[],
- unsigned rank)
+H5S__hyper_rebuild_helper(const H5S_hyper_span_info_t *spans, H5S_hyper_dim_t span_slab_info[])
{
+ const H5S_hyper_span_t *span; /* Hyperslab span */
+ const H5S_hyper_span_t *prev_span; /* Previous span in list */
+ hsize_t start; /* Starting element for this dimension */
+ hsize_t stride; /* Stride for this dimension */
+ hsize_t block; /* Block size for this dimension */
+ hsize_t prev_low; /* Low bound for previous span */
+ size_t spancount; /* Number of spans encountered in this dimension */
hbool_t ret_value = TRUE; /* Return value */
FUNC_ENTER_STATIC_NOERR
- if(span) {
- const H5S_hyper_span_t *prev_span = NULL; /* Previous span in list */
- H5S_hyper_dim_t canon_down_span_slab_info[H5S_MAX_RANK];
- hsize_t curr_stride;
- hsize_t curr_block;
- hsize_t curr_start;
- hsize_t curr_low;
- size_t outcount; /* Number of spans encountered in this dimension */
-
- /* Initialization */
- curr_stride = 1;
- curr_low = 0;
- outcount = 0;
-
- /* Get "canonical" down span information */
- if(span->down) {
- HDassert(span->down->head);
-
- /* Go to the next down span and check whether the selection can be rebuilt */
- if(!H5S__hyper_rebuild_helper(span->down->head, span_slab_info, rank - 1))
- HGOTO_DONE(FALSE)
-
- HDmemcpy(canon_down_span_slab_info, span_slab_info, sizeof(H5S_hyper_dim_t) * rank);
- } /* end if */
+ /* Sanity check */
+ HDassert(spans);
- /* Assign the initial starting point & block size */
- curr_start = span->low;
- curr_block = (span->high - span->low) + 1;
+ /* Initialization */
+ span = spans->head;
+ stride = 1;
+ prev_low = 0;
+ spancount = 0;
- /* Loop the spans */
- while(span) {
- if(outcount > 0) {
- hsize_t next_stride; /* Stride from previous span */
- hsize_t next_block; /* Block size of current span */
+ /* Get "canonical" down span information */
+ if(span->down)
+ /* Go to the next down span and check whether the selection can be rebuilt */
+ if(!H5S__hyper_rebuild_helper(span->down, &span_slab_info[1]))
+ HGOTO_DONE(FALSE)
- /* Check that down spans match current slab info */
- /* (Can skip check if previous span's down pointer is same as current one) */
- if(span->down && (NULL == prev_span || prev_span->down != span->down)) {
- H5S_hyper_dim_t *curr_down_span_slab_info;
- unsigned u; /* Local index variable */
+ /* Assign the initial starting point & block size for this dimension */
+ start = span->low;
+ block = (span->high - span->low) + 1;
- HDassert(span->down->head);
+ /* Loop the spans */
+ prev_span = NULL;
+ while(span) {
+ if(spancount > 0) {
+ hsize_t curr_stride; /* Current stride from previous span */
+ hsize_t curr_block; /* Block size of current span */
- /* Go to the next down span and check whether the selection can be rebuilt.*/
- if(!H5S__hyper_rebuild_helper(span->down->head, span_slab_info, rank - 1))
- HGOTO_DONE(FALSE)
+ /* Sanity check */
+ HDassert(prev_span);
- /* Compare the slab information of the adjacent spans in the down span tree.
- We have to compare all the sub-tree slab information with the canon_down_span_slab_info.*/
- for(u = 0; u < rank - 1; u++) {
- curr_down_span_slab_info = &span_slab_info[u];
-
- if(curr_down_span_slab_info->count > 0 && canon_down_span_slab_info[u].count > 0) {
- if(curr_down_span_slab_info->start != canon_down_span_slab_info[u].start
- || curr_down_span_slab_info->stride != canon_down_span_slab_info[u].stride
- || curr_down_span_slab_info->block != canon_down_span_slab_info[u].block
- || curr_down_span_slab_info->count != canon_down_span_slab_info[u].count)
- HGOTO_DONE(FALSE)
- } /* end if */
- else if(!((curr_down_span_slab_info->count == 0) && (canon_down_span_slab_info[u].count == 0)))
- HGOTO_DONE(FALSE)
- } /* end for */
- } /* end if */
+ /* Check that down spans match current slab info */
+ /* (Can skip check if previous span's down pointer is same as current one) */
+ if(span->down && prev_span->down != span->down)
+ if(!H5S__hyper_cmp_spans(span->down, prev_span->down))
+ HGOTO_DONE(FALSE)
- /* Obtain values for stride and block */
- next_stride = span->low - curr_low;
- next_block = (span->high - span->low) + 1;
+ /* Obtain values for stride and block */
+ curr_stride = span->low - prev_low;
+ curr_block = (span->high - span->low) + 1;
- /* Compare stride and block in this span, to compare stride,
- * three spans are needed. Account for the first two spans.
- */
- if(next_block != curr_block)
- HGOTO_DONE(FALSE)
- if(outcount > 1 && curr_stride != next_stride)
+ /* Compare stride and block for this span. To compare stride,
+ * three spans are needed. Account for the first two spans.
+ */
+ if(curr_block != block)
+ HGOTO_DONE(FALSE)
+ if(spancount > 1) {
+ if(stride != curr_stride)
HGOTO_DONE(FALSE)
-
- /* Keep the isolated stride to be 1 */
- curr_stride = next_stride;
} /* end if */
+ else
+ stride = curr_stride;
+ } /* end if */
- /* Keep current starting point */
- curr_low = span->low;
+ /* Keep current starting point */
+ prev_low = span->low;
- /* Advance to next span */
- prev_span = span;
- span = span->next;
- outcount++;
- } /* end while */
+ /* Advance to next span */
+ prev_span = span;
+ span = span->next;
+ spancount++;
+ } /* end while */
- /* Save the span information. */
- span_slab_info[rank - 1].start = curr_start;
- span_slab_info[rank - 1].count = outcount;
- span_slab_info[rank - 1].block = curr_block;
- span_slab_info[rank - 1].stride = curr_stride;
- } /* end if */
+ /* Save the span information. */
+ span_slab_info[0].start = start;
+ span_slab_info[0].count = spancount;
+ span_slab_info[0].block = block;
+ span_slab_info[0].stride = stride;
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S__hyper_rebuild_helper() */
-
+
/*--------------------------------------------------------------------------
NAME
H5S__hyper_rebuild
@@ -6120,68 +8918,49 @@ done:
Rebuild optimized hyperslab information if possible.
(It can be recovered with regular selection)
USAGE
- hbool_t H5S__hyper_rebuild(space)
- const H5S_t *space; IN: Dataspace to check
+ void H5S__hyper_rebuild(space)
+ H5S_t *space; IN: Dataspace to check
RETURNS
- TRUE/FALSE for hyperslab selection rebuilt
+ None
DESCRIPTION
- Examine the span tree for a hyperslab selection and rebuild
- the start/stride/count/block information for the selection, if possible.
+ Examine the span tree for a hyperslab selection and rebuild a regular
+ start/stride/count/block hyperslab selection, if possible.
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
To be able to recover the optimized information, the span tree must conform
to span tree able to be generated from a single H5S_SELECT_SET operation.
EXAMPLES
REVISION LOG
- This routine is the optimization of the old version. The previous version
- can only detect a singluar selection. This version is general enough to
- detect any regular selection.
- KY, 2005/9/22
--------------------------------------------------------------------------*/
-static hbool_t
+void
H5S__hyper_rebuild(H5S_t *space)
{
- H5S_hyper_dim_t top_span_slab_info[H5O_LAYOUT_NDIMS];
- unsigned rank, curr_dim;
- hbool_t ret_value = TRUE; /* Return value */
+ H5S_hyper_dim_t rebuilt_slab_info[H5S_MAX_RANK];
- FUNC_ENTER_STATIC_NOERR
+ FUNC_ENTER_PACKAGE_NOERR
/* Check args */
HDassert(space);
HDassert(space->select.sel_info.hslab->span_lst);
- /* Check the rank of space */
- rank = space->extent.rank;
-
- /* Check whether the slab can be rebuilt. Only regular selection can be rebuilt. If yes, fill in correct values.*/
- if(!H5S__hyper_rebuild_helper(space->select.sel_info.hslab->span_lst->head, top_span_slab_info, rank)) {
- HGOTO_DONE(FALSE)
- } /* end if */
+ /* Check whether the slab can be rebuilt */
+ /* (Only regular selection can be rebuilt. If yes, fill in correct values) */
+ if(FALSE == H5S__hyper_rebuild_helper(space->select.sel_info.hslab->span_lst, rebuilt_slab_info))
+ space->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_IMPOSSIBLE;
else {
- H5S_hyper_dim_t *diminfo;
- H5S_hyper_dim_t *app_diminfo;
-
- diminfo = space->select.sel_info.hslab->opt_diminfo;
- app_diminfo = space->select.sel_info.hslab->app_diminfo;
-
- for(curr_dim = 0; curr_dim < rank; curr_dim++) {
+ /* Set the dimension info & bounds for the dataspace, from the rebuilt info */
+ H5MM_memcpy(space->select.sel_info.hslab->diminfo.app, rebuilt_slab_info, sizeof(rebuilt_slab_info));
+ H5MM_memcpy(space->select.sel_info.hslab->diminfo.opt, rebuilt_slab_info, sizeof(rebuilt_slab_info));
+ H5MM_memcpy(space->select.sel_info.hslab->diminfo.low_bounds, space->select.sel_info.hslab->span_lst->low_bounds, sizeof(hsize_t) * space->extent.rank);
+ H5MM_memcpy(space->select.sel_info.hslab->diminfo.high_bounds, space->select.sel_info.hslab->span_lst->high_bounds, sizeof(hsize_t) * space->extent.rank);
- app_diminfo[(rank - curr_dim) - 1].start = diminfo[(rank - curr_dim) - 1].start = top_span_slab_info[curr_dim].start;
- app_diminfo[(rank - curr_dim) - 1].stride = diminfo[(rank - curr_dim) - 1].stride = top_span_slab_info[curr_dim].stride;
- app_diminfo[(rank - curr_dim) - 1].count = diminfo[(rank - curr_dim) - 1].count = top_span_slab_info[curr_dim].count;
- app_diminfo[(rank - curr_dim) - 1].block = diminfo[(rank - curr_dim) - 1].block = top_span_slab_info[curr_dim].block;
-
- } /* end for */
-
- space->select.sel_info.hslab->diminfo_valid = TRUE;
+ space->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_YES;
} /* end else */
-done:
- FUNC_LEAVE_NOAPI(ret_value)
+ FUNC_LEAVE_NOAPI_VOID
} /* end H5S__hyper_rebuild() */
-
+
/*--------------------------------------------------------------------------
NAME
H5S__hyper_generate_spans
@@ -6203,12 +8982,12 @@ done:
static herr_t
H5S__hyper_generate_spans(H5S_t *space)
{
- hsize_t tmp_start[H5O_LAYOUT_NDIMS]; /* Temporary start information */
- hsize_t tmp_stride[H5O_LAYOUT_NDIMS]; /* Temporary stride information */
- hsize_t tmp_count[H5O_LAYOUT_NDIMS]; /* Temporary count information */
- hsize_t tmp_block[H5O_LAYOUT_NDIMS]; /* Temporary block information */
- unsigned u; /* Local index variable */
- herr_t ret_value = SUCCEED; /* Return value */
+ hsize_t tmp_start[H5S_MAX_RANK]; /* Temporary start information */
+ hsize_t tmp_stride[H5S_MAX_RANK]; /* Temporary stride information */
+ hsize_t tmp_count[H5S_MAX_RANK]; /* Temporary count information */
+ hsize_t tmp_block[H5S_MAX_RANK]; /* Temporary block information */
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC
@@ -6221,15 +9000,15 @@ H5S__hyper_generate_spans(H5S_t *space)
/* These should be able to be converted to assertions once everything
* that calls this function checks for unlimited selections first
* (especially the new hyperslab API) -NAF */
- if(space->select.sel_info.hslab->opt_diminfo[u].count == H5S_UNLIMITED)
+ if(space->select.sel_info.hslab->diminfo.opt[u].count == H5S_UNLIMITED)
HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "can't generate spans with unlimited count")
- if(space->select.sel_info.hslab->opt_diminfo[u].block == H5S_UNLIMITED)
+ if(space->select.sel_info.hslab->diminfo.opt[u].block == H5S_UNLIMITED)
HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "can't generate spans with unlimited block")
- tmp_start[u]=space->select.sel_info.hslab->opt_diminfo[u].start;
- tmp_stride[u]=space->select.sel_info.hslab->opt_diminfo[u].stride;
- tmp_count[u]=space->select.sel_info.hslab->opt_diminfo[u].count;
- tmp_block[u]=space->select.sel_info.hslab->opt_diminfo[u].block;
+ tmp_start[u] = space->select.sel_info.hslab->diminfo.opt[u].start;
+ tmp_stride[u] = space->select.sel_info.hslab->diminfo.opt[u].stride;
+ tmp_count[u] = space->select.sel_info.hslab->diminfo.opt[u].count;
+ tmp_block[u] = space->select.sel_info.hslab->diminfo.opt[u].block;
} /* end for */
/* Build the hyperslab information also */
@@ -6240,33 +9019,404 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S__hyper_generate_spans() */
-#ifndef NEW_HYPERSLAB_API
-
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S__check_spans_overlap
+ PURPOSE
+ Check if two selections' bounds overlap.
+ USAGE
+ hbool_t H5S__check_spans_overlap(spans1, spans2)
+ const H5S_hyper_span_info_t *spans1; IN: Second span list
+ const H5S_hyper_span_info_t *spans2; IN: Second span list
+ RETURNS
+ TRUE for overlap, FALSE for no overlap
+ PROGRAMMER
+ Quincey Koziol - January 24, 2019
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static H5_ATTR_PURE hbool_t
+H5S__check_spans_overlap(const H5S_hyper_span_info_t *spans1,
+ const H5S_hyper_span_info_t *spans2)
+{
+ hbool_t ret_value = FALSE; /* Return value */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Sanity checks */
+ HDassert(spans1);
+ HDassert(spans2);
+
+ /* Use low & high bounds to try to avoid spinning through the span lists */
+ if(H5S_RANGE_OVERLAP(spans1->low_bounds[0], spans1->high_bounds[0],
+ spans2->low_bounds[0], spans2->high_bounds[0])) {
+ H5S_hyper_span_t *span1, *span2; /* Hyperslab spans */
+
+ /* Walk over spans, comparing them for overlap */
+ span1 = spans1->head;
+ span2 = spans2->head;
+ while(span1 && span2) {
+ /* Check current two spans for overlap */
+ if(H5S_RANGE_OVERLAP(span1->low, span1->high, span2->low, span2->high)) {
+ /* Check for spans in lowest dimension already */
+ if(span1->down) {
+ /* Sanity check */
+ HDassert(span2->down);
+
+ /* Check lower dimensions for overlap */
+ if(H5S__check_spans_overlap(span1->down, span2->down))
+ HGOTO_DONE(TRUE);
+ } /* end if */
+ else
+ HGOTO_DONE(TRUE);
+ } /* end if */
+
+ /* Advance one of the spans */
+ if(span1->high <= span2->high) {
+ /* Advance span1, unless it would be off the list and span2 has more nodes */
+ if(NULL == span1->next && NULL != span2->next)
+ span2 = span2->next;
+ else
+ span1 = span1->next;
+ } /* end if */
+ else {
+ /* Advance span2, unless it would be off the list and span1 has more nodes */
+ if(NULL == span2->next && NULL != span1->next)
+ span1 = span1->next;
+ else
+ span2 = span2->next;
+ } /* end else */
+ } /* end while */
+
+ /* Make certain we've exhausted our comparisons */
+ HDassert((NULL == span1 && (NULL != span2 && NULL == span2->next)) ||
+ ((NULL != span1 && NULL == span1->next) && NULL == span2));
+ } /* end of */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S__check_spans_overlap() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S__fill_in_new_space
+ PURPOSE
+ Combine two span lists, one from an existing dataspace and the
+ other from input arguments, into a new selection depending on the
+ selection operator. The new selection is put into a resulting dataspace
+ which could be allocated inside the function.
+ USAGE
+ herr_t H5S__fill_in_new_space(space1, op, space2_span_lst, can_own_span2,
+ span2_owned, result)
+ H5S_t *space1; IN: Dataspace containing the first span list
+ H5S_seloper_t op; IN: Selection operation
+ H5S_hyper_span_info_t *space2_span_lst; IN: Second span list
+ hbool_t can_own_span2; IN: Indicates whether the 2nd span list could be
+ owned by the result. If not, the 2nd span list
+ has to be copied.
+ hbool_t *span2_owned; OUT: Indicates if the 2nd span list is actually owned
+ H5S_t **result; OUT: The dataspace containing the the new selection. It
+ could be same with the 1st dataspace.
+ RETURNS
+ Non-negative on success, negative on failure
+ PROGRAMMER
+ Chao Mei July 8, 2011
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static herr_t
+H5S__fill_in_new_space(H5S_t *space1, H5S_seloper_t op,
+ H5S_hyper_span_info_t *space2_span_lst, hbool_t can_own_span2,
+ hbool_t *span2_owned, hbool_t *updated_spans, H5S_t **result)
+{
+ H5S_hyper_span_info_t *a_not_b = NULL; /* Span tree for hyperslab spans in old span tree and not in new span tree */
+ H5S_hyper_span_info_t *a_and_b = NULL; /* Span tree for hyperslab spans in both old and new span trees */
+ H5S_hyper_span_info_t *b_not_a = NULL; /* Span tree for hyperslab spans in new span tree and not in old span tree */
+ hbool_t overlapped = FALSE; /* Whether selections overlap */
+ hbool_t is_result_new = FALSE;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ HDassert(space1);
+ HDassert(space2_span_lst);
+ HDassert(op >= H5S_SELECT_OR && op <= H5S_SELECT_NOTA);
+ /* The result is either a to-be-created space or an empty one */
+ HDassert(*result == NULL || *result == space1);
+ HDassert(space1->select.sel_info.hslab->span_lst);
+ HDassert(span2_owned);
+
+ /* Reset flags to return */
+ *span2_owned = FALSE;
+ *updated_spans = FALSE;
+
+ /* The result shares the same info from space1 */
+ if(*result == NULL) {
+ if(NULL == ((*result) = H5S_copy(space1, TRUE, TRUE)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to copy dataspace")
+ space1->select.sel_info.hslab->span_lst->count--;
+ (*result)->select.sel_info.hslab->span_lst = NULL;
+ is_result_new = TRUE;
+ } /* end if */
+
+ /* Check both spaces to see if they overlap */
+ overlapped = H5S__check_spans_overlap(space1->select.sel_info.hslab->span_lst, space2_span_lst);
+
+ if(!overlapped) {
+ switch(op) {
+ case H5S_SELECT_OR:
+ case H5S_SELECT_XOR:
+ /* Add the new disjoint spans to the space */
+ /* Copy of space1's spans to *result, and another copy of space2's spans */
+ if(is_result_new)
+ (*result)->select.sel_info.hslab->span_lst = H5S__hyper_copy_span(space1->select.sel_info.hslab->span_lst, space1->extent.rank);
+ if(!can_own_span2) {
+ b_not_a = H5S__hyper_copy_span(space2_span_lst, space1->extent.rank);
+ if(H5S__hyper_add_disjoint_spans(*result, b_not_a) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't append hyperslabs")
+
+ /* The new_spans are now owned by 'space', so they should not be released */
+ b_not_a = NULL;
+ } /* end if */
+ else {
+ if(H5S__hyper_add_disjoint_spans(*result, space2_span_lst) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't append hyperslabs")
+ *span2_owned = TRUE;
+ } /* end else */
+
+ /* Indicate that the spans changed */
+ *updated_spans = TRUE;
+ break;
+
+ case H5S_SELECT_AND:
+ /* Convert *result to "none" selection */
+ if(H5S_select_none(*result) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't convert selection")
+ HGOTO_DONE(SUCCEED);
+
+ case H5S_SELECT_NOTB:
+ /* Copy space1's spans to *result */
+ if(is_result_new)
+ (*result)->select.sel_info.hslab->span_lst = H5S__hyper_copy_span(space1->select.sel_info.hslab->span_lst, space1->extent.rank);
+
+ /* Indicate that the spans changed */
+ *updated_spans = TRUE;
+ break;
+
+ case H5S_SELECT_NOTA:
+ if(!is_result_new) {
+ HDassert(space1 == *result);
+
+ /* Free the current selection */
+ H5S__hyper_free_span_info(space1->select.sel_info.hslab->span_lst);
+ space1->select.sel_info.hslab->span_lst = NULL;
+ } /* end if */
+
+ /* Copy space2's spans to *result */
+ if(!can_own_span2)
+ (*result)->select.sel_info.hslab->span_lst = H5S__hyper_copy_span(space2_span_lst, space1->extent.rank);
+ else {
+ (*result)->select.sel_info.hslab->span_lst = space2_span_lst;
+ *span2_owned = TRUE;
+ } /* end else */
+
+ /* Reset the number of items in selection */
+ (*result)->select.num_elem = H5S__hyper_spans_nelem(space2_span_lst);
+
+ /* Indicate that the spans changed */
+ *updated_spans = TRUE;
+ break;
+
+ case H5S_SELECT_NOOP:
+ case H5S_SELECT_SET:
+ case H5S_SELECT_APPEND:
+ case H5S_SELECT_PREPEND:
+ case H5S_SELECT_INVALID:
+ default:
+ HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation")
+ } /* end switch */
+ } /* end if */
+ else {
+ unsigned selector = 0; /* Select which clipping spans to generate */
+
+ /* Generate mask for clip operation depending on the op */
+ switch(op) {
+ case H5S_SELECT_OR: /* a + b_not_a */
+ selector = H5S_HYPER_COMPUTE_B_NOT_A;
+ break;
+
+ case H5S_SELECT_XOR: /* a_not_b + b_not_a */
+ selector = H5S_HYPER_COMPUTE_A_NOT_B | H5S_HYPER_COMPUTE_B_NOT_A;
+ break;
+
+ case H5S_SELECT_AND: /* a_and_b */
+ selector = H5S_HYPER_COMPUTE_A_AND_B;
+ break;
+
+ case H5S_SELECT_NOTB: /* a_not_b */
+ selector = H5S_HYPER_COMPUTE_A_NOT_B;
+ break;
+
+ case H5S_SELECT_NOTA: /* b_not_a */
+ selector = H5S_HYPER_COMPUTE_B_NOT_A;
+ break;
+
+ case H5S_SELECT_NOOP:
+ case H5S_SELECT_SET:
+ case H5S_SELECT_APPEND:
+ case H5S_SELECT_PREPEND:
+ case H5S_SELECT_INVALID:
+ default:
+ HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation")
+ } /* end switch */
+
+ /* Generate lists of spans which overlap and don't overlap */
+ if(H5S__hyper_clip_spans(space1->select.sel_info.hslab->span_lst,
+ space2_span_lst, selector, space1->extent.rank,
+ &a_not_b, &a_and_b, &b_not_a) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL, "can't clip hyperslab information")
+ switch(op) {
+ case H5S_SELECT_OR:
+ if(is_result_new)
+ (*result)->select.sel_info.hslab->span_lst = H5S__hyper_copy_span(space1->select.sel_info.hslab->span_lst, space1->extent.rank);
+ break;
+
+ case H5S_SELECT_AND:
+ case H5S_SELECT_XOR:
+ case H5S_SELECT_NOTB:
+ case H5S_SELECT_NOTA:
+ if(!is_result_new) {
+ HDassert(space1 == *result);
+
+ /* Free the current selection */
+ H5S__hyper_free_span_info(space1->select.sel_info.hslab->span_lst);
+ space1->select.sel_info.hslab->span_lst = NULL;
+ } /* end if */
+
+ /* Reset the number of items in selection */
+ /* (Will be set below) */
+ (*result)->select.num_elem = 0;
+ break;
+
+ case H5S_SELECT_NOOP:
+ case H5S_SELECT_SET:
+ case H5S_SELECT_APPEND:
+ case H5S_SELECT_PREPEND:
+ case H5S_SELECT_INVALID:
+ default:
+ HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation")
+ } /* end switch */
+
+ /* Check if there are any non-overlapped selections */
+ if(a_not_b) {
+ /* Other than OR, the span_lst is set to NULL. And in OR,
+ * a_not_b is not needed
+ */
+ HDassert(NULL == (*result)->select.sel_info.hslab->span_lst);
+
+ /* The results dataspace takes ownership of the spans */
+ /* (Since it must be NULL) */
+ (*result)->select.sel_info.hslab->span_lst = a_not_b;
+
+ /* Update the number of elements in current selection */
+ (*result)->select.num_elem = H5S__hyper_spans_nelem(a_not_b);
+
+ /* Indicate that the spans were updated */
+ *updated_spans = TRUE;
+
+ /* Indicate that the a_not_b spans are owned */
+ a_not_b = NULL;
+ } /* end if */
+
+ if(a_and_b) {
+ /**
+ * 1. Other than OR, the span_lst is set to NULL. And in OR,
+ * a_and_b is not needed
+ * 2. a_not_b will never be computed together with a_and_b
+ * because merging these two equals to a.
+ */
+ HDassert(NULL == (*result)->select.sel_info.hslab->span_lst);
+
+ /* The results dataspace takes ownership of the spans */
+ /* (Since it must be NULL) */
+ (*result)->select.sel_info.hslab->span_lst = a_and_b;
+
+ /* Update the number of elements in current selection */
+ (*result)->select.num_elem = H5S__hyper_spans_nelem(a_and_b);
+
+ /* Indicate that the spans were updated */
+ *updated_spans = TRUE;
+
+ /* Indicate that the a_and_b spans are owned */
+ a_and_b = NULL;
+ } /* end if */
+
+ if(b_not_a) {
+ /* Merge the b_not_a spans into the result dataspace */
+ if(H5S__hyper_merge_spans(*result, b_not_a) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert hyperslabs")
+
+ /* Update the number of elements in current selection */
+ (*result)->select.num_elem += H5S__hyper_spans_nelem(b_not_a);
+
+ /* Indicate that the spans were updated */
+ *updated_spans = TRUE;
+ } /* end if */
+ } /* end else for the case the new span overlaps with the old (i.e. space) */
+
+ /* Check if the spans weren't updated, and reset selection if so */
+ if(!*updated_spans) {
+ /* If updated_spans remains FALSE as in this branch, it means the
+ * result has been cleared in XOR / AND / NOTB / NOTA cases, and the
+ * result is a copy of the dataspace in the OR case.
+ *
+ * If two dataspaces have generated any of the three clipped
+ * span trees (i.e. a_not_b, a_and_b, and b_not_a), the
+ * updated_spans must be TRUE.
+ */
+ if(H5S_SELECT_OR != op) {
+ /* Convert *result to "none" selection */
+ if(H5S_select_none(*result) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't convert selection")
+ } /* end else */
+ } /* end if */
+
+done:
+ /* Free resources */
+ if(a_not_b)
+ H5S__hyper_free_span_info(a_not_b);
+ if(a_and_b)
+ H5S__hyper_free_span_info(a_and_b);
+ if(b_not_a)
+ H5S__hyper_free_span_info(b_not_a);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S__fill_in_new_space() */
+
+
/*-------------------------------------------------------------------------
- * Function: H5S__generate_hyperlab
+ * Function: H5S__generate_hyperlab
*
- * Purpose: Generate hyperslab information from H5S_select_hyperslab()
+ * Purpose: Generate hyperslab information from H5S_select_hyperslab()
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Quincey Koziol (split from HS_select_hyperslab()).
+ * Programmer: Quincey Koziol
* Tuesday, September 12, 2000
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
static herr_t
-H5S__generate_hyperslab (H5S_t *space, H5S_seloper_t op,
- const hsize_t start[],
- const hsize_t stride[],
- const hsize_t count[],
- const hsize_t block[])
+H5S__generate_hyperslab(H5S_t *space, H5S_seloper_t op, const hsize_t start[],
+ const hsize_t stride[], const hsize_t count[], const hsize_t block[])
{
- H5S_hyper_span_info_t *new_spans=NULL; /* Span tree for new hyperslab */
- H5S_hyper_span_info_t *a_not_b = NULL; /* Span tree for hyperslab spans in old span tree and not in new span tree */
- H5S_hyper_span_info_t *a_and_b = NULL; /* Span tree for hyperslab spans in both old and new span trees */
- H5S_hyper_span_info_t *b_not_a = NULL; /* Span tree for hyperslab spans in new span tree and not in old span tree */
+ H5S_hyper_span_info_t *new_spans = NULL; /* Span tree for new hyperslab */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC
@@ -6284,216 +9434,400 @@ H5S__generate_hyperslab (H5S_t *space, H5S_seloper_t op,
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't create hyperslab information")
/* Generate list of blocks to add/remove based on selection operation */
- if(op==H5S_SELECT_SET) {
- /* Add new spans to current selection */
- if(H5S__hyper_merge_spans(space,new_spans,TRUE)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert hyperslabs")
+ if(op == H5S_SELECT_SET) {
+ /* Free current selection */
+ if(NULL != space->select.sel_info.hslab->span_lst)
+ H5S__hyper_free_span_info(space->select.sel_info.hslab->span_lst);
+
+ /* Set the hyperslab selection to the new span tree */
+ space->select.sel_info.hslab->span_lst = new_spans;
/* Set the number of elements in current selection */
space->select.num_elem = H5S__hyper_spans_nelem(new_spans);
/* Indicate that the new_spans are owned */
- new_spans=NULL;
+ new_spans = NULL;
} /* end if */
else {
- hbool_t updated_spans = FALSE; /* Whether the spans in the selection were modified */
+ hbool_t new_spans_owned = FALSE;
+ hbool_t updated_spans = FALSE;
- /* Generate lists of spans which overlap and don't overlap */
- if(H5S__hyper_clip_spans(space->select.sel_info.hslab->span_lst,new_spans,&a_not_b,&a_and_b,&b_not_a)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL, "can't clip hyperslab information")
+ /* Generate new spans for space */
+ if(H5S__fill_in_new_space(space, op, new_spans, TRUE, &new_spans_owned, &updated_spans, &space) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't generate the specified hyperslab")
- switch(op) {
- case H5S_SELECT_OR:
- /* Add any new spans from b_not_a to current selection */
- if(b_not_a!=NULL) {
- if(H5S__hyper_merge_spans(space,b_not_a,FALSE)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert hyperslabs")
+ /* Check if the spans were updated by H5S__fill_in_new_space */
+ if(updated_spans) {
+ H5S_hyper_dim_t new_hyper_diminfo[H5S_MAX_RANK];
+ unsigned u; /* Local index variable */
- /* Update the number of elements in current selection */
- space->select.num_elem += H5S__hyper_spans_nelem(b_not_a);
+ /* Sanity check */
+ HDassert(space->select.sel_info.hslab->span_lst->head);
+
+ /* Build diminfo struct */
+ for(u = 0; u <space->extent.rank; u++) {
+ new_hyper_diminfo[u].start = start[u];
+ new_hyper_diminfo[u].stride = stride[u];
+ new_hyper_diminfo[u].count = count[u];
+ new_hyper_diminfo[u].block = block[u];
+ } /* end for */
- /* Indicate that the spans were updated */
- updated_spans = TRUE;
- } /* end if */
- break;
+ /* Update space's dim info */
+ if(H5S__hyper_update_diminfo(space, op, new_hyper_diminfo) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOUNT, FAIL, "can't update hyperslab info")
+ } /* end if */
- case H5S_SELECT_AND:
- /* Free the current selection */
- if(H5S__hyper_free_span_info(space->select.sel_info.hslab->span_lst)<0)
- HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "failed to release hyperslab spans")
- space->select.sel_info.hslab->span_lst=NULL;
+ /* Indicate that the new_spans are owned, there's no need to free */
+ if(new_spans_owned)
+ new_spans = NULL;
+ } /* end else */
- /* Reset the number of items in selection */
- space->select.num_elem=0;
+done:
+ if(new_spans)
+ H5S__hyper_free_span_info(new_spans);
- /* Check if there are any overlapped selections */
- if(a_and_b!=NULL) {
- if(H5S__hyper_merge_spans(space,a_and_b,TRUE)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert hyperslabs")
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S__generate_hyperslab() */
- /* Update the number of elements in current selection */
- space->select.num_elem = H5S__hyper_spans_nelem(a_and_b);
- /* Indicate that the a_and_b spans are owned */
- a_and_b=NULL;
+/*-------------------------------------------------------------------------
+ * Function: H5S__set_regular_hyperslab
+ *
+ * Purpose: Set a regular hyperslab
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, October 2, 2014
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5S__set_regular_hyperslab(H5S_t *space, const hsize_t start[],
+ const hsize_t *app_stride, const hsize_t app_count[], const hsize_t *app_block,
+ const hsize_t *opt_stride, const hsize_t opt_count[], const hsize_t *opt_block)
+{
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
- /* Indicate that the spans were updated */
- updated_spans = TRUE;
- } /* end if */
- break;
+ /* Check args */
+ HDassert(space);
+ HDassert(start);
+ HDassert(app_stride);
+ HDassert(app_count);
+ HDassert(app_block);
+ HDassert(opt_stride);
+ HDassert(opt_count);
+ HDassert(opt_block);
+
+ /* If we are setting a new selection, remove current selection first */
+ if(H5S_SELECT_RELEASE(space) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release selection")
- case H5S_SELECT_XOR:
- /* Free the current selection */
- if(H5S__hyper_free_span_info(space->select.sel_info.hslab->span_lst)<0)
- HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "failed to release hyperslab spans")
- space->select.sel_info.hslab->span_lst=NULL;
+ /* Allocate space for the hyperslab selection information */
+ if(NULL == (space->select.sel_info.hslab = H5FL_MALLOC(H5S_hyper_sel_t)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate hyperslab info")
- /* Reset the number of items in selection */
- space->select.num_elem=0;
+ /* Set the diminfo */
+ space->select.num_elem = 1;
+ space->select.sel_info.hslab->unlim_dim = -1;
+ for(u = 0; u < space->extent.rank; u++) {
+ /* Set application and optimized hyperslab info */
+ space->select.sel_info.hslab->diminfo.app[u].start = start[u];
+ space->select.sel_info.hslab->diminfo.app[u].stride = app_stride[u];
+ space->select.sel_info.hslab->diminfo.app[u].count = app_count[u];
+ space->select.sel_info.hslab->diminfo.app[u].block = app_block[u];
+
+ space->select.sel_info.hslab->diminfo.opt[u].start = start[u];
+ space->select.sel_info.hslab->diminfo.opt[u].stride = opt_stride[u];
+ space->select.sel_info.hslab->diminfo.opt[u].count = opt_count[u];
+ space->select.sel_info.hslab->diminfo.opt[u].block = opt_block[u];
+
+ /* Update # of elements selected */
+ space->select.num_elem *= (opt_count[u] * opt_block[u]);
+
+ /* Set low bound of bounding box for the hyperslab selection */
+ space->select.sel_info.hslab->diminfo.low_bounds[u] = start[u];
+
+ /* Check for unlimited dimension & set high bound */
+ if((app_count[u] == H5S_UNLIMITED) || (app_block[u] == H5S_UNLIMITED)) {
+ space->select.sel_info.hslab->unlim_dim = (int)u;
+ space->select.sel_info.hslab->diminfo.high_bounds[u] = H5S_UNLIMITED;
+ } /* end if */
+ else
+ space->select.sel_info.hslab->diminfo.high_bounds[u] = start[u] + opt_stride[u] * (opt_count[u] - 1) + (opt_block[u] - 1);
+ } /* end for */
- /* Check if there are any non-overlapped selections */
- if(a_not_b!=NULL) {
- if(H5S__hyper_merge_spans(space,a_not_b,FALSE)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert hyperslabs")
+ /* Handle unlimited selections */
+ if(space->select.sel_info.hslab->unlim_dim >= 0) {
+ /* Calculate num_elem_non_unlim */
+ space->select.sel_info.hslab->num_elem_non_unlim = (hsize_t)1;
+ for(u = 0; u < space->extent.rank; u++)
+ if((int)u != space->select.sel_info.hslab->unlim_dim)
+ space->select.sel_info.hslab->num_elem_non_unlim *= (opt_count[u] * opt_block[u]);
- /* Update the number of elements in current selection */
- space->select.num_elem = H5S__hyper_spans_nelem(a_not_b);
+ /* Update num_elem */
+ space->select.num_elem = H5S_UNLIMITED;
+ } /* end if */
- /* Indicate that the spans were updated */
- updated_spans = TRUE;
- } /* end if */
- if(b_not_a!=NULL) {
- if(H5S__hyper_merge_spans(space,b_not_a,FALSE)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert hyperslabs")
+ /* Indicate that the dimension information is valid */
+ space->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_YES;
- /* Update the number of elements in current selection */
- space->select.num_elem += H5S__hyper_spans_nelem(b_not_a);
+ /* Indicate that there's no slab information */
+ space->select.sel_info.hslab->span_lst = NULL;
- /* Indicate that the spans were updated */
- updated_spans = TRUE;
- } /* end if */
- break;
+ /* Set selection type */
+ space->select.type = H5S_sel_hyper;
- case H5S_SELECT_NOTB:
- /* Free the current selection */
- if(H5S__hyper_free_span_info(space->select.sel_info.hslab->span_lst)<0)
- HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "failed to release hyperslab spans")
- space->select.sel_info.hslab->span_lst=NULL;
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S__set_regular_hyperslab() */
- /* Reset the number of items in selection */
- space->select.num_elem=0;
- /* Check if there are any non-overlapped selections */
- if(a_not_b!=NULL) {
- if(H5S__hyper_merge_spans(space,a_not_b,TRUE)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert hyperslabs")
+/*-------------------------------------------------------------------------
+ * Function: H5S__hyper_regular_and_single_block
+ *
+ * Purpose: Optimized routine to perform "AND" operation of a single
+ * block against a regular hyperslab selection.
+ *
+ * Note: This algorithm is invoked when constructing the chunk map
+ * and a regular hyperslab is selected in the file's dataspace.
+ *
+ * Return: Non-negative on success / Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Saturday, February 9, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5S__hyper_regular_and_single_block(H5S_t *space, const hsize_t start[],
+ const hsize_t block[])
+{
+ hsize_t select_end, block_end; /* End of block & selection */
+ hbool_t single_block; /* Whether the selection is a single block */
+ hbool_t overlap; /* Whether block & selection overlap */
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
- /* Update the number of elements in current selection */
- space->select.num_elem = H5S__hyper_spans_nelem(a_not_b);
+ /* Check args */
+ HDassert(space);
+ HDassert(start);
+ HDassert(block);
- /* Indicate that the a_not_b are owned */
- a_not_b=NULL;
+ /* Check for single block selection in dataspace */
+ single_block = TRUE;
+ for(u = 0; u < space->extent.rank; u++)
+ if(1 != space->select.sel_info.hslab->diminfo.opt[u].count) {
+ single_block = FALSE;
+ break;
+ } /* end if */
- /* Indicate that the spans were updated */
- updated_spans = TRUE;
- } /* end if */
+ /* Perform different optimizations, based on type of regular selection */
+ if(single_block) {
+ hsize_t new_start[H5S_MAX_RANK]; /* New starting coordinate */
+ hsize_t new_block[H5S_MAX_RANK]; /* New block size */
+
+ /* Check for overlap and compute new start offset & block sizes */
+ overlap = TRUE;
+ for(u = 0; u < space->extent.rank; u++) {
+ /* Compute the end of the selection & block in this dimension */
+ select_end = space->select.sel_info.hslab->diminfo.high_bounds[u];
+ block_end = (start[u] + block[u]) - 1;
+
+ /* Check for overlap */
+ if(!H5S_RANGE_OVERLAP(space->select.sel_info.hslab->diminfo.opt[u].start, select_end, start[u], block_end)) {
+ overlap = FALSE;
break;
+ } /* end if */
- case H5S_SELECT_NOTA:
- /* Free the current selection */
- if(H5S__hyper_free_span_info(space->select.sel_info.hslab->span_lst)<0)
- HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "failed to release hyperslab spans")
- space->select.sel_info.hslab->span_lst=NULL;
+ /* Set new start & block size in this dimension */
+ new_start[u] = MAX(space->select.sel_info.hslab->diminfo.opt[u].start, start[u]);
+ new_block[u] = (MIN(select_end, block_end) - new_start[u]) + 1;
+ } /* end for */
- /* Reset the number of items in selection */
- space->select.num_elem=0;
+ /* Check for overlap of selection & block */
+ if(overlap) {
+ /* Set selection to regular hyperslab */
+ if(H5S__set_regular_hyperslab(space, new_start, H5S_hyper_ones_g, H5S_hyper_ones_g, new_block,
+ H5S_hyper_ones_g, H5S_hyper_ones_g, new_block) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't set regular hyperslab selection")
+ } /* end if */
+ else
+ /* Selection & block don't overlap, set to "none" selection */
+ if(H5S_select_none(space) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't convert selection")
+ } /* end if */
+ else {
+ hsize_t new_start[H5S_MAX_RANK]; /* New start for hyperslab selection */
+ hsize_t new_count[H5S_MAX_RANK]; /* New count for hyperslab selection */
+ hsize_t stride[H5S_MAX_RANK]; /* Stride for hyperslab selection */
+ hsize_t new_block[H5S_MAX_RANK]; /* New block for hyperslab selection */
+ hbool_t partial_first_span; /* Whether first span in intersection is partial */
+ hbool_t partial_last_span; /* Whether last span in intersection is partial */
+
+ /* Iterate over selection, checking for overlap and computing first / last
+ * span that intersects with the block.
+ */
+ overlap = TRUE;
+ partial_first_span = FALSE;
+ partial_last_span = FALSE;
+ for(u = 0; u < space->extent.rank; u++) {
+ hsize_t first_span_start, first_span_end; /* Start / end of first span */
+ hsize_t last_span_start, last_span_end; /* Start / end of last span */
+ hsize_t nstride; /* Number of strides into the selection */
+
+ /* Compute the end of the selection & block in this dimension */
+ select_end = space->select.sel_info.hslab->diminfo.high_bounds[u];
+ block_end = (start[u] + block[u]) - 1;
+
+ /* Check for overlap */
+ if(!H5S_RANGE_OVERLAP(space->select.sel_info.hslab->diminfo.opt[u].start, select_end, start[u], block_end)) {
+ overlap = FALSE;
+ break;
+ } /* end if */
- /* Check if there are any non-overlapped selections */
- if(b_not_a!=NULL) {
- if(H5S__hyper_merge_spans(space,b_not_a,TRUE)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert hyperslabs")
+ /* Find first span that is before or overlaps with start of block */
+ if(space->select.sel_info.hslab->diminfo.opt[u].start >= start[u]) {
+ /* Calculate start & end of first span */
+ first_span_start = space->select.sel_info.hslab->diminfo.opt[u].start;
+ first_span_end = (first_span_start +
+ space->select.sel_info.hslab->diminfo.opt[u].block) - 1;
- /* Update the number of elements in current selection */
- space->select.num_elem = H5S__hyper_spans_nelem(b_not_a);
+ /* Check if first span overlaps _end_ of block */
+ if(block_end >= first_span_start && block_end <= first_span_end)
+ partial_first_span = TRUE;
+ } /* end if */
+ else {
+ hsize_t adj_start; /* Start coord, adjusted for hyperslab selection parameters */
- /* Indicate that the b_not_a are owned */
- b_not_a=NULL;
+ /* Adjust start coord for selection's 'start' offset */
+ adj_start = start[u] - space->select.sel_info.hslab->diminfo.opt[u].start;
- /* Indicate that the spans were updated */
- updated_spans = TRUE;
+ /* Compute # of strides into the selection */
+ if(space->select.sel_info.hslab->diminfo.opt[u].count > 1)
+ nstride = adj_start / space->select.sel_info.hslab->diminfo.opt[u].stride;
+ else
+ nstride = 0;
+
+ /* Calculate start & end of first span */
+ first_span_start = space->select.sel_info.hslab->diminfo.opt[u].start +
+ (nstride * space->select.sel_info.hslab->diminfo.opt[u].stride);
+ first_span_end = (first_span_start +
+ space->select.sel_info.hslab->diminfo.opt[u].block) - 1;
+
+ /* Check if first span overlaps start of block */
+ if(first_span_start < start[u] && first_span_end >= start[u])
+ partial_first_span = TRUE;
+
+ /* Advance first span to start higher than block's start,
+ * if it's not partial.
+ */
+ if(first_span_end < start[u]) {
+ first_span_start += space->select.sel_info.hslab->diminfo.opt[u].stride;
+ first_span_end += space->select.sel_info.hslab->diminfo.opt[u].stride;
} /* end if */
- break;
+ } /* end else */
- case H5S_SELECT_NOOP:
- case H5S_SELECT_SET:
- case H5S_SELECT_APPEND:
- case H5S_SELECT_PREPEND:
- case H5S_SELECT_INVALID:
- default:
- HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation")
- } /* end switch */
+ /* Find last span that is before or overlaps with end of block */
+ if(select_end < block_end) {
+ /* Calculate start & end of last span */
+ last_span_start = (select_end -
+ space->select.sel_info.hslab->diminfo.opt[u].block) + 1;
+ last_span_end = select_end;
- /* Check if the resulting hyperslab span tree is empty */
- if(space->select.sel_info.hslab->span_lst==NULL) {
- H5S_hyper_span_info_t *spans; /* Empty hyperslab span tree */
+ /* Check if last span overlaps _start_ of block */
+ if(start[u] >= last_span_start && start[u] <= last_span_end)
+ partial_last_span = TRUE;
+ } /* end if */
+ else {
+ hsize_t adj_end; /* End coord, adjusted for hyperslab selection parameters */
+
+ /* Adjust end coord for selection's 'start' offset */
+ adj_end = block_end - space->select.sel_info.hslab->diminfo.opt[u].start;
+
+ /* Compute # of strides into the selection */
+ if(space->select.sel_info.hslab->diminfo.opt[u].count > 1)
+ nstride = adj_end / space->select.sel_info.hslab->diminfo.opt[u].stride;
+ else
+ nstride = 0;
+
+ /* Calculate start & end of last span */
+ last_span_start = space->select.sel_info.hslab->diminfo.opt[u].start +
+ (nstride * space->select.sel_info.hslab->diminfo.opt[u].stride);
+ last_span_end = (last_span_start +
+ space->select.sel_info.hslab->diminfo.opt[u].block) - 1;
+
+ /* Check if last span overlaps end of block */
+ if(block_end >= last_span_start && block_end <= last_span_end)
+ partial_last_span = TRUE;
+ } /* end else */
+
+ /* Check if no spans are inside block */
+ /* (Can happen when block falls in "gap" between spans) */
+ if(last_span_end < start[u]) {
+ overlap = FALSE;
+ break;
+ } /* end if */
/* Sanity check */
- HDassert(space->select.num_elem == 0);
+ HDassert(first_span_start <= last_span_start);
- /* Allocate a span info node */
- if((spans = H5FL_MALLOC(H5S_hyper_span_info_t))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span")
+ /* Compute new start / count / block values */
+ new_start[u] = first_span_start;
+ if(last_span_start != first_span_start)
+ new_count[u] = ((last_span_start - first_span_start) /
+ space->select.sel_info.hslab->diminfo.opt[u].stride) + 1;
+ else
+ new_count[u] = 1;
+ new_block[u] = space->select.sel_info.hslab->diminfo.opt[u].block;
- /* Set the reference count */
- spans->count=1;
+ /* Keep same stride */
+ stride[u] = space->select.sel_info.hslab->diminfo.opt[u].stride;
+ } /* end for */
- /* Reset the scratch pad space */
- spans->scratch=0;
+ /* Check for overlap of selection & block */
+ if(overlap) {
+ /* Set selection to regular hyperslab */
+ if(H5S__set_regular_hyperslab(space, new_start, stride, new_count, new_block,
+ stride, new_count, new_block) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't set regular hyperslab selection")
- /* Set to empty tree */
- spans->head=NULL;
+ /* If there's a partial first or last span, have to 'AND' against selection */
+ if(partial_first_span || partial_last_span) {
+ /* Generate span tree for regular selection */
+ if(H5S__hyper_generate_spans(space) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "dataspace does not have span tree")
- /* Set pointer to empty span tree */
- space->select.sel_info.hslab->span_lst=spans;
+ /* 'AND' against block */
+ if(H5S__generate_hyperslab(space, H5S_SELECT_AND, start, H5S_hyper_ones_g, H5S_hyper_ones_g, block) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't generate hyperslabs")
+ } /* end if */
} /* end if */
else {
- /* Check if we updated the spans */
- if(updated_spans) {
- /* Attempt to rebuild "optimized" start/stride/count/block information.
- * from resulting hyperslab span tree
- */
- H5S__hyper_rebuild(space);
- } /* end if */
+ /* Selection & block don't overlap, set to "none" selection */
+ if(H5S_select_none(space) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't convert selection")
} /* end else */
} /* end else */
done:
- /* Free resources */
- if(a_not_b)
- if(H5S__hyper_free_span_info(a_not_b) < 0)
- HDONE_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "failed to release temporary hyperslab spans")
- if(a_and_b)
- if(H5S__hyper_free_span_info(a_and_b) < 0)
- HDONE_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "failed to release temporary hyperslab spans")
- if(b_not_a)
- if(H5S__hyper_free_span_info(b_not_a) < 0)
- HDONE_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "failed to release temporary hyperslab spans")
- if(new_spans)
- if(H5S__hyper_free_span_info(new_spans) < 0)
- HDONE_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "failed to release temporary hyperslab spans")
-
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5S__generate_hyperslab() */
+} /* end H5S__hyper_regular_and_single_block() */
+
-
/*-------------------------------------------------------------------------
- * Function: H5S_select_hyperslab
+ * Function: H5S_select_hyperslab
*
- * Purpose: Internal version of H5Sselect_hyperslab().
+ * Purpose: Internal version of H5Sselect_hyperslab().
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* Wednesday, January 10, 2001
*
*-------------------------------------------------------------------------
@@ -6502,9 +9836,9 @@ herr_t
H5S_select_hyperslab(H5S_t *space, H5S_seloper_t op, const hsize_t start[],
const hsize_t *stride, const hsize_t count[], const hsize_t *block)
{
- hsize_t int_stride[H5O_LAYOUT_NDIMS]; /* Internal storage for stride information */
- hsize_t int_count[H5O_LAYOUT_NDIMS]; /* Internal storage for count information */
- hsize_t int_block[H5O_LAYOUT_NDIMS]; /* Internal storage for block information */
+ hsize_t int_stride[H5S_MAX_RANK]; /* Internal storage for stride information */
+ hsize_t int_count[H5S_MAX_RANK]; /* Internal storage for count information */
+ hsize_t int_block[H5S_MAX_RANK]; /* Internal storage for block information */
const hsize_t *opt_stride; /* Optimized stride information */
const hsize_t *opt_count; /* Optimized count information */
const hsize_t *opt_block; /* Optimized block information */
@@ -6528,9 +9862,7 @@ H5S_select_hyperslab(H5S_t *space, H5S_seloper_t op, const hsize_t start[],
if(block == NULL)
block = H5S_hyper_ones_g;
- /*
- * Check new selection.
- */
+ /* Check new selection */
for(u = 0; u < space->extent.rank; u++) {
/* Check for overlapping hyperslab blocks in new selection. */
if(count[u] > 1 && stride[u] < block[u])
@@ -6566,7 +9898,7 @@ H5S_select_hyperslab(H5S_t *space, H5S_seloper_t op, const hsize_t start[],
if(unlim_dim >= 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "cannot have more than one unlimited dimension in selection")
else {
- if(count[u] == block[u] /* == H5S_UNLIMITED */)
+ if(count[u] == block[u]) /* Both are H5S_UNLIMITED */
HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "count and block cannot both be unlimited")
unlim_dim = (int)u;
} /* end else */
@@ -6716,6 +10048,7 @@ H5S_select_hyperslab(H5S_t *space, H5S_seloper_t op, const hsize_t start[],
if(op == H5S_SELECT_SET) /* Allow only "set" operation to proceed */
break;
/* Else fall through to error */
+ H5_ATTR_FALLTHROUGH
case H5S_SEL_ERROR:
case H5S_SEL_N:
@@ -6724,56 +10057,13 @@ H5S_select_hyperslab(H5S_t *space, H5S_seloper_t op, const hsize_t start[],
} /* end switch */
if(op == H5S_SELECT_SET) {
- /* If we are setting a new selection, remove current selection first */
- if(H5S_SELECT_RELEASE(space) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release selection")
-
- /* Allocate space for the hyperslab selection information */
- if(NULL == (space->select.sel_info.hslab = H5FL_MALLOC(H5S_hyper_sel_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab info")
-
- /* Save the diminfo */
- space->select.num_elem = 1;
- for(u = 0; u < space->extent.rank; u++) {
- space->select.sel_info.hslab->app_diminfo[u].start = start[u];
- space->select.sel_info.hslab->app_diminfo[u].stride = stride[u];
- space->select.sel_info.hslab->app_diminfo[u].count = count[u];
- space->select.sel_info.hslab->app_diminfo[u].block = block[u];
-
- space->select.sel_info.hslab->opt_diminfo[u].start = start[u];
- space->select.sel_info.hslab->opt_diminfo[u].stride = opt_stride[u];
- space->select.sel_info.hslab->opt_diminfo[u].count = opt_count[u];
- space->select.sel_info.hslab->opt_diminfo[u].block = opt_block[u];
-
- space->select.num_elem *= (opt_count[u] * opt_block[u]);
- } /* end for */
-
- /* Save unlim_dim */
- space->select.sel_info.hslab->unlim_dim = unlim_dim;
-
- /* Indicate that the dimension information is valid */
- space->select.sel_info.hslab->diminfo_valid = TRUE;
-
- /* Indicate that there's no slab information */
- space->select.sel_info.hslab->span_lst = NULL;
-
- /* Handle unlimited selections */
- if(unlim_dim >= 0) {
- /* Calculate num_elem_non_unlim */
- space->select.sel_info.hslab->num_elem_non_unlim = (hsize_t)1;
- for(u = 0; u < space->extent.rank; u++)
- if((int)u != unlim_dim)
- space->select.sel_info.hslab->num_elem_non_unlim *= (opt_count[u] * opt_block[u]);
-
- /* Set num_elem */
- if(space->select.num_elem != (hsize_t)0)
- space->select.num_elem = H5S_UNLIMITED;
- } /* end if */
-
- /* Set selection type */
- space->select.type = H5S_sel_hyper;
+ /* Set selection to regular hyperslab */
+ if(H5S__set_regular_hyperslab(space, start, stride, count, block, opt_stride, opt_count, opt_block) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't set regular hyperslab selection")
} /* end if */
else if(op >= H5S_SELECT_OR && op <= H5S_SELECT_NOTA) {
+ hbool_t single_block; /* Whether the selection is a single block */
+
/* Sanity check */
HDassert(H5S_GET_SELECT_TYPE(space) == H5S_SEL_HYPERSLABS);
@@ -6795,7 +10085,8 @@ H5S_select_hyperslab(H5S_t *space, H5S_seloper_t op, const hsize_t start[],
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get selection bounds")
/* Patch count and block to remove unlimited and include the
- * existing selection */
+ * existing selection.
+ */
H5S__hyper_get_clip_diminfo(start[unlim_dim], opt_stride[unlim_dim], &tmp_count, &tmp_block, bounds_end[unlim_dim] + (hsize_t)1);
HDassert((tmp_count == 1) || (opt_count != H5S_hyper_ones_g));
HDassert((tmp_block == 1) || (opt_block != H5S_hyper_ones_g));
@@ -6809,21 +10100,35 @@ H5S_select_hyperslab(H5S_t *space, H5S_seloper_t op, const hsize_t start[],
} /* end if */
} /* end if */
- /* Check if there's no hyperslab span information currently */
- if(NULL == space->select.sel_info.hslab->span_lst)
- if(H5S__hyper_generate_spans(space) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "dataspace does not have span tree")
+ /* Check for a single block selected */
+ single_block = TRUE;
+ for(u = 0; u < space->extent.rank; u++)
+ if(1 != opt_count[u]) {
+ single_block = FALSE;
+ break;
+ } /* end if */
- /* Indicate that the regular dimensions are no longer valid */
- space->select.sel_info.hslab->diminfo_valid = FALSE;
+ /* Check for single block "AND" operation on a regular hyperslab, which
+ * is used for constructing chunk maps and can be optimized for.
+ */
+ if(H5S_SELECT_AND == op && single_block &&
+ space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) {
+ if(H5S__hyper_regular_and_single_block(space, start, opt_block) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTOPERATE, FAIL, "can't 'AND' single block against regular hyperslab")
+ } /* end if */
+ else {
+ /* Check if there's no hyperslab span information currently */
+ if(NULL == space->select.sel_info.hslab->span_lst)
+ if(H5S__hyper_generate_spans(space) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "dataspace does not have span tree")
- /* Set selection type */
- /* (Could be overridden by resetting selection to 'none', below) */
- space->select.type = H5S_sel_hyper;
+ /* Set selection type */
+ space->select.type = H5S_sel_hyper;
- /* Add in the new hyperslab information */
- if(H5S__generate_hyperslab(space, op, start, opt_stride, opt_count, opt_block) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't generate hyperslabs")
+ /* Add in the new hyperslab information */
+ if(H5S__generate_hyperslab(space, op, start, opt_stride, opt_count, opt_block) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't generate hyperslabs")
+ } /* end else */
} /* end if */
else
HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation")
@@ -6832,7 +10137,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_select_hyperslab() */
-
+
/*--------------------------------------------------------------------------
NAME
H5Sselect_hyperslab
@@ -6895,692 +10200,267 @@ H5Sselect_hyperslab(hid_t space_id, H5S_seloper_t op, const hsize_t start[],
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Sselect_hyperslab() */
-#else /* NEW_HYPERSLAB_API */ /* Works */
-
-/*-------------------------------------------------------------------------
- * Function: H5S_operate_hyperslab
- *
- * Purpose: Combines two hyperslabs with an operation, putting the
- * result into a third hyperslab selection
- *
- * Return: non-negative on success/NULL on failure
- *
- * Programmer: Quincey Koziol
- * Tuesday, October 30, 2001
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5S_operate_hyperslab (H5S_t *result, H5S_hyper_span_info_t *spans1, H5S_seloper_t op, H5S_hyper_span_info_t *spans2,
- hbool_t can_own_span2, hbool_t *span2_owned)
-{
- H5S_hyper_span_info_t *a_not_b=NULL; /* Span tree for hyperslab spans in old span tree and not in new span tree */
- H5S_hyper_span_info_t *a_and_b=NULL; /* Span tree for hyperslab spans in both old and new span trees */
- H5S_hyper_span_info_t *b_not_a=NULL; /* Span tree for hyperslab spans in new span tree and not in old span tree */
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT
-
- /* Check args */
- HDassert(result);
- HDassert(spans2);
- HDassert(op > H5S_SELECT_NOOP && op < H5S_SELECT_INVALID);
-
- /* Just copy the selection from spans2 if we are setting the selection */
- /* ('space1' to 'result' aliasing happens at the next layer up) */
- if(op==H5S_SELECT_SET) {
- if(H5S__hyper_merge_spans(result,spans2,can_own_span2)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert hyperslabs")
-
- /* Update the number of elements in current selection */
- result->select.num_elem = H5S__hyper_spans_nelem(spans2);
-
- /* Indicate that we took ownership of span2, if allowed */
- if(can_own_span2)
- *span2_owned=TRUE;
- } /* end if */
- else {
- hbool_t updated_spans = FALSE; /* Whether the spans in the selection were modified */
-
- HDassert(spans1);
-
- /* Generate lists of spans which overlap and don't overlap */
- if(H5S__hyper_clip_spans(spans1,spans2,&a_not_b,&a_and_b,&b_not_a)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL, "can't clip hyperslab information")
-
- /* Switch on the operation */
- switch(op) {
- case H5S_SELECT_OR:
- /* Copy spans from spans1 to current selection */
- if(spans1!=NULL) {
- if(H5S__hyper_merge_spans(result,spans1,FALSE)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert hyperslabs")
-
- /* Update the number of elements in current selection */
- result->select.num_elem = H5S__hyper_spans_nelem(spans1);
- } /* end if */
-
- /* Add any new spans from spans2 to current selection */
- if(b_not_a!=NULL) {
- if(H5S__hyper_merge_spans(result,b_not_a,FALSE)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert hyperslabs")
- /* Update the number of elements in current selection */
- result->select.num_elem += H5S__hyper_spans_nelem(b_not_a);
-
- /* Indicate that the spans were updated */
- updated_spans = TRUE;
- } /* end if */
- break;
-
- case H5S_SELECT_AND:
- /* Check if there are any overlapped selections */
- if(a_and_b!=NULL) {
- if(H5S__hyper_merge_spans(result,a_and_b,TRUE)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert hyperslabs")
-
- /* Update the number of elements in current selection */
- result->select.num_elem = H5S__hyper_spans_nelem(a_and_b);
-
- /* Indicate that the result owns the a_and_b spans */
- a_and_b=NULL;
-
- /* Indicate that the spans were updated */
- updated_spans = TRUE;
- } /* end if */
- break;
-
- case H5S_SELECT_XOR:
- /* Check if there are any non-overlapped selections */
- if(a_not_b!=NULL) {
- if(H5S__hyper_merge_spans(result,a_not_b,FALSE)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert hyperslabs")
-
- /* Update the number of elements in current selection */
- result->select.num_elem = H5S__hyper_spans_nelem(a_not_b);
-
- /* Indicate that the spans were updated */
- updated_spans = TRUE;
- } /* end if */
- if(b_not_a!=NULL) {
- if(H5S__hyper_merge_spans(result,b_not_a,FALSE)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert hyperslabs")
-
- /* Update the number of elements in current selection */
- result->select.num_elem += H5S__hyper_spans_nelem(b_not_a);
-
- /* Indicate that the spans were updated */
- updated_spans = TRUE;
- } /* end if */
- break;
- case H5S_SELECT_NOTB:
- /* Check if there are any non-overlapped selections */
- if(a_not_b!=NULL) {
- if(H5S__hyper_merge_spans(result,a_not_b,TRUE)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert hyperslabs")
-
- /* Update the number of elements in current selection */
- result->select.num_elem = H5S__hyper_spans_nelem(a_not_b);
-
- /* Indicate that the result owns the a_not_b spans */
- a_not_b=NULL;
-
- /* Indicate that the spans were updated */
- updated_spans = TRUE;
- } /* end if */
- break;
-
- case H5S_SELECT_NOTA:
- /* Check if there are any non-overlapped selections */
- if(b_not_a!=NULL) {
- if(H5S__hyper_merge_spans(result,b_not_a,TRUE)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert hyperslabs")
-
- /* Update the number of elements in current selection */
- result->select.num_elem = H5S__hyper_spans_nelem(b_not_a);
-
- /* Indicate that the result owns the b_not_a spans */
- b_not_a=NULL;
-
- /* Indicate that the spans were updated */
- updated_spans = TRUE;
- } /* end if */
- break;
-
- default:
- HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation")
- } /* end switch */
-
- /* Free the hyperslab trees generated from the clipping algorithm */
- if(a_not_b)
- H5S__hyper_free_span_info(a_not_b);
- if(a_and_b)
- H5S__hyper_free_span_info(a_and_b);
- if(b_not_a)
- H5S__hyper_free_span_info(b_not_a);
-
- /* Check if the resulting hyperslab span tree is empty */
- if(result->select.sel_info.hslab->span_lst==NULL) {
- H5S_hyper_span_info_t *spans; /* Empty hyperslab span tree */
-
- /* Sanity check */
- HDassert(result->select.num_elem == 0);
-
- /* Allocate a span info node */
- if((spans = H5FL_MALLOC(H5S_hyper_span_info_t))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate hyperslab span")
-
- /* Set the reference count */
- spans->count=1;
-
- /* Reset the scratch pad space */
- spans->scratch=0;
-
- /* Set to empty tree */
- spans->head=NULL;
-
- /* Set pointer to empty span tree */
- result->select.sel_info.hslab->span_lst=spans;
- } /* end if */
- else {
- /* Check if we updated the spans */
- if(updated_spans) {
- /* Attempt to rebuild "optimized" start/stride/count/block information.
- * from resulting hyperslab span tree
- */
- H5S__hyper_rebuild(result);
- } /* end if */
- } /* end else */
- } /* end else */
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5S_operate_hyperslab() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5S_generate_hyperlab
- *
- * Purpose: Generate hyperslab information from H5S_select_hyperslab()
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol (split from HS_select_hyperslab()).
- * Tuesday, September 12, 2000
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5S__generate_hyperslab(H5S_t *space, H5S_seloper_t op, const hsize_t start[],
- const hsize_t stride[], const hsize_t count[], const hsize_t block[])
-{
- H5S_hyper_span_info_t *new_spans=NULL; /* Span tree for new hyperslab */
- H5S_hyper_span_info_t *tmp_spans=NULL; /* Temporary copy of selection */
- hbool_t span2_owned=FALSE; /* Flag to indicate that span2 was used in H5S_operate_hyperslab() */
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT
-
- /* Check args */
- HDassert(space);
- HDassert(op > H5S_SELECT_NOOP && op < H5S_SELECT_INVALID);
- HDassert(start);
- HDassert(stride);
- HDassert(count);
- HDassert(block);
-
- /* Generate span tree for new hyperslab information */
- if(NULL == (new_spans = H5S__hyper_make_spans(space->extent.rank, start, stride, count, block)))
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't create hyperslab information")
-
- /* Copy the original dataspace */
- if(space->select.sel_info.hslab->span_lst!=NULL) {
- /* Take ownership of the dataspace's hyperslab spans */
- /* (These are freed later) */
- tmp_spans=space->select.sel_info.hslab->span_lst;
- space->select.sel_info.hslab->span_lst=NULL;
-
- /* Reset the other dataspace selection information */
- if(H5S_SELECT_RELEASE(space)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release selection")
-
- /* Allocate space for the hyperslab selection information */
- if((space->select.sel_info.hslab=H5FL_MALLOC(H5S_hyper_sel_t))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab info")
-
- /* Set unlim_dim */
- space->select.sel_info.hslab->unlim_dim = -1;
- } /* end if */
-
- /* Combine tmp_space (really space) & new_space, with the result in space */
- if(H5S_operate_hyperslab(space,tmp_spans,op,new_spans,TRUE,&span2_owned)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL, "can't clip hyperslab information")
-
-done:
- /* Free temporary data structures */
- if(tmp_spans!=NULL)
- if(H5S__hyper_free_span_info(tmp_spans)<0)
- HDONE_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "failed to release temporary hyperslab spans")
- if(new_spans!=NULL && span2_owned==FALSE)
- if(H5S__hyper_free_span_info(new_spans)<0)
- HDONE_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "failed to release temporary hyperslab spans")
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5S__generate_hyperslab() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5S_select_hyperslab
- *
- * Purpose: Internal version of H5Sselect_hyperslab().
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * Wednesday, January 10, 2001
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
+/*--------------------------------------------------------------------------
+ NAME
+ H5S_combine_hyperslab
+ PURPOSE
+ Specify a hyperslab to combine with the current hyperslab selection, and
+ store the result in the new hyperslab selection.
+ USAGE
+ herr_t H5S_combine_hyperslab(new_space, old_space, op, start, stride, count, block)
+ H5S_t *old_space; IN: The old space the selection is performed on
+ H5S_seloper_t op; IN: Operation to perform on current selection
+ const hsize_t start[]; IN: Offset of start of hyperslab
+ const hsize_t *stride; IN: Hyperslab stride
+ const hsize_t count[]; IN: Number of blocks included in hyperslab
+ const hsize_t *block; IN: Size of block in hyperslab
+ H5S_t **new_space; OUT: The new dataspace to store the selection result
+ RETURNS
+ Non-negative on success/Negative on failure
+ DESCRIPTION
+ Combines a hyperslab selection with the current selection for a dataspace.
+ If STRIDE or BLOCK is NULL, they are assumed to be set to all '1'.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ In some cases, copying the whole span tree from old_space to new_space
+ can be avoided. Deal with such cases directly, otherwise this function
+ is equivalent to:
+ 1. Copy the whole span tree from old_space into new_space
+ 2. Call H5S_select_hyperslab with the new_space.
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
herr_t
-H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op,
- const hsize_t start[],
- const hsize_t *stride,
- const hsize_t count[],
- const hsize_t *block)
+H5S_combine_hyperslab(H5S_t *old_space, H5S_seloper_t op, const hsize_t start[],
+ const hsize_t *stride, const hsize_t count[], const hsize_t *block,
+ H5S_t **new_space)
{
- hsize_t int_stride[H5O_LAYOUT_NDIMS]; /* Internal storage for stride information */
- hsize_t int_count[H5O_LAYOUT_NDIMS]; /* Internal storage for count information */
- hsize_t int_block[H5O_LAYOUT_NDIMS]; /* Internal storage for block information */
- const hsize_t *opt_stride; /* Optimized stride information */
- const hsize_t *opt_count; /* Optimized count information */
- const hsize_t *opt_block; /* Optimized block information */
- unsigned u; /* Counters */
- int unlim_dim = -1; /* Unlimited dimension in selection, of -1 if none */
- herr_t ret_value=SUCCEED; /* Return value */
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
/* Check args */
- HDassert(space);
+ HDassert(old_space);
HDassert(start);
HDassert(count);
- HDassert(op > H5S_SELECT_NOOP && op < H5S_SELECT_INVALID);
+ HDassert(op >= H5S_SELECT_SET && op <= H5S_SELECT_NOTA);
+ HDassert(new_space);
+ HDassert(*new_space == NULL);
/* Point to the correct stride values */
- if(stride==NULL)
+ if(stride == NULL)
stride = H5S_hyper_ones_g;
/* Point to the correct block values */
- if(block==NULL)
+ if(block == NULL)
block = H5S_hyper_ones_g;
- /* Check for unlimited dimension */
- for(u = 0; u<space->extent.rank; u++)
- if((count[u] == H5S_UNLIMITED) || (block[u] == H5S_UNLIMITED)) {
- if(unlim_dim >= 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "cannot have more than one unlimited dimension in selection")
- else {
- if(count[u] == block[u] /* == H5S_UNLIMITED */)
- HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "count and block cannot both be unlimited")
- unlim_dim = (int)u;
- } /* end else */
- } /* end if */
-
- /*
- * Check new selection.
- */
- for(u=0; u<space->extent.rank; u++) {
+ /* Check new selection. */
+ for(u = 0; u < old_space->extent.rank; u++) {
/* Check for overlapping hyperslab blocks in new selection. */
- if(count[u]>1 && stride[u]<block[u])
+ if(count[u] > 1 && stride[u] < block[u])
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "hyperslab blocks overlap")
/* Detect zero-sized hyperslabs in new selection */
if(count[u] == 0 || block[u] == 0) {
switch(op) {
- case H5S_SELECT_SET: /* Select "set" operation */
case H5S_SELECT_AND: /* Binary "and" operation for hyperslabs */
case H5S_SELECT_NOTA: /* Binary "B not A" operation for hyperslabs */
/* Convert to "none" selection */
- if(H5S_select_none(space)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't convert selection")
+ /* Copy the first dataspace without sharing the list of spans */
+ if(NULL == ((*new_space) = H5S_copy(old_space, TRUE, TRUE)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to copy dataspace")
+ if(H5S_select_none((*new_space)) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't convert selection")
HGOTO_DONE(SUCCEED);
case H5S_SELECT_OR: /* Binary "or" operation for hyperslabs */
case H5S_SELECT_XOR: /* Binary "xor" operation for hyperslabs */
case H5S_SELECT_NOTB: /* Binary "A not B" operation for hyperslabs */
+ /* Copy the first dataspace with sharing the list of spans */
+ if(NULL == ((*new_space) = H5S_copy(old_space, FALSE, TRUE)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to copy dataspace")
HGOTO_DONE(SUCCEED); /* Selection stays same */
+ case H5S_SELECT_NOOP:
+ case H5S_SELECT_SET:
+ case H5S_SELECT_APPEND:
+ case H5S_SELECT_PREPEND:
+ case H5S_SELECT_INVALID:
default:
HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation")
} /* end switch */
} /* end if */
} /* end for */
- /* Optimize hyperslab parameters to merge contiguous blocks, etc. */
- if(stride == H5S_hyper_ones_g && block == H5S_hyper_ones_g) {
- /* Point to existing arrays */
- opt_stride = H5S_hyper_ones_g;
- opt_count = H5S_hyper_ones_g;
- opt_block = count;
- } /* end if */
- else {
- /* Point to local arrays */
- opt_stride = int_stride;
- opt_count = int_count;
- opt_block = int_block;
- for(u=0; u<space->extent.rank; u++) {
- /* contiguous hyperslabs have the block size equal to the stride */
- if((stride[u] == block[u]) && (count[u] != H5S_UNLIMITED)) {
- int_count[u]=1;
- int_stride[u]=1;
- if(block[u]==1)
- int_block[u]=count[u];
- else
- int_block[u]=block[u]*count[u];
- } /* end if */
- else {
- if(count[u]==1)
- int_stride[u]=1;
- else {
- HDassert((stride[u] > block[u]) || ((stride[u] == block[u])
- && (count[u] == H5S_UNLIMITED)));
- int_stride[u]=stride[u];
- } /* end else */
- int_count[u]=count[u];
- int_block[u]=block[u];
- } /* end else */
- } /* end for */
- } /* end else */
-
- /* Check for operating on unlimited selection */
- if((H5S_GET_SELECT_TYPE(space) == H5S_SEL_HYPERSLABS)
- && (space->select.sel_info.hslab->unlim_dim >= 0)
- && (op != H5S_SELECT_SET))
- {
- /* Check for invalid operation */
- if(unlim_dim >= 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "cannot modify unlimited selection with another unlimited selection")
- if(!((op == H5S_SELECT_AND) || (op == H5S_SELECT_NOTA)))
- HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unsupported operation on unlimited selection")
- HDassert(space->select.sel_info.hslab->diminfo_valid);
+ if(H5S_GET_SELECT_TYPE(old_space) == H5S_SEL_HYPERSLABS) {
+ hsize_t *old_low_bounds; /* Pointer to old space's low & high bounds */
+ hsize_t *old_high_bounds;
+ hsize_t new_low_bounds[H5S_MAX_RANK]; /* New space's low & high bounds */
+ hsize_t new_high_bounds[H5S_MAX_RANK];
+ hbool_t overlapped = FALSE;
+
+ /* Set up old space's low & high bounds */
+ if(old_space->select.sel_info.hslab->span_lst) {
+ old_low_bounds = old_space->select.sel_info.hslab->span_lst->low_bounds;
+ old_high_bounds = old_space->select.sel_info.hslab->span_lst->high_bounds;
+ } /* end if */
+ else {
+ old_low_bounds = old_space->select.sel_info.hslab->diminfo.low_bounds;
+ old_high_bounds = old_space->select.sel_info.hslab->diminfo.high_bounds;
+ } /* end else */
- /* Clip unlimited selection to include new selection */
- if(H5S_hyper_clip_unlim(space,
- start[space->select.sel_info.hslab->unlim_dim]
- + ((opt_count[space->select.sel_info.hslab->unlim_dim]
- - (hsize_t)1)
- * opt_stride[space->select.sel_info.hslab->unlim_dim])
- + opt_block[space->select.sel_info.hslab->unlim_dim]) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL, "failed to clip unlimited selection")
+ /* Generate bounding box for hyperslab parameters */
+ for(u = 0; u < old_space->extent.rank; u++) {
+ new_low_bounds[u] = start[u];
+ new_high_bounds[u] = start[u] + stride[u] * (count[u] - 1) + (block[u] - 1);
+ } /* end for */
- /* If an empty space was returned it must be "none" */
- HDassert((space->select.num_elem > (hsize_t)0)
- || (space->select.type->type == H5S_SEL_NONE));
- } /* end if */
+ /* Check bound box of both spaces to see if they overlap */
+ if(H5S_RANGE_OVERLAP(old_low_bounds[0], old_high_bounds[0],
+ new_low_bounds[0], new_high_bounds[0]))
+ overlapped = TRUE;
+
+ /* Non-overlapping situations can be handled in special ways */
+ if(!overlapped) {
+ H5S_hyper_span_info_t *new_spans = NULL;
+ H5S_hyper_dim_t new_hyper_diminfo[H5S_MAX_RANK];
+
+ if(NULL == ((*new_space) = H5S_copy(old_space, TRUE, TRUE)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy dataspace")
+ if(NULL != (*new_space)->select.sel_info.hslab->span_lst) {
+ old_space->select.sel_info.hslab->span_lst->count--;
+ (*new_space)->select.sel_info.hslab->span_lst = NULL;
+ } /* end if */
- /* Fixup operation for non-hyperslab selections */
- switch(H5S_GET_SELECT_TYPE(space)) {
- case H5S_SEL_NONE: /* No elements selected in dataspace */
+ /* Generate hyperslab info for new space */
switch(op) {
- case H5S_SELECT_SET: /* Select "set" operation */
- /* Change "none" selection to hyperslab selection */
- break;
+ case H5S_SELECT_OR:
+ case H5S_SELECT_XOR:
+ /* Add the new space to the space */
+ if(NULL == (new_spans = H5S__hyper_make_spans(old_space->extent.rank, start, stride, count, block)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't create hyperslab information")
+ if(NULL != old_space->select.sel_info.hslab->span_lst)
+ (*new_space)->select.sel_info.hslab->span_lst = H5S__hyper_copy_span(old_space->select.sel_info.hslab->span_lst, old_space->extent.rank);
+ if(H5S__hyper_add_disjoint_spans(*new_space, new_spans) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't append hyperslabs")
+
+ /* Build diminfo struct */
+ for(u = 0; u < (*new_space)->extent.rank; u++) {
+ new_hyper_diminfo[u].start = start[u];
+ new_hyper_diminfo[u].stride = stride[u];
+ new_hyper_diminfo[u].count = count[u];
+ new_hyper_diminfo[u].block = block[u];
+ } /* end for */
- case H5S_SELECT_OR: /* Binary "or" operation for hyperslabs */
- case H5S_SELECT_XOR: /* Binary "xor" operation for hyperslabs */
- case H5S_SELECT_NOTA: /* Binary "B not A" operation for hyperslabs */
- op=H5S_SELECT_SET; /* Maps to "set" operation when applied to "none" selection */
+ /* Update space's dim info */
+ if(H5S__hyper_update_diminfo(*new_space, op, new_hyper_diminfo) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOUNT, FAIL, "can't update hyperslab info")
break;
- case H5S_SELECT_AND: /* Binary "and" operation for hyperslabs */
- case H5S_SELECT_NOTB: /* Binary "A not B" operation for hyperslabs */
- HGOTO_DONE(SUCCEED); /* Selection stays "none" */
-
- default:
- HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation")
- } /* end switch */
- break;
-
- case H5S_SEL_ALL: /* All elements selected in dataspace */
- switch(op) {
- case H5S_SELECT_SET: /* Select "set" operation */
- /* Change "all" selection to hyperslab selection */
+ case H5S_SELECT_AND:
+ if(H5S_select_none((*new_space)) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't convert selection")
break;
- case H5S_SELECT_OR: /* Binary "or" operation for hyperslabs */
- HGOTO_DONE(SUCCEED); /* Selection stays "all" */
-
- case H5S_SELECT_AND: /* Binary "and" operation for hyperslabs */
- op=H5S_SELECT_SET; /* Maps to "set" operation when applied to "none" selection */
+ case H5S_SELECT_NOTB:
+ if(NULL != old_space->select.sel_info.hslab->span_lst) {
+ if(NULL == ((*new_space)->select.sel_info.hslab->span_lst = H5S__hyper_copy_span(old_space->select.sel_info.hslab->span_lst, old_space->extent.rank)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy dataspace")
+ } /* end if */
+ else {
+ if(H5S_select_none((*new_space)) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't convert selection")
+ } /* end else */
break;
- case H5S_SELECT_XOR: /* Binary "xor" operation for hyperslabs */
- case H5S_SELECT_NOTB: /* Binary "A not B" operation for hyperslabs */
- /* Convert current "all" selection to "real" hyperslab selection */
- /* Then allow operation to proceed */
- {
- hsize_t tmp_start[H5O_LAYOUT_NDIMS]; /* Temporary start information */
- hsize_t tmp_stride[H5O_LAYOUT_NDIMS]; /* Temporary stride information */
- hsize_t tmp_count[H5O_LAYOUT_NDIMS]; /* Temporary count information */
- hsize_t tmp_block[H5O_LAYOUT_NDIMS]; /* Temporary block information */
-
- /* Fill in temporary information for the dimensions */
- for(u=0; u<space->extent.rank; u++) {
- tmp_start[u]=0;
- tmp_stride[u]=1;
- tmp_count[u]=1;
- tmp_block[u]=space->extent.size[u];
- } /* end for */
-
- /* Convert to hyperslab selection */
- if(H5S_select_hyperslab(space,H5S_SELECT_SET,tmp_start,tmp_stride,tmp_count,tmp_block)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't convert selection")
- } /* end case */
+ case H5S_SELECT_NOTA:
+ if(H5S__set_regular_hyperslab(*new_space, start, stride, count, block, stride, count, block) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't set regular selection")
break;
- case H5S_SELECT_NOTA: /* Binary "B not A" operation for hyperslabs */
- /* Convert to "none" selection */
- if(H5S_select_none(space)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't convert selection")
- HGOTO_DONE(SUCCEED);
-
+ case H5S_SELECT_NOOP:
+ case H5S_SELECT_SET:
+ case H5S_SELECT_APPEND:
+ case H5S_SELECT_PREPEND:
+ case H5S_SELECT_INVALID:
default:
HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation")
} /* end switch */
- break;
-
- case H5S_SEL_HYPERSLABS:
- /* Hyperslab operation on hyperslab selection, OK */
- break;
-
- case H5S_SEL_POINTS: /* Can't combine hyperslab operations and point selections currently */
- if(op==H5S_SELECT_SET) /* Allow only "set" operation to proceed */
- break;
- /* Else fall through to error */
- default:
- HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation")
- } /* end switch */
-
-
- if(op==H5S_SELECT_SET) {
- /* If we are setting a new selection, remove current selection first */
- if(H5S_SELECT_RELEASE(space)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release hyperslab")
+ HGOTO_DONE(SUCCEED);
+ } /* end if(!overlapped) */
+ } /* end if the selection of old space is H5S_SEL_HYPERSLABS */
- /* Allocate space for the hyperslab selection information */
- if(NULL == (space->select.sel_info.hslab = H5FL_MALLOC(H5S_hyper_sel_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab info")
-
- /* Save the diminfo */
- space->select.num_elem=1;
- for(u=0; u<space->extent.rank; u++) {
- space->select.sel_info.hslab->app_diminfo[u].start = start[u];
- space->select.sel_info.hslab->app_diminfo[u].stride = stride[u];
- space->select.sel_info.hslab->app_diminfo[u].count = count[u];
- space->select.sel_info.hslab->app_diminfo[u].block = block[u];
-
- space->select.sel_info.hslab->opt_diminfo[u].start = start[u];
- space->select.sel_info.hslab->opt_diminfo[u].stride = opt_stride[u];
- space->select.sel_info.hslab->opt_diminfo[u].count = opt_count[u];
- space->select.sel_info.hslab->opt_diminfo[u].block = opt_block[u];
-
- space->select.num_elem*=(opt_count[u]*opt_block[u]);
- } /* end for */
-
- /* Save unlim_dim */
- space->select.sel_info.hslab->unlim_dim = unlim_dim;
-
- /* Indicate that the dimension information is valid */
- space->select.sel_info.hslab->diminfo_valid = TRUE;
+ /* Copy the first dataspace with sharing the list of spans */
+ if(NULL == ((*new_space) = H5S_copy(old_space, TRUE, TRUE)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to copy dataspace")
- /* Indicate that there's no slab information */
- space->select.sel_info.hslab->span_lst = NULL;
-
- /* Handle unlimited selections */
- if(unlim_dim >= 0) {
- /* Calculate num_elem_non_unlim */
- space->select.sel_info.hslab->num_elem_non_unlim = (hsize_t)1;
- for(u = 0; u < space->extent.rank; u++)
- if((int)u != unlim_dim)
- space->select.sel_info.hslab->num_elem_non_unlim *= (opt_count[u] * opt_block[u]);
+ /* Note: a little overhead in calling the function as some conditions are checked again */
+ if(H5S_select_hyperslab(*new_space, op, start, stride, count, block) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to set hyperslab selection")
- /* Set num_elem */
- if(space->select.num_elem != (hsize_t)0)
- space->select.num_elem = H5S_UNLIMITED;
- } /* end if */
- } /* end if */
- else if(op>=H5S_SELECT_OR && op<=H5S_SELECT_NOTA) {
- /* Sanity check */
- HDassert(H5S_GET_SELECT_TYPE(space) == H5S_SEL_HYPERSLABS);
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S_combine_hyperslab() */
- /* Handle unlimited selections */
- if(unlim_dim >= 0) {
- hsize_t bounds_start[H5S_MAX_RANK];
- hsize_t bounds_end[H5S_MAX_RANK];
- hsize_t tmp_count = opt_count[unlim_dim];
- hsize_t tmp_block = opt_block[unlim_dim];
- /* Check for invalid operation */
- if(space->select.sel_info.hslab->unlim_dim >= 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "cannot modify unlimited selection with another unlimited selection")
- if(!((op == H5S_SELECT_AND) || (op == H5S_SELECT_NOTB)))
- HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unsupported operation with unlimited selection")
+/*-------------------------------------------------------------------------
+ * Function: H5S__fill_in_select
+ *
+ * Purpose: Combines two hyperslabs with an operation, putting the
+ * result into a third hyperslab selection
+ *
+ * Return: Non-negative on success/negative on failure
+ *
+ * Programmer: Chao Mei
+ * Tuesday, July 5, 2011
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5S__fill_in_select(H5S_t *space1, H5S_seloper_t op, H5S_t *space2, H5S_t **result)
+{
+ hbool_t span2_owned;
+ hbool_t updated_spans;
+ herr_t ret_value = SUCCEED; /* Return value */
- /* Get bounds of existing selection */
- if(H5S_hyper_bounds(space, bounds_start, bounds_end) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get selection bounds")
+ FUNC_ENTER_STATIC
- /* Patch count and block to remove unlimited and include the
- * existing selection */
- H5S__hyper_get_clip_diminfo(start[unlim_dim], opt_stride[unlim_dim], &tmp_count, &tmp_block, bounds_end[unlim_dim] + (hsize_t)1);
- HDassert((tmp_count == 1) || (opt_count != H5S_hyper_ones_g));
- HDassert((tmp_block == 1) || (opt_block != H5S_hyper_ones_g));
- if(opt_count != H5S_hyper_ones_g) {
- HDassert(opt_count == int_count);
- int_count[unlim_dim] = tmp_count;
- } /* end if */
- if(opt_block != H5S_hyper_ones_g) {
- HDassert(opt_block == int_block);
- int_block[unlim_dim] = tmp_block;
- } /* end if */
+ /* Sanity check */
+ HDassert(space1);
+ HDassert(space2);
+ HDassert(op >= H5S_SELECT_OR && op <= H5S_SELECT_NOTA);
+ HDassert(space1->extent.rank == space2->extent.rank);
+ /* The result is either a to-be-created space or an empty one */
+ HDassert(NULL == *result || *result == space1);
+ HDassert(space1->select.sel_info.hslab->span_lst);
+ HDassert(space2->select.sel_info.hslab->span_lst);
+
+ /* Note: the offset of space2 is not considered here for bounding box */
+ if(H5S__fill_in_new_space(space1, op, space2->select.sel_info.hslab->span_lst, FALSE, &span2_owned, &updated_spans, result) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't create the specified selection")
+
+ /* Update diminfo if space2's diminfo was valid, otherwise just mark it as
+ * invalid if the spans were updated */
+ HDassert(result);
+ if(updated_spans) {
+ if(space2->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) {
+ if(H5S__hyper_update_diminfo(*result, op, space2->select.sel_info.hslab->diminfo.opt) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOUNT, FAIL, "can't update hyperslab info")
} /* end if */
-
- /* Check if there's no hyperslab span information currently */
- if(NULL == space->select.sel_info.hslab->span_lst)
- if(H5S__hyper_generate_spans(space) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "dataspace does not have span tree")
-
- /* Indicate that the regular dimensions are no longer valid */
- space->select.sel_info.hslab->diminfo_valid = FALSE;
-
- /* Add in the new hyperslab information */
- if(H5S__generate_hyperslab (space, op, start, opt_stride, opt_count, opt_block)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't generate hyperslabs")
+ else
+ (*result)->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_NO;
} /* end if */
- else
- HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation")
-
- /* Set selection type */
- space->select.type = H5S_sel_hyper;
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5S_select_hyperslab() */
-
-
-/*--------------------------------------------------------------------------
- NAME
- H5Sselect_hyperslab
- PURPOSE
- Specify a hyperslab to combine with the current hyperslab selection
- USAGE
- herr_t H5Sselect_hyperslab(dsid, op, start, stride, count, block)
- hid_t dsid; IN: Dataspace ID of selection to modify
- H5S_seloper_t op; IN: Operation to perform on current selection
- const hsize_t *start; IN: Offset of start of hyperslab
- const hsize_t *stride; IN: Hyperslab stride
- const hsize_t *count; IN: Number of blocks included in hyperslab
- const hsize_t *block; IN: Size of block in hyperslab
- RETURNS
- Non-negative on success/Negative on failure
- DESCRIPTION
- Combines a hyperslab selection with the current selection for a dataspace.
- If the current selection is not a hyperslab, it is freed and the hyperslab
- parameters passed in are combined with the H5S_SEL_ALL hyperslab (ie. a
- selection composing the entire current extent). If STRIDE or BLOCK is
- NULL, they are assumed to be set to all '1'.
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
-herr_t
-H5Sselect_hyperslab(hid_t space_id, H5S_seloper_t op, const hsize_t start[],
- const hsize_t stride[], const hsize_t count[], const hsize_t block[])
-{
- H5S_t *space = NULL; /* Dataspace to modify selection of */
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_API(FAIL)
- H5TRACE6("e", "iSs*h*h*h*h", space_id, op, start, stride, count, block);
-
- /* Check args */
- if (NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
- if (H5S_SCALAR==H5S_GET_EXTENT_TYPE(space))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "hyperslab doesn't support H5S_SCALAR space")
- if (H5S_NULL==H5S_GET_EXTENT_TYPE(space))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "hyperslab doesn't support H5S_NULL space")
- if(start==NULL || count==NULL)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "hyperslab not specified")
- if(!(op>H5S_SELECT_NOOP && op<H5S_SELECT_INVALID))
- HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation")
- if(stride!=NULL) {
- unsigned u; /* Local index variable */
+} /* end H5S__fill_in_select() */
- /* Check for 0-sized strides */
- for(u=0; u<space->extent.rank; u++) {
- if(stride[u]==0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid stride==0 value")
- } /* end for */
- } /* end if */
-
- if (H5S_select_hyperslab(space, op, start, stride, count, block)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to set hyperslab selection")
-
-done:
- FUNC_LEAVE_API(ret_value)
-} /* end H5Sselect_hyperslab() */
-
/*--------------------------------------------------------------------------
NAME
H5Scombine_hyperslab
@@ -7589,7 +10469,7 @@ done:
return a new dataspace with the combined selection as the selection in the
new dataspace.
USAGE
- hid_t H5Srefine_hyperslab(dsid, op, start, stride, count, block)
+ hid_t H5Scombine_hyperslab(dsid, op, start, stride, count, block)
hid_t dsid; IN: Dataspace ID of selection to use
H5S_seloper_t op; IN: Operation to perform on current selection
const hsize_t *start; IN: Offset of start of hyperslab
@@ -7597,7 +10477,7 @@ done:
const hsize_t *count; IN: Number of blocks included in hyperslab
const hsize_t *block; IN: Size of block in hyperslab
RETURNS
- Dataspace ID on success/Negative on failure
+ Dataspace ID on success / H5I_INVALID_HID on failure
DESCRIPTION
Combines a hyperslab selection with the current selection for a dataspace,
creating a new dataspace to return the generated selection.
@@ -7614,32 +10494,28 @@ hid_t
H5Scombine_hyperslab(hid_t space_id, H5S_seloper_t op, const hsize_t start[],
const hsize_t stride[], const hsize_t count[], const hsize_t block[])
{
- H5S_t *space; /* Dataspace to modify selection of */
- H5S_t *new_space = NULL; /* New dataspace created */
- hid_t ret_value; /* Return value */
+ H5S_t *space; /* Dataspace to modify selection of */
+ H5S_t *new_space = NULL; /* New dataspace created */
+ hid_t ret_value; /* Return value */
- FUNC_ENTER_API(FAIL)
+ FUNC_ENTER_API(H5I_INVALID_HID)
H5TRACE6("i", "iSs*h*h*h*h", space_id, op, start, stride, count, block);
/* Check args */
if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a dataspace")
if(start == NULL || count == NULL)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "hyperslab not specified")
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "hyperslab not specified")
if(!(op >= H5S_SELECT_SET && op <= H5S_SELECT_NOTA))
- HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation")
+ HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, H5I_INVALID_HID, "invalid selection operation")
- /* Copy the first dataspace */
- if (NULL == (new_space = H5S_copy (space, TRUE, TRUE)))
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, NULL, "unable to copy dataspace")
-
- /* Go modify the selection in the new dataspace */
- if (H5S_select_hyperslab(new_space, op, start, stride, count, block)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to set hyperslab selection")
+ /* Generate new space, with combination of selections */
+ if(H5S_combine_hyperslab(space, op, start, stride, count, block, &new_space) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, H5I_INVALID_HID, "unable to set hyperslab selection")
/* Atomize */
if((ret_value = H5I_register(H5I_DATASPACE, new_space, TRUE)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace atom")
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register dataspace atom")
done:
if(ret_value < 0 && new_space)
@@ -7648,28 +10524,24 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Scombine_hyperslab() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5S__combine_select
+ * Function: H5S__combine_select
*
- * Purpose: Internal version of H5Scombine_select().
+ * Purpose: Internal version of H5Scombine_select().
*
- * Return: New dataspace on success/NULL on failure
+ * Return: New dataspace on success/NULL on failure
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* Tuesday, October 30, 2001
*
- * Chao Mei
- * Wednesday, June 29, 2011
- *
*-------------------------------------------------------------------------
*/
static H5S_t *
H5S__combine_select(H5S_t *space1, H5S_seloper_t op, H5S_t *space2)
{
H5S_t *new_space = NULL; /* New dataspace generated */
- hbool_t span2_owned=FALSE; /* Flag to indicate that span2 was used in H5S_operate_hyperslab() */
- H5S_t *ret_value; /* return value */
+ H5S_t *ret_value = NULL; /* Return value */
FUNC_ENTER_STATIC
@@ -7678,33 +10550,38 @@ H5S__combine_select(H5S_t *space1, H5S_seloper_t op, H5S_t *space2)
HDassert(space2);
HDassert(op >= H5S_SELECT_OR && op <= H5S_SELECT_NOTA);
- /* Check that the space selections both have span trees */
- if(space1->select.sel_info.hslab->span_lst==NULL)
- if(H5S__hyper_generate_spans(space1)<0)
+ /* Check if space1 selections has span trees */
+ if(NULL == space1->select.sel_info.hslab->span_lst)
+ if(H5S__hyper_generate_spans(space1) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, NULL, "dataspace does not have span tree")
- if(space2->select.sel_info.hslab->span_lst==NULL)
- if(H5S__hyper_generate_spans(space2)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, NULL, "dataspace does not have span tree")
-
- /* Copy the first dataspace */
- if (NULL == (new_space = H5S_copy (space1, TRUE, TRUE)))
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, NULL, "unable to copy dataspace")
- /* Free the current selection for the new dataspace */
- if(H5S_SELECT_RELEASE(new_space)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, NULL, "can't release selection")
+ if(NULL == space2->select.sel_info.hslab->span_lst) {
+ hsize_t tmp_start[H5S_MAX_RANK];
+ hsize_t tmp_stride[H5S_MAX_RANK];
+ hsize_t tmp_count[H5S_MAX_RANK];
+ hsize_t tmp_block[H5S_MAX_RANK];
+ unsigned u;
+
+ for(u = 0; u < space2->extent.rank; u++) {
+ tmp_start[u] = space2->select.sel_info.hslab->diminfo.opt[u].start;
+ tmp_stride[u] = space2->select.sel_info.hslab->diminfo.opt[u].stride;
+ tmp_count[u] = space2->select.sel_info.hslab->diminfo.opt[u].count;
+ tmp_block[u] = space2->select.sel_info.hslab->diminfo.opt[u].block;
+ } /* end for */
- /* Allocate space for the hyperslab selection information */
- if((new_space->select.sel_info.hslab=H5FL_CALLOC(H5S_hyper_sel_t))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate hyperslab info")
+ /* Combine hyperslab selection with regular selection directly */
+ if(H5S_combine_hyperslab(space1, op, tmp_start, tmp_stride, tmp_count, tmp_block, &new_space) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, NULL, "unable to set hyperslab selection")
+ } /* end if */
+ else{
+ /* Combine new_space (a copy of space 1) & space2, with the result in new_space */
+ if(H5S__fill_in_select(space1, op, space2, &new_space) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, NULL, "can't clip hyperslab information")
+ } /* end else */
/* Set unlim_dim */
new_space->select.sel_info.hslab->unlim_dim = -1;
- /* Combine space1 & space2, with the result in new_space */
- if(H5S_operate_hyperslab(new_space,space1->select.sel_info.hslab->span_lst,op,space2->select.sel_info.hslab->span_lst,FALSE,&span2_owned)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, NULL, "can't clip hyperslab information")
-
/* Set return value */
ret_value = new_space;
@@ -7715,7 +10592,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S__combine_select() */
-
+
/*--------------------------------------------------------------------------
NAME
H5Scombine_select
@@ -7728,7 +10605,7 @@ done:
H5S_seloper_t op; IN: Selection operation
hid_t space2; IN: Second Dataspace ID
RETURNS
- Dataspace ID on success/Negative on failure
+ Dataspace ID on success / H5I_INVALID_HID on failure
DESCRIPTION
Combine two existing hyperslab selections with an operation, returning
a new dataspace with the resulting selection. The dataspace extent from
@@ -7741,37 +10618,47 @@ done:
hid_t
H5Scombine_select(hid_t space1_id, H5S_seloper_t op, hid_t space2_id)
{
- H5S_t *space1; /* First Dataspace */
- H5S_t *space2; /* Second Dataspace */
- H5S_t *new_space = NULL; /* New Dataspace */
- hid_t ret_value; /* Return value */
+ H5S_t *space1; /* First Dataspace */
+ H5S_t *space2; /* Second Dataspace */
+ H5S_t *new_space = NULL; /* New Dataspace */
+ hid_t ret_value; /* Return value */
- FUNC_ENTER_API(FAIL)
+ FUNC_ENTER_API(H5I_INVALID_HID)
H5TRACE3("i", "iSsi", space1_id, op, space2_id);
/* Check args */
if(NULL == (space1 = (H5S_t *)H5I_object_verify(space1_id, H5I_DATASPACE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a dataspace")
if(NULL == (space2 = (H5S_t *)H5I_object_verify(space2_id, H5I_DATASPACE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a dataspace")
if(!(op >= H5S_SELECT_OR && op <= H5S_SELECT_NOTA))
- HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation")
+ HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, H5I_INVALID_HID, "invalid selection operation")
/* Check that both dataspaces have the same rank */
if(space1->extent.rank != space2->extent.rank)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dataspaces not same rank")
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "dataspaces not same rank")
+
+ /* Note: currently, the offset of each dataspace is ignored */
+#if 0
+ /* Check that both dataspaces have the same offset */
+ /* Same note as in H5Smodify_select */
+ for(u=0; u<space1->extent.rank; u++) {
+ if(space1->select.offset[u] != space2->select.offset[u])
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "dataspaces not same offset")
+ } /* end for */
+#endif
/* Check that both dataspaces have hyperslab selections */
if(H5S_GET_SELECT_TYPE(space1) != H5S_SEL_HYPERSLABS || H5S_GET_SELECT_TYPE(space2) != H5S_SEL_HYPERSLABS)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dataspaces don't have hyperslab selections")
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "dataspaces don't have hyperslab selections")
/* Go combine the dataspaces */
if(NULL == (new_space = H5S__combine_select(space1, op, space2)))
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to create hyperslab selection")
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, H5I_INVALID_HID, "unable to create hyperslab selection")
/* Atomize */
if((ret_value = H5I_register(H5I_DATASPACE, new_space, TRUE)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace atom")
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register dataspace atom")
done:
if(ret_value < 0 && new_space)
@@ -7780,79 +10667,75 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Scombine_select() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5S_select_select
+ * Function: H5S__modify_select
*
- * Purpose: Internal version of H5Sselect_select().
+ * Purpose: Internal version of H5Smodify_select().
*
- * Return: New dataspace on success/NULL on failure
+ * Return: New dataspace on success/NULL on failure
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* Tuesday, October 30, 2001
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
-static herr_t
-H5S_select_select (H5S_t *space1, H5S_seloper_t op, H5S_t *space2)
+herr_t
+H5S__modify_select(H5S_t *space1, H5S_seloper_t op, H5S_t *space2)
{
- H5S_hyper_span_info_t *tmp_spans=NULL; /* Temporary copy of selection */
- hbool_t span2_owned=FALSE; /* Flag to indicate that span2 was used in H5S_operate_hyperslab() */
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_PACKAGE
/* Check args */
HDassert(space1);
HDassert(space2);
- HDassert(op > H5S_SELECT_NOOP && op < H5S_SELECT_INVALID);
+ HDassert(op >= H5S_SELECT_OR && op <= H5S_SELECT_NOTA);
/* Check that the space selections both have span trees */
- if(space1->select.sel_info.hslab->span_lst==NULL)
- if(H5S__hyper_generate_spans(space1)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "dataspace does not have span tree")
- if(space2->select.sel_info.hslab->span_lst==NULL)
- if(H5S__hyper_generate_spans(space2)<0)
+ if(NULL == space1->select.sel_info.hslab->span_lst)
+ if(H5S__hyper_generate_spans(space1) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "dataspace does not have span tree")
- /* Take ownership of the dataspace's hyperslab spans */
- /* (These are freed later) */
- tmp_spans=space1->select.sel_info.hslab->span_lst;
- space1->select.sel_info.hslab->span_lst=NULL;
-
- /* Reset the other dataspace selection information */
- if(H5S_SELECT_RELEASE(space1)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release selection")
-
- /* Allocate space for the hyperslab selection information */
- if((space1->select.sel_info.hslab=H5FL_CALLOC(H5S_hyper_sel_t))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab info")
-
/* Set unlim_dim */
space1->select.sel_info.hslab->unlim_dim = -1;
- /* Combine tmp_spans (from space1) & spans from space2, with the result in space1 */
- if(H5S_operate_hyperslab(space1,tmp_spans,op,space2->select.sel_info.hslab->span_lst,FALSE,&span2_owned)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL, "can't clip hyperslab information")
+ if(NULL == space2->select.sel_info.hslab->span_lst) {
+ hsize_t tmp_start[H5S_MAX_RANK];
+ hsize_t tmp_stride[H5S_MAX_RANK];
+ hsize_t tmp_count[H5S_MAX_RANK];
+ hsize_t tmp_block[H5S_MAX_RANK];
+ unsigned u;
+
+ for(u = 0; u < space2->extent.rank; u++) {
+ tmp_start[u] = space2->select.sel_info.hslab->diminfo.opt[u].start;
+ tmp_stride[u] = space2->select.sel_info.hslab->diminfo.opt[u].stride;
+ tmp_count[u] = space2->select.sel_info.hslab->diminfo.opt[u].count;
+ tmp_block[u] = space2->select.sel_info.hslab->diminfo.opt[u].block;
+ } /* end for */
-done:
- if(tmp_spans!=NULL)
- H5S__hyper_free_span_info(tmp_spans);
+ /* Call H5S_select_hyperslab directly */
+ if(H5S_select_hyperslab(space1, op, tmp_start, tmp_stride, tmp_count, tmp_block) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to set hyperslab selection")
+ } /* end if */
+ else
+ /* Combine spans from space1 & spans from space2, with the result in space1 */
+ if(H5S__fill_in_select(space1, op, space2, &space1) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL, "can't perform operation on two selections")
+done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5S_select_select() */
+} /* end H5S__modify_select() */
+
-
/*--------------------------------------------------------------------------
NAME
- H5Sselect_select
+ H5Smodify_select
PURPOSE
Refine a hyperslab selection with an operation using a second hyperslab
- to modify it.
+ to modify it
USAGE
- herr_t H5Sselect_select(space1, op, space2)
+ herr_t H5Smodify_select(space1, op, space2)
hid_t space1; IN/OUT: First Dataspace ID
H5S_seloper_t op; IN: Selection operation
hid_t space2; IN: Second Dataspace ID
@@ -7868,10 +10751,10 @@ done:
REVISION LOG
--------------------------------------------------------------------------*/
herr_t
-H5Sselect_select(hid_t space1_id, H5S_seloper_t op, hid_t space2_id)
+H5Smodify_select(hid_t space1_id, H5S_seloper_t op, hid_t space2_id)
{
- H5S_t *space1; /* First Dataspace */
- H5S_t *space2; /* Second Dataspace */
+ H5S_t *space1; /* First Dataspace */
+ H5S_t *space2; /* Second Dataspace */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -7889,1350 +10772,617 @@ H5Sselect_select(hid_t space1_id, H5S_seloper_t op, hid_t space2_id)
if(space1->extent.rank != space2->extent.rank)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dataspaces not same rank")
+ /* Check that both dataspaces have the same offset */
+ /** Note that this is a tricky part of this function. It's
+ * possible that two dataspaces have different "offset". If the
+ * space2 has smaller offset value than that of space1 in a
+ * dimension, then the span elements of this dimension in
+ * space2 could have negative "low" and "high" values relative
+ * to the offset in space1. In other words, if the bounds of
+ * span elements in space2 are adjusted relative to the offset
+ * in space1, then every span element's bound is computed as
+ * "origin_bound+offset2-offset1". Therefore, if offset2 (the
+ * offset of space2) is smaller, then
+ * "origin_bound+offset2-offset1" could be negative which is
+ * not allowed by the bound type declaration as hsize_t!
+ * As a result, if the op is an OR selection, then the final
+ * result may contain span elements that have negative bound!
+ * So right now, the difference in the offset is totally
+ * ignored!!
+ */
+#if 0
+ for(u=0; u<space1->extent.rank; u++) {
+ if(space1->select.offset[u] != space2->select.offset[u])
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dataspaces not same offset")
+ } /* end for */
+#endif
+
/* Check that both dataspaces have hyperslab selections */
if(H5S_GET_SELECT_TYPE(space1) != H5S_SEL_HYPERSLABS || H5S_GET_SELECT_TYPE(space2) != H5S_SEL_HYPERSLABS)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dataspaces don't have hyperslab selections")
/* Go refine the first selection */
- if (H5S_select_select(space1, op, space2)<0)
+ if(H5S__modify_select(space1, op, space2) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to modify hyperslab selection")
done:
FUNC_LEAVE_API(ret_value)
-} /* end H5Sselect_select() */
-#endif /* NEW_HYPERSLAB_API */ /* Works */
+} /* end H5Smodify_select() */
+
-
/*--------------------------------------------------------------------------
NAME
- H5S__hyper_get_seq_list_gen
+ H5S__hyper_proj_int_build_proj
PURPOSE
- Create a list of offsets & lengths for a selection
+ Secondary iteration routine for H5S__hyper_project_intersection
USAGE
- herr_t H5S_select_hyper_get_file_list_gen(space,iter,maxseq,maxelem,nseq,nelem,off,len)
- H5S_t *space; IN: Dataspace containing selection to use.
- H5S_sel_iter_t *iter; IN/OUT: Selection iterator describing last
- position of interest in selection.
- size_t maxseq; IN: Maximum number of sequences to generate
- size_t maxelem; IN: Maximum number of elements to include in the
- generated sequences
- size_t *nseq; OUT: Actual number of sequences generated
- size_t *nelem; OUT: Actual number of elements in sequences generated
- hsize_t *off; OUT: Array of offsets
- size_t *len; OUT: Array of lengths
+ herr_t H5S__hyper_proj_int_build_proj(udata)
+ H5S_hyper_project_intersect_ud_t *udata; IN/OUT: Persistent shared data for iteration
RETURNS
Non-negative on success/Negative on failure.
DESCRIPTION
- Use the selection in the dataspace to generate a list of byte offsets and
- lengths for the region(s) selected. Start/Restart from the position in the
- ITER parameter. The number of sequences generated is limited by the MAXSEQ
- parameter and the number of sequences actually generated is stored in the
- NSEQ parameter.
+ Takes the skip and nelem amounts listed in udata and converts them to
+ span trees in the projected space, using the destination space. This
+ is a non-recursive algorithm by necessity, it saves the current state
+ of iteration in udata and resumes in the same location on subsequent
+ calls.
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S__hyper_get_seq_list_gen(const H5S_t *space, H5S_sel_iter_t *iter,
- size_t maxseq, size_t maxelem, size_t *nseq, size_t *nelem,
- hsize_t *off, size_t *len)
-{
- H5S_hyper_span_t *curr_span; /* Current hyperslab span node */
- H5S_hyper_span_t **ispan; /* Iterator's hyperslab span nodes */
- hsize_t slab[H5O_LAYOUT_NDIMS]; /* Cumulative size of each dimension in bytes */
- hsize_t acc; /* Accumulator for computing cumulative sizes */
- hsize_t loc_off; /* Element offset in the dataspace */
- hsize_t last_span_end = 0; /* The offset of the end of the last span */
- hsize_t *abs_arr; /* Absolute hyperslab span position */
- const hssize_t *off_arr; /* Offset within the dataspace extent */
- size_t span_size = 0; /* Number of bytes in current span to actually process */
- size_t io_left; /* Number of elements left to process */
- size_t io_bytes_left; /* Number of bytes left to process */
- size_t io_used; /* Number of elements processed */
- size_t curr_seq = 0; /* Number of sequence/offsets stored in the arrays */
- size_t elem_size; /* Size of each element iterating over */
- unsigned ndims; /* Number of dimensions of dataset */
- unsigned fast_dim; /* Rank of the fastest changing dimension for the dataspace */
- int curr_dim; /* Current dimension being operated on */
- unsigned u; /* Index variable */
- int i; /* Index variable */
-
- FUNC_ENTER_STATIC_NOERR
-
- /* Check args */
- HDassert(space);
- HDassert(iter);
- HDassert(maxseq > 0);
- HDassert(maxelem > 0);
- HDassert(nseq);
- HDassert(nelem);
- HDassert(off);
- HDassert(len);
-
- /* Set the rank of the fastest changing dimension */
- ndims = space->extent.rank;
- fast_dim = (ndims - 1);
-
- /* Get the pointers to the current span info and span nodes */
- curr_span = iter->u.hyp.span[fast_dim];
- abs_arr = iter->u.hyp.off;
- off_arr = space->select.offset;
- ispan = iter->u.hyp.span;
- elem_size = iter->elmt_size;
-
- /* Set the amount of elements to perform I/O on, etc. */
- H5_CHECK_OVERFLOW(iter->elmt_left, hsize_t, size_t);
- io_left = MIN(maxelem, (size_t)iter->elmt_left);
- io_bytes_left = io_left * elem_size;
-
- /* Compute the cumulative size of dataspace dimensions */
- for(i = (int)fast_dim, acc = elem_size; i >= 0; i--) {
- slab[i] = acc;
- acc *= space->extent.size[i];
- } /* end for */
-
- /* Set the offset of the first element iterated on */
- for(u = 0, loc_off = 0; u < ndims; u++)
- /* Compute the sequential element offset */
- loc_off += ((hsize_t)((hssize_t)abs_arr[u] + off_arr[u])) * slab[u];
-
- /* Range check against number of elements left in selection */
- HDassert(io_bytes_left <= (iter->elmt_left * elem_size));
-
- /* Take care of any partial spans leftover from previous I/Os */
- if(abs_arr[fast_dim]!=curr_span->low) {
-
- /* Finish the span in the fastest changing dimension */
-
- /* Compute the number of bytes to attempt in this span */
- H5_CHECKED_ASSIGN(span_size, size_t, ((curr_span->high-abs_arr[fast_dim])+1)*elem_size, hsize_t);
-
- /* Check number of bytes against upper bounds allowed */
- if(span_size>io_bytes_left)
- span_size=io_bytes_left;
-
- /* Add the partial span to the list of sequences */
- off[curr_seq]=loc_off;
- len[curr_seq]=span_size;
-
- /* Increment sequence count */
- curr_seq++;
-
- /* Set the location of the last span's end */
- last_span_end=loc_off+span_size;
+H5S__hyper_proj_int_build_proj(H5S_hyper_project_intersect_ud_t *udata) {
+ herr_t ret_value = SUCCEED; /* Return value */
- /* Decrement I/O left to perform */
- io_bytes_left-=span_size;
+ FUNC_ENTER_STATIC
- /* Advance the hyperslab iterator */
- /* Check if we are done */
- if(io_bytes_left > 0) {
- /* Move to next span in fastest changing dimension */
- curr_span = curr_span->next;
+ HDassert(udata->nelem > 0);
- if(NULL != curr_span) {
- /* Move location offset of destination */
- loc_off += (curr_span->low - abs_arr[fast_dim]) * elem_size;
-
- /* Move iterator for fastest changing dimension */
- abs_arr[fast_dim] = curr_span->low;
- } /* end if */
- } /* end if */
- else {
- abs_arr[fast_dim] += span_size / elem_size;
+ /*
+ * Skip over skipped elements
+ */
+ if(udata->skip > 0) {
+ /* Work upwards, finishing each span tree before moving up */
+ HDassert(udata->ds_span[udata->depth]);
+ do {
+ /* Check for lowest dimension */
+ if(udata->ds_span[udata->depth]->down) {
+ if(udata->ds_low[udata->depth] <= udata->ds_span[udata->depth]->high) {
+ /* If we will run out of elements to skip in this span,
+ * advance to the first not fully skipped span and break
+ * out of this loop (start moving downwards) */
+ if(udata->skip < H5S__hyper_spans_nelem_helper(udata->ds_span[udata->depth]->down, udata->op_gen)
+ * (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1)) {
+ udata->ds_low[udata->depth] += udata->skip / udata->ds_span[udata->depth]->down->u.nelmts;
+ udata->skip %= udata->ds_span[udata->depth]->down->u.nelmts;
+ break;
+ } /* end if */
- /* Check if we are still within the span */
- if(abs_arr[fast_dim] <= curr_span->high) {
- iter->u.hyp.span[fast_dim] = curr_span;
+ /* Skip over this entire span */
+ udata->skip -= udata->ds_span[udata->depth]->down->u.nelmts
+ * (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1);
+ } /* end if */
} /* end if */
- /* If we walked off that span, advance to the next span */
else {
- /* Advance span in this dimension */
- curr_span = curr_span->next;
-
- /* Check if we have a valid span in this dimension still */
- if(NULL != curr_span) {
- /* Reset absolute position */
- abs_arr[fast_dim] = curr_span->low;
- iter->u.hyp.span[fast_dim] = curr_span;
- } /* end if */
- } /* end else */
- } /* end else */
-
- /* Adjust iterator pointers */
-
- if(NULL == curr_span) {
-/* Same as code in main loop */
- /* Start at the next fastest dim */
- curr_dim = (int)(fast_dim - 1);
-
- /* Work back up through the dimensions */
- while(curr_dim >= 0) {
- /* Reset the current span */
- curr_span = iter->u.hyp.span[curr_dim];
-
- /* Increment absolute position */
- abs_arr[curr_dim]++;
-
- /* Check if we are still within the span */
- if(abs_arr[curr_dim] <= curr_span->high) {
+ HDassert(udata->ds_rank - udata->depth == 1);
+
+ /* If we will run out of elements to skip in this span,
+ * skip the remainder of the skipped elements and break out */
+ HDassert(udata->ds_low[udata->depth] <= udata->ds_span[udata->depth]->high);
+ if(udata->skip < (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1)) {
+ udata->ds_low[udata->depth] += udata->skip;
+ udata->skip = 0;
break;
} /* end if */
- /* If we walked off that span, advance to the next span */
- else {
- /* Advance span in this dimension */
- curr_span = curr_span->next;
- /* Check if we have a valid span in this dimension still */
- if(NULL != curr_span) {
- /* Reset the span in the current dimension */
- ispan[curr_dim] = curr_span;
+ /* Skip over this entire span */
+ udata->skip -= udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1;
+ } /* end else */
- /* Reset absolute position */
- abs_arr[curr_dim] = curr_span->low;
+ /* Advance to next span */
+ udata->ds_span[udata->depth] = udata->ds_span[udata->depth]->next;
+ if(udata->ds_span[udata->depth])
+ udata->ds_low[udata->depth] = udata->ds_span[udata->depth]->low;
+ else if(udata->depth > 0) {
+ /* If present, append this span tree to the higher dimension's,
+ * and release ownership of it */
+ if(udata->ps_span_info[udata->depth]) {
+ if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth - 1],
+ udata->ds_rank - udata->depth + 1, udata->ds_low[udata->depth - 1],
+ udata->ds_low[udata->depth - 1],
+ udata->ps_span_info[udata->depth]) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+ H5S__hyper_free_span_info(udata->ps_span_info[udata->depth]);
+ udata->ps_span_info[udata->depth] = NULL;
+ } /* end if */
+ /* Ran out of spans, move up one dimension */
+ udata->depth--;
+ HDassert(udata->ds_span[udata->depth]);
+ udata->ds_low[udata->depth]++;
+ } /* end if */
+ else
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "insufficient elements in destination selection")
+ } while((udata->skip > 0)
+ || (udata->ds_low[udata->depth] > udata->ds_span[udata->depth]->high));
+
+ /* Work downwards until skip is 0 */
+ HDassert(udata->ds_span[udata->depth]);
+ while(udata->skip > 0) {
+ HDassert(udata->ds_span[udata->depth]->down);
+ udata->depth++;
+ udata->ds_span[udata->depth] = udata->ds_span[udata->depth - 1]->down->head;
+ udata->ds_low[udata->depth] = udata->ds_span[udata->depth]->low;
+ if(udata->ds_span[udata->depth]->down) {
+ do {
+ /* If we will run out of elements to skip in this span,
+ * advance to the first not fully skipped span and
+ * continue down */
+ if(udata->skip < H5S__hyper_spans_nelem_helper(udata->ds_span[udata->depth]->down, udata->op_gen)
+ * (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1)) {
+ udata->ds_low[udata->depth] += udata->skip / udata->ds_span[udata->depth]->down->u.nelmts;
+ udata->skip %= udata->ds_span[udata->depth]->down->u.nelmts;
break;
} /* end if */
- else {
- /* If we finished the span list in this dimension, decrement the dimension worked on and loop again */
- curr_dim--;
- } /* end else */
- } /* end else */
- } /* end while */
-
- /* Check if we have more spans in the tree */
- if(curr_dim >= 0) {
- /* Walk back down the iterator positions, resetting them */
- while((unsigned)curr_dim < fast_dim) {
- HDassert(curr_span);
- HDassert(curr_span->down);
- HDassert(curr_span->down->head);
-
- /* Increment current dimension */
- curr_dim++;
-
- /* Set the new span_info & span for this dimension */
- iter->u.hyp.span[curr_dim] = curr_span->down->head;
-
- /* Advance span down the tree */
- curr_span = curr_span->down->head;
-
- /* Reset the absolute offset for the dim */
- abs_arr[curr_dim] = curr_span->low;
- } /* end while */
-
- /* Verify that the curr_span points to the fastest dim */
- HDassert(curr_span == iter->u.hyp.span[fast_dim]);
-
- /* Reset the buffer offset */
- for(u = 0, loc_off = 0; u < ndims; u++)
- loc_off += ((hsize_t)((hssize_t)abs_arr[u] + off_arr[u])) * slab[u];
- } /* end else */
- else
- /* We had better be done with I/O or bad things are going to happen... */
- HDassert(io_bytes_left == 0);
- } /* end if */
- } /* end if */
-
- /* Perform the I/O on the elements, based on the position of the iterator */
- while(io_bytes_left > 0 && curr_seq < maxseq) {
- /* Sanity check */
- HDassert(curr_span);
-
- /* Adjust location offset of destination to compensate for initial increment below */
- loc_off -= curr_span->pstride;
-
- /* Loop over all the spans in the fastest changing dimension */
- while(curr_span != NULL) {
- /* Move location offset of destination */
- loc_off += curr_span->pstride;
-
- /* Compute the number of elements to attempt in this span */
- H5_CHECKED_ASSIGN(span_size, size_t, curr_span->nelem, hsize_t);
-
- /* Check number of elements against upper bounds allowed */
- if(span_size >= io_bytes_left) {
- /* Trim the number of bytes to output */
- span_size = io_bytes_left;
- io_bytes_left = 0;
-
-/* COMMON */
- /* Store the I/O information for the span */
-
- /* Check if this is appending onto previous sequence */
- if(curr_seq > 0 && last_span_end == loc_off)
- len[curr_seq - 1] += span_size;
- else {
- off[curr_seq] = loc_off;
- len[curr_seq] = span_size;
-
- /* Increment the number of sequences in arrays */
- curr_seq++;
- } /* end else */
- /* Set the location of the last span's end */
- last_span_end = loc_off + span_size;
-/* end COMMON */
+ /* Skip over this entire span */
+ udata->skip -= udata->ds_span[udata->depth]->down->u.nelmts
+ * (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1);
- /* Break out now, we are finished with I/O */
- break;
+ /* Advance to next span */
+ udata->ds_span[udata->depth] = udata->ds_span[udata->depth]->next;
+ HDassert(udata->ds_span[udata->depth]);
+ udata->ds_low[udata->depth] = udata->ds_span[udata->depth]->low;
+ } while(udata->skip > 0);
} /* end if */
else {
- /* Decrement I/O left to perform */
- io_bytes_left -= span_size;
-
-/* COMMON */
- /* Store the I/O information for the span */
-
- /* Check if this is appending onto previous sequence */
- if(curr_seq > 0 && last_span_end == loc_off)
- len[curr_seq-1]+=span_size;
- else {
- off[curr_seq] = loc_off;
- len[curr_seq] = span_size;
-
- /* Increment the number of sequences in arrays */
- curr_seq++;
- } /* end else */
+ do {
+ /* If we will run out of elements to skip in this span,
+ * skip the remainder of the skipped elements */
+ if(udata->skip < (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1)) {
+ udata->ds_low[udata->depth] += udata->skip;
+ udata->skip = 0;
+ break;
+ } /* end if */
- /* Set the location of the last span's end */
- last_span_end = loc_off + span_size;
-/* end COMMON */
+ /* Skip over this entire span */
+ udata->skip -= udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1;
- /* If the sequence & offset arrays are full, do what? */
- if(curr_seq >= maxseq) {
- /* Break out now, we are finished with sequences */
- break;
- } /* end else */
+ /* Advance to next span */
+ udata->ds_span[udata->depth] = udata->ds_span[udata->depth]->next;
+ HDassert(udata->ds_span[udata->depth]);
+ udata->ds_low[udata->depth] = udata->ds_span[udata->depth]->low;
+ } while(udata->skip > 0);
} /* end else */
-
- /* Move to next span in fastest changing dimension */
- curr_span=curr_span->next;
} /* end while */
+ } /* end if */
- /* Check if we are done */
- if(io_bytes_left==0 || curr_seq>=maxseq) {
- HDassert(curr_span);
- abs_arr[fast_dim]=curr_span->low+(span_size/elem_size);
-
- /* Check if we are still within the span */
- if(abs_arr[fast_dim]<=curr_span->high) {
- iter->u.hyp.span[fast_dim]=curr_span;
- break;
- } /* end if */
- /* If we walked off that span, advance to the next span */
- else {
- /* Advance span in this dimension */
- curr_span=curr_span->next;
-
- /* Check if we have a valid span in this dimension still */
- if(curr_span!=NULL) {
- /* Reset absolute position */
- abs_arr[fast_dim]=curr_span->low;
- iter->u.hyp.span[fast_dim]=curr_span;
+ /*
+ * Add requested number of elements to projected space
+ */
+ /* Work upwards, adding all elements of each span tree until it can't fit
+ * all elements */
+ HDassert(udata->ds_span[udata->depth]);
+ do {
+ /* Check for lowest dimension */
+ if(udata->ds_span[udata->depth]->down) {
+ if(udata->ds_low[udata->depth] <= udata->ds_span[udata->depth]->high) {
+ /* If we will run out of elements to add in this span, add
+ * any complete spans, advance to the first not fully added
+ * span, and break out of this loop (start moving downwards)
+ */
+ if(udata->nelem < H5S__hyper_spans_nelem_helper(udata->ds_span[udata->depth]->down, udata->op_gen)
+ * (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1)) {
+ if(udata->nelem >= udata->ds_span[udata->depth]->down->u.nelmts) {
+ if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth],
+ udata->ds_rank - udata->depth, udata->ds_low[udata->depth],
+ udata->ds_low[udata->depth] + (udata->nelem / udata->ds_span[udata->depth]->down->u.nelmts) - 1,
+ udata->ds_span[udata->depth]->down) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+ udata->ds_low[udata->depth] += udata->nelem / udata->ds_span[udata->depth]->down->u.nelmts;
+ udata->nelem %= udata->ds_span[udata->depth]->down->u.nelmts;
+ } /* end if */
break;
} /* end if */
- } /* end else */
- } /* end if */
-
- /* Adjust iterator pointers */
-
- /* Start at the next fastest dim */
- curr_dim = (int)(fast_dim - 1);
-
- /* Work back up through the dimensions */
- while(curr_dim >= 0) {
- /* Reset the current span */
- curr_span=iter->u.hyp.span[curr_dim];
-
- /* Increment absolute position */
- abs_arr[curr_dim]++;
- /* Check if we are still within the span */
- if(abs_arr[curr_dim]<=curr_span->high) {
+ /* Append span tree for entire span */
+ if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth],
+ udata->ds_rank - udata->depth, udata->ds_low[udata->depth],
+ udata->ds_span[udata->depth]->high,
+ udata->ds_span[udata->depth]->down) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+ udata->nelem -= udata->ds_span[udata->depth]->down->u.nelmts
+ * (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1);
+ } /* end if */
+ } /* end if */
+ else {
+ HDassert(udata->ds_rank - udata->depth == 1);
+
+ /* If we will run out of elements to add in this span, add the
+ * remainder of the elements and break out */
+ HDassert(udata->ds_low[udata->depth] <= udata->ds_span[udata->depth]->high);
+ if(udata->nelem < (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1)) {
+ if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth], 1,
+ udata->ds_low[udata->depth], udata->ds_low[udata->depth] + udata->nelem - 1, NULL) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+ udata->ds_low[udata->depth] += udata->nelem;
+ udata->nelem = 0;
break;
} /* end if */
- /* If we walked off that span, advance to the next span */
- else {
- /* Advance span in this dimension */
- curr_span=curr_span->next;
- /* Check if we have a valid span in this dimension still */
- if(curr_span!=NULL) {
- /* Reset the span in the current dimension */
- ispan[curr_dim]=curr_span;
+ /* Append span tree for entire span */
+ if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth], 1,
+ udata->ds_low[udata->depth], udata->ds_span[udata->depth]->high, NULL) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+ udata->nelem -= udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1;
+ } /* end else */
- /* Reset absolute position */
- abs_arr[curr_dim]=curr_span->low;
+ /* Advance to next span */
+ udata->ds_span[udata->depth] = udata->ds_span[udata->depth]->next;
+ if(udata->ds_span[udata->depth])
+ udata->ds_low[udata->depth] = udata->ds_span[udata->depth]->low;
+ else if(udata->depth > 0) {
+ /* Append this span tree to the higher dimension's, and release
+ * ownership of it */
+ HDassert(udata->ps_span_info[udata->depth]);
+ if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth - 1],
+ udata->ds_rank - udata->depth + 1, udata->ds_low[udata->depth - 1],
+ udata->ds_low[udata->depth - 1],
+ udata->ps_span_info[udata->depth]) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+ H5S__hyper_free_span_info(udata->ps_span_info[udata->depth]);
+ udata->ps_span_info[udata->depth] = NULL;
+ /* Ran out of spans, move up one dimension */
+ udata->depth--;
+ HDassert(udata->ds_span[udata->depth]);
+ udata->ds_low[udata->depth]++;
+ } /* end if */
+ else {
+ /* We have finished the entire destination span tree. If there are
+ * still elements to add, issue an error. */
+ if(udata->nelem > 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "insufficient elements in destination selection")
+ break;
+ } /* end else */
+ } while((udata->nelem > 0)
+ || (udata->ds_low[udata->depth] > udata->ds_span[udata->depth]->high));
+
+ /* Work downwards until nelem is 0 */
+ HDassert(udata->ds_span[udata->depth] || (udata->nelem == 0));
+ while(udata->nelem > 0) {
+ HDassert(udata->ds_span[udata->depth]->down);
+ udata->depth++;
+ udata->ds_span[udata->depth] = udata->ds_span[udata->depth - 1]->down->head;
+ udata->ds_low[udata->depth] = udata->ds_span[udata->depth]->low;
+ if(udata->ds_span[udata->depth]->down) {
+ do {
+ /* If we will run out of elements to add in this span, add
+ * any complete spans, advance to the first not fully added
+ * span and continue down
+ */
+ HDassert(udata->ds_low[udata->depth] <= udata->ds_span[udata->depth]->high);
+ if(udata->nelem < H5S__hyper_spans_nelem_helper(udata->ds_span[udata->depth]->down, udata->op_gen)
+ * (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1)) {
+ if(udata->nelem >= udata->ds_span[udata->depth]->down->u.nelmts) {
+ if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth],
+ udata->ds_rank - udata->depth, udata->ds_low[udata->depth],
+ udata->ds_low[udata->depth] + (udata->nelem / udata->ds_span[udata->depth]->down->u.nelmts) - 1,
+ udata->ds_span[udata->depth]->down) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+ udata->ds_low[udata->depth] += udata->nelem / udata->ds_span[udata->depth]->down->u.nelmts;
+ udata->nelem %= udata->ds_span[udata->depth]->down->u.nelmts;
+ } /* end if */
break;
} /* end if */
- else {
- /* If we finished the span list in this dimension, decrement the dimension worked on and loop again */
- curr_dim--;
- } /* end else */
- } /* end else */
- } /* end while */
- /* Check if we are finished with the spans in the tree */
- if(curr_dim < 0) {
- /* We had better be done with I/O or bad things are going to happen... */
- HDassert(io_bytes_left == 0);
- break;
+ /* Append span tree for entire span */
+ if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth],
+ udata->ds_rank - udata->depth, udata->ds_low[udata->depth],
+ udata->ds_span[udata->depth]->high,
+ udata->ds_span[udata->depth]->down) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+ udata->nelem -= udata->ds_span[udata->depth]->down->u.nelmts
+ * (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1);
+
+ /* Advance to next span */
+ udata->ds_span[udata->depth] = udata->ds_span[udata->depth]->next;
+ HDassert(udata->ds_span[udata->depth]);
+ udata->ds_low[udata->depth] = udata->ds_span[udata->depth]->low;
+ } while(udata->nelem > 0);
} /* end if */
else {
- /* Walk back down the iterator positions, resetting them */
- while((unsigned)curr_dim < fast_dim) {
- HDassert(curr_span);
- HDassert(curr_span->down);
- HDassert(curr_span->down->head);
-
- /* Increment current dimension to the next dimension down */
- curr_dim++;
-
- /* Set the new span for the next dimension down */
- iter->u.hyp.span[curr_dim] = curr_span->down->head;
-
- /* Advance span down the tree */
- curr_span = curr_span->down->head;
-
- /* Reset the absolute offset for the dim */
- abs_arr[curr_dim] = curr_span->low;
- } /* end while */
+ HDassert(udata->ds_rank - udata->depth == 1);
+ do {
+ /* If we will run out of elements to add in this span, add
+ * the remainder of the elements and break out */
+ HDassert(udata->ds_low[udata->depth] <= udata->ds_span[udata->depth]->high);
+ if(udata->nelem < (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1)) {
+ if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth], 1,
+ udata->ds_low[udata->depth], udata->ds_low[udata->depth] + udata->nelem - 1, NULL) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+ udata->ds_low[udata->depth] += udata->nelem;
+ udata->nelem = 0;
+ break;
+ } /* end if */
- /* Verify that the curr_span points to the fastest dim */
- HDassert(curr_span == iter->u.hyp.span[fast_dim]);
+ /* Append span tree for entire span */
+ if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth], 1,
+ udata->ds_low[udata->depth], udata->ds_span[udata->depth]->high, NULL) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+ udata->nelem -= udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1;
+
+ /* Advance to next span */
+ udata->ds_span[udata->depth] = udata->ds_span[udata->depth]->next;
+ HDassert(udata->ds_span[udata->depth]);
+ udata->ds_low[udata->depth] = udata->ds_span[udata->depth]->low;
+ } while(udata->nelem > 0);
} /* end else */
-
- /* Reset the buffer offset */
- for(u = 0, loc_off = 0; u < ndims; u++)
- loc_off += ((hsize_t)((hssize_t)abs_arr[u] + off_arr[u])) * slab[u];
} /* end while */
- /* Decrement number of elements left in iterator */
- io_used = (io_left - (io_bytes_left / elem_size));
- iter->elmt_left -= io_used;
+ HDassert(udata->skip == 0);
+ HDassert(udata->nelem == 0);
- /* Set the number of sequences generated */
- *nseq = curr_seq;
+ /* Mark projected space as changed (for all ranks) */
+ udata->ps_clean_bitmap = 0;
- /* Set the number of elements used */
- *nelem = io_used;
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S__hyper_proj_int_build_proj() */
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5S__hyper_get_seq_list_gen() */
-
/*--------------------------------------------------------------------------
NAME
- H5S__hyper_get_seq_list_opt
+ H5S__hyper_proj_int_iterate
PURPOSE
- Create a list of offsets & lengths for a selection
+ Main iteration routine for H5S__hyper_project_intersection
USAGE
- herr_t H5S_select_hyper_get_file_list_opt(space,iter,maxseq,maxelem,nseq,nelem,off,len)
- H5S_t *space; IN: Dataspace containing selection to use.
- H5S_sel_iter_t *iter; IN/OUT: Selection iterator describing last
- position of interest in selection.
- size_t maxseq; IN: Maximum number of sequences to generate
- size_t maxelem; IN: Maximum number of elements to include in the
- generated sequences
- size_t *nseq; OUT: Actual number of sequences generated
- size_t *nelem; OUT: Actual number of elements in sequences generated
- hsize_t *off; OUT: Array of offsets
- size_t *len; OUT: Array of lengths
+ herr_t H5S__hyper_proj_int_iterate(ss_span_info,sis_span_info,count,depth,udata)
+ const H5S_hyper_span_info_t *ss_span_info; IN: Span tree for source selection
+ const H5S_hyper_span_info_t *sis_span_info; IN: Span tree for source intersect selection
+ hsize_t count; IN: Number of times to compute the intersection of ss_span_info and sis_span_info
+ unsigned depth; IN: Depth of iteration (in terms of rank)
+ H5S_hyper_project_intersect_ud_t *udata; IN/OUT: Persistent shared data for iteration
RETURNS
Non-negative on success/Negative on failure.
DESCRIPTION
- Use the selection in the dataspace to generate a list of byte offsets and
- lengths for the region(s) selected. Start/Restart from the position in the
- ITER parameter. The number of sequences generated is limited by the MAXSEQ
- parameter and the number of sequences actually generated is stored in the
- NSEQ parameter.
+ Computes the intersection of ss_span_info and sis_span_info and projects it
+ to the projected space (held in udata). It accomplishes this by iterating
+ over both spaces and computing the number of elements to skip (in
+ ss_span_info) and the number of elements to add (the intersection) in a
+ sequential fashion (similar to run length encoding). As necessary, this
+ function both recurses into lower dimensions and calls
+ H5S__hyper_proj_int_build_proj to convert the skip/nelem pairs to the
+ projected span tree.
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S__hyper_get_seq_list_opt(const H5S_t *space, H5S_sel_iter_t *iter,
- size_t maxseq, size_t maxelem, size_t *nseq, size_t *nelem,
- hsize_t *off, size_t *len)
+H5S__hyper_proj_int_iterate(const H5S_hyper_span_info_t *ss_span_info,
+ const H5S_hyper_span_info_t *sis_span_info, hsize_t count, unsigned depth,
+ H5S_hyper_project_intersect_ud_t *udata)
{
- hsize_t *mem_size; /* Size of the source buffer */
- hsize_t slab[H5O_LAYOUT_NDIMS]; /* Hyperslab size */
- const hssize_t *sel_off; /* Selection offset in dataspace */
- hsize_t offset[H5O_LAYOUT_NDIMS]; /* Coordinate offset in dataspace */
- hsize_t tmp_count[H5O_LAYOUT_NDIMS];/* Temporary block count */
- hsize_t tmp_block[H5O_LAYOUT_NDIMS];/* Temporary block offset */
- hsize_t wrap[H5O_LAYOUT_NDIMS]; /* Bytes to wrap around at the end of a row */
- hsize_t skip[H5O_LAYOUT_NDIMS]; /* Bytes to skip between blocks */
- const H5S_hyper_dim_t *tdiminfo; /* Temporary pointer to diminfo information */
- hsize_t fast_dim_start, /* Local copies of fastest changing dimension info */
- fast_dim_stride,
- fast_dim_block,
- fast_dim_offset;
- size_t fast_dim_buf_off; /* Local copy of amount to move fastest dimension buffer offset */
- size_t fast_dim_count; /* Number of blocks left in fastest changing dimension */
- size_t tot_blk_count; /* Total number of blocks left to output */
- size_t act_blk_count; /* Actual number of blocks to output */
- size_t total_rows; /* Total number of entire rows to output */
- size_t curr_rows; /* Current number of entire rows to output */
- unsigned fast_dim; /* Rank of the fastest changing dimension for the dataspace */
- unsigned ndims; /* Number of dimensions of dataset */
- int temp_dim; /* Temporary rank holder */
- hsize_t acc; /* Accumulator */
- hsize_t loc; /* Coordinate offset */
- size_t curr_seq = 0; /* Current sequence being operated on */
- size_t actual_elem; /* The actual number of elements to count */
- size_t actual_bytes;/* The actual number of bytes to copy */
- size_t io_left; /* The number of elements left in I/O operation */
- size_t start_io_left; /* The initial number of elements left in I/O operation */
- size_t elem_size; /* Size of each element iterating over */
- unsigned u; /* Local index variable */
- int i; /* Local index variable */
-
- FUNC_ENTER_STATIC_NOERR
-
- /* Check args */
- HDassert(space);
- HDassert(iter);
- HDassert(maxseq > 0);
- HDassert(maxelem > 0);
- HDassert(nseq);
- HDassert(nelem);
- HDassert(off);
- HDassert(len);
-
- /* Set the local copy of the diminfo pointer */
- tdiminfo = iter->u.hyp.diminfo;
-
- /* Check if this is a "flattened" regular hyperslab selection */
- if(iter->u.hyp.iter_rank != 0 && iter->u.hyp.iter_rank < space->extent.rank) {
- /* Set the aliases for a few important dimension ranks */
- ndims = iter->u.hyp.iter_rank;
- fast_dim = ndims - 1;
-
- /* Set the local copy of the selection offset */
- sel_off = iter->u.hyp.sel_off;
-
- /* Set up the pointer to the size of the memory space */
- mem_size = iter->u.hyp.size;
- } /* end if */
- else {
- /* Set the aliases for a few important dimension ranks */
- ndims = space->extent.rank;
- fast_dim = ndims - 1;
-
- /* Set the local copy of the selection offset */
- sel_off = space->select.offset;
-
- /* Set up the pointer to the size of the memory space */
- mem_size = space->extent.size;
- } /* end else */
-
- /* initialize row sizes for each dimension */
- elem_size = iter->elmt_size;
- for(i = (int)fast_dim, acc = elem_size; i >= 0; i--) {
- slab[i] = acc;
- acc *= mem_size[i];
- } /* end for */
-
- /* Calculate the number of elements to sequence through */
- H5_CHECK_OVERFLOW(iter->elmt_left, hsize_t, size_t);
- io_left = MIN((size_t)iter->elmt_left, maxelem);
-
- /* Sanity check that there aren't any "remainder" sequences in process */
- HDassert(!((iter->u.hyp.off[fast_dim] - tdiminfo[fast_dim].start) % tdiminfo[fast_dim].stride != 0 ||
- ((iter->u.hyp.off[fast_dim] != tdiminfo[fast_dim].start) && tdiminfo[fast_dim].count == 1)));
-
- /* We've cleared the "remainder" of the previous fastest dimension
- * sequence before calling this routine, so we must be at the beginning of
- * a sequence. Use the fancy algorithm to compute the offsets and run
- * through as many as possible, until the buffer fills up.
- */
-
- /* Keep the number of elements we started with */
- start_io_left = io_left;
-
- /* Compute the arrays to perform I/O on */
+ const H5S_hyper_span_t *ss_span; /* Current span in source space */
+ const H5S_hyper_span_t *sis_span; /* Current span in source intersect space */
+ hsize_t ss_low; /* Current low bounds of source span */
+ hsize_t sis_low; /* Current low bounds of source intersect span */
+ hsize_t high; /* High bounds of current intersection */
+ hsize_t low; /* Low bounds of current intersection */
+ hsize_t old_skip; /* Value of udata->skip before main loop */
+ hsize_t old_nelem; /* Value of udata->nelem before main loop */
+ hbool_t check_intersect; /* Whether to check for intersecting elements */
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
- /* Copy the location of the point to get */
- /* (Add in the selection offset) */
- for(u = 0; u < ndims; u++)
- offset[u] = (hsize_t)((hssize_t)iter->u.hyp.off[u] + sel_off[u]);
+ FUNC_ENTER_STATIC
- /* Compute the current "counts" for this location */
- for(u = 0; u < ndims; u++) {
- if(tdiminfo[u].count == 1) {
- tmp_count[u] = 0;
- tmp_block[u] = iter->u.hyp.off[u] - tdiminfo[u].start;
+ /* Check for non-overlapping bounds */
+ check_intersect = TRUE;
+ for(u = 0; u < (udata->ss_rank - depth); u++)
+ if(!H5S_RANGE_OVERLAP(ss_span_info->low_bounds[u],
+ ss_span_info->high_bounds[u],
+ sis_span_info->low_bounds[u],
+ sis_span_info->high_bounds[u])) {
+ check_intersect = FALSE;
+ break;
} /* end if */
- else {
- tmp_count[u] = (iter->u.hyp.off[u] - tdiminfo[u].start) / tdiminfo[u].stride;
- tmp_block[u] = (iter->u.hyp.off[u] - tdiminfo[u].start) % tdiminfo[u].stride;
- } /* end else */
- } /* end for */
-
- /* Compute the initial buffer offset */
- for(u = 0, loc = 0; u < ndims; u++)
- loc += offset[u] * slab[u];
-
- /* Set the number of elements to write each time */
- H5_CHECKED_ASSIGN(actual_elem, size_t, tdiminfo[fast_dim].block, hsize_t);
-
- /* Set the number of actual bytes */
- actual_bytes = actual_elem * elem_size;
-
- /* Set local copies of information for the fastest changing dimension */
- fast_dim_start = tdiminfo[fast_dim].start;
- fast_dim_stride = tdiminfo[fast_dim].stride;
- fast_dim_block = tdiminfo[fast_dim].block;
- H5_CHECKED_ASSIGN(fast_dim_buf_off, size_t, slab[fast_dim] * fast_dim_stride, hsize_t);
- fast_dim_offset = (hsize_t)((hssize_t)fast_dim_start + sel_off[fast_dim]);
-
- /* Compute the number of blocks which would fit into the buffer */
- H5_CHECK_OVERFLOW(io_left / fast_dim_block, hsize_t, size_t);
- tot_blk_count = (size_t)(io_left / fast_dim_block);
-
- /* Don't go over the maximum number of sequences allowed */
- tot_blk_count = MIN(tot_blk_count, (maxseq - curr_seq));
-
- /* Compute the amount to wrap at the end of each row */
- for(u = 0; u < ndims; u++)
- wrap[u] = (mem_size[u] - (tdiminfo[u].stride * tdiminfo[u].count)) * slab[u];
-
- /* Compute the amount to skip between blocks */
- for(u = 0; u < ndims; u++)
- skip[u] = (tdiminfo[u].stride - tdiminfo[u].block) * slab[u];
-
- /* Check if there is a partial row left (with full blocks) */
- if(tmp_count[fast_dim] > 0) {
- /* Get number of blocks in fastest dimension */
- H5_CHECKED_ASSIGN(fast_dim_count, size_t, tdiminfo[fast_dim].count - tmp_count[fast_dim], hsize_t);
-
- /* Make certain this entire row will fit into buffer */
- fast_dim_count = MIN(fast_dim_count, tot_blk_count);
-
- /* Number of blocks to sequence over */
- act_blk_count = fast_dim_count;
- /* Loop over all the blocks in the fastest changing dimension */
- while(fast_dim_count > 0) {
- /* Store the sequence information */
- off[curr_seq] = loc;
- len[curr_seq] = actual_bytes;
+ /* Only enter main loop if there's something to do */
+ if(check_intersect) {
+ /* Set ps_clean_bitmap */
+ udata->ps_clean_bitmap |= (((uint32_t)1) << depth);
- /* Increment sequence count */
- curr_seq++;
-
- /* Increment information to reflect block just processed */
- loc += fast_dim_buf_off;
+ /* Save old skip and nelem */
+ old_skip = udata->skip;
+ old_nelem = udata->nelem;
- /* Decrement number of blocks */
- fast_dim_count--;
- } /* end while */
-
- /* Decrement number of elements left */
- io_left -= actual_elem * act_blk_count;
-
- /* Decrement number of blocks left */
- tot_blk_count -= act_blk_count;
+ /* Intersect spaces once per count */
+ for(u = 0; u < count; u++) {
+ ss_span = ss_span_info->head;
+ sis_span = sis_span_info->head;
+ HDassert(ss_span && sis_span);
+ ss_low = ss_span->low;
+ sis_low = sis_span->low;
- /* Increment information to reflect block just processed */
- tmp_count[fast_dim] += act_blk_count;
+ /* Main loop */
+ do {
+ /* Check if spans overlap */
+ if(H5S_RANGE_OVERLAP(ss_low, ss_span->high,
+ sis_low, sis_span->high)) {
+ high = MIN(ss_span->high, sis_span->high);
+ if(ss_span->down) {
+ /* Add skipped elements if there's a pre-gap */
+ if(ss_low < sis_low) {
+ low = sis_low;
+ H5S_HYPER_PROJ_INT_ADD_SKIP(udata, H5S__hyper_spans_nelem_helper(ss_span->down, udata->op_gen) * (sis_low - ss_low), FAIL);
+ } /* end if */
+ else
+ low = ss_low;
- /* Check if we finished the entire row of blocks */
- if(tmp_count[fast_dim] >= tdiminfo[fast_dim].count) {
- /* Increment offset in destination buffer */
- loc += wrap[fast_dim];
+ /* Recurse into next dimension down */
+ if(H5S__hyper_proj_int_iterate(ss_span->down, sis_span->down, high - low + 1, depth + 1, udata) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOMPARE, FAIL, "can't iterate over source selections")
+ } /* end if */
+ else {
+ HDassert(depth == udata->ss_rank - 1);
- /* Increment information to reflect block just processed */
- offset[fast_dim] = fast_dim_offset; /* reset the offset in the fastest dimension */
- tmp_count[fast_dim] = 0;
+ /* Add skipped elements if there's a pre-gap */
+ if(ss_low < sis_low) {
+ low = sis_low;
+ H5S_HYPER_PROJ_INT_ADD_SKIP(udata, sis_low - ss_low, FAIL);
+ } /* end if */
+ else
+ low = ss_low;
- /* Increment the offset and count for the other dimensions */
- temp_dim = (int)fast_dim - 1;
- while(temp_dim >= 0) {
- /* Move to the next row in the curent dimension */
- offset[temp_dim]++;
- tmp_block[temp_dim]++;
+ /* Add overlapping elements */
+ udata->nelem += high - low + 1;
+ } /* end else */
- /* If this block is still in the range of blocks to output for the dimension, break out of loop */
- if(tmp_block[temp_dim] < tdiminfo[temp_dim].block)
- break;
+ /* Advance spans */
+ if(ss_span->high == sis_span->high) {
+ /* Advance both spans */
+ ss_span = ss_span->next;
+ if(ss_span)
+ ss_low = ss_span->low;
+ sis_span = sis_span->next;
+ if(sis_span)
+ sis_low = sis_span->low;
+ } /* end if */
+ else if(ss_span->high == high) {
+ /* Advance source span */
+ HDassert(ss_span->high < sis_span->high);
+ sis_low = high + 1;
+ ss_span = ss_span->next;
+ if(ss_span)
+ ss_low = ss_span->low;
+ } /* end if */
+ else {
+ /* Advance source intersect span */
+ HDassert(ss_span->high > sis_span->high);
+ ss_low = high + 1;
+ sis_span = sis_span->next;
+ if(sis_span)
+ sis_low = sis_span->low;
+ } /* end else */
+ } /* end if */
else {
- /* Move to the next block in the current dimension */
- offset[temp_dim] += (tdiminfo[temp_dim].stride - tdiminfo[temp_dim].block);
- loc += skip[temp_dim];
- tmp_block[temp_dim] = 0;
- tmp_count[temp_dim]++;
+ /* Advance spans */
+ if(ss_span->high < sis_low) {
+ /* Add skipped elements */
+ if(ss_span->down)
+ H5S_HYPER_PROJ_INT_ADD_SKIP(udata, H5S__hyper_spans_nelem_helper(ss_span->down, udata->op_gen) * (ss_span->high - ss_low + 1), FAIL);
+ else
+ H5S_HYPER_PROJ_INT_ADD_SKIP(udata, ss_span->high - ss_low + 1, FAIL);
- /* If this block is still in the range of blocks to output for the dimension, break out of loop */
- if(tmp_count[temp_dim] < tdiminfo[temp_dim].count)
- break;
+ /* Advance source span */
+ ss_span = ss_span->next;
+ if(ss_span)
+ ss_low = ss_span->low;
+ } /* end if */
else {
- offset[temp_dim] = (hsize_t)((hssize_t)tdiminfo[temp_dim].start + sel_off[temp_dim]);
- loc += wrap[temp_dim];
- tmp_count[temp_dim] = 0; /* reset back to the beginning of the line */
- tmp_block[temp_dim] = 0;
+ /* Advance source intersect span */
+ HDassert(ss_low > sis_span->high);
+ sis_span = sis_span->next;
+ if(sis_span)
+ sis_low = sis_span->low;
} /* end else */
} /* end else */
-
- /* Decrement dimension count */
- temp_dim--;
- } /* end while */
- } /* end if */
- else {
- /* Update the offset in the fastest dimension */
- offset[fast_dim] += (fast_dim_stride * act_blk_count);
- } /* end else */
- } /* end if */
-
- /* Compute the number of entire rows to read in */
- H5_CHECK_OVERFLOW(tot_blk_count / tdiminfo[fast_dim].count, hsize_t, size_t);
- curr_rows = total_rows = (size_t)(tot_blk_count / tdiminfo[fast_dim].count);
-
- /* Reset copy of number of blocks in fastest dimension */
- H5_CHECKED_ASSIGN(fast_dim_count, size_t, tdiminfo[fast_dim].count, hsize_t);
-
- /* Read in data until an entire sequence can't be written out any longer */
- while(curr_rows > 0) {
-
-#define DUFF_GUTS \
-/* Store the sequence information */ \
-off[curr_seq] = loc; \
-len[curr_seq] = actual_bytes; \
- \
-/* Increment sequence count */ \
-curr_seq++; \
- \
-/* Increment information to reflect block just processed */ \
-loc += fast_dim_buf_off;
-
-#ifdef NO_DUFFS_DEVICE
- /* Loop over all the blocks in the fastest changing dimension */
- while(fast_dim_count > 0) {
- DUFF_GUTS
-
- /* Decrement number of blocks */
- fast_dim_count--;
- } /* end while */
-#else /* NO_DUFFS_DEVICE */
- {
- size_t duffs_index; /* Counting index for Duff's device */
-
- duffs_index = (fast_dim_count + 7) / 8;
- switch (fast_dim_count % 8) {
- default:
- HDassert(0 && "This Should never be executed!");
- break;
- case 0:
- do
- {
- DUFF_GUTS
- case 7:
- DUFF_GUTS
- case 6:
- DUFF_GUTS
- case 5:
- DUFF_GUTS
- case 4:
- DUFF_GUTS
- case 3:
- DUFF_GUTS
- case 2:
- DUFF_GUTS
- case 1:
- DUFF_GUTS
- } while (--duffs_index > 0);
- } /* end switch */
- }
-#endif /* NO_DUFFS_DEVICE */
-#undef DUFF_GUTS
-
- /* Increment offset in destination buffer */
- loc += wrap[fast_dim];
-
- /* Increment the offset and count for the other dimensions */
- temp_dim = (int)fast_dim - 1;
- while(temp_dim >= 0) {
- /* Move to the next row in the curent dimension */
- offset[temp_dim]++;
- tmp_block[temp_dim]++;
-
- /* If this block is still in the range of blocks to output for the dimension, break out of loop */
- if(tmp_block[temp_dim] < tdiminfo[temp_dim].block)
- break;
- else {
- /* Move to the next block in the current dimension */
- offset[temp_dim] += (tdiminfo[temp_dim].stride - tdiminfo[temp_dim].block);
- loc += skip[temp_dim];
- tmp_block[temp_dim] = 0;
- tmp_count[temp_dim]++;
-
- /* If this block is still in the range of blocks to output for the dimension, break out of loop */
- if(tmp_count[temp_dim] < tdiminfo[temp_dim].count)
- break;
+ } while(ss_span && sis_span);
+
+ if(ss_span && !((depth == 0) && (u == count - 1))) {
+ /* Count remaining elements in ss_span_info */
+ if(ss_span->down) {
+ H5S_HYPER_PROJ_INT_ADD_SKIP(udata, H5S__hyper_spans_nelem_helper(ss_span->down, udata->op_gen) * (ss_span->high - ss_low + 1), FAIL);
+ ss_span = ss_span->next;
+ while(ss_span) {
+ H5S_HYPER_PROJ_INT_ADD_SKIP(udata, H5S__hyper_spans_nelem_helper(ss_span->down, udata->op_gen) * (ss_span->high - ss_span->low + 1), FAIL);
+ ss_span = ss_span->next;
+ } /* end while */
+ } /* end if */
else {
- offset[temp_dim] = (hsize_t)((hssize_t)tdiminfo[temp_dim].start + sel_off[temp_dim]);
- loc += wrap[temp_dim];
- tmp_count[temp_dim] = 0; /* reset back to the beginning of the line */
- tmp_block[temp_dim] = 0;
+ H5S_HYPER_PROJ_INT_ADD_SKIP(udata, ss_span->high - ss_low + 1, FAIL);
+ ss_span = ss_span->next;
+ while(ss_span) {
+ H5S_HYPER_PROJ_INT_ADD_SKIP(udata, ss_span->high - ss_span->low + 1, FAIL);
+ ss_span = ss_span->next;
+ } /* end while */
} /* end else */
- } /* end else */
-
- /* Decrement dimension count */
- temp_dim--;
- } /* end while */
-
- /* Decrement the number of rows left */
- curr_rows--;
- } /* end while */
-
- /* Adjust the number of blocks & elements left to transfer */
-
- /* Decrement number of elements left */
- H5_CHECK_OVERFLOW(actual_elem * (total_rows * tdiminfo[fast_dim].count), hsize_t, size_t);
- io_left -= (size_t)(actual_elem * (total_rows * tdiminfo[fast_dim].count));
-
- /* Decrement number of blocks left */
- H5_CHECK_OVERFLOW((total_rows * tdiminfo[fast_dim].count), hsize_t, size_t);
- tot_blk_count -= (size_t)(total_rows * tdiminfo[fast_dim].count);
-
- /* Read in partial row of blocks */
- if(io_left > 0 && curr_seq < maxseq) {
- /* Get remaining number of blocks left to output */
- fast_dim_count = tot_blk_count;
-
- /* Loop over all the blocks in the fastest changing dimension */
- while(fast_dim_count > 0) {
- /* Store the sequence information */
- off[curr_seq] = loc;
- len[curr_seq] = actual_bytes;
-
- /* Increment sequence count */
- curr_seq++;
-
- /* Increment information to reflect block just processed */
- loc += fast_dim_buf_off;
-
- /* Decrement number of blocks */
- fast_dim_count--;
- } /* end while */
-
- /* Decrement number of elements left */
- io_left -= actual_elem * tot_blk_count;
-
- /* Increment information to reflect block just processed */
- offset[fast_dim] += (fast_dim_stride * tot_blk_count); /* move the offset in the fastest dimension */
-
- /* Handle any leftover, partial blocks in this row */
- if(io_left > 0 && curr_seq < maxseq) {
- actual_elem = io_left;
- actual_bytes = actual_elem * elem_size;
-
- /* Store the sequence information */
- off[curr_seq] = loc;
- len[curr_seq] = actual_bytes;
-
- /* Increment sequence count */
- curr_seq++;
-
- /* Decrement the number of elements left */
- io_left -= actual_elem;
-
- /* Increment buffer correctly */
- offset[fast_dim] += actual_elem;
- } /* end if */
-
- /* don't bother checking slower dimensions */
- HDassert(io_left == 0 || curr_seq == maxseq);
- } /* end if */
-
- /* Update the iterator */
-
- /* Update the iterator with the location we stopped */
- /* (Subtract out the selection offset) */
- for(u = 0; u < ndims; u++)
- iter->u.hyp.off[u] = (hsize_t)((hssize_t)offset[u] - sel_off[u]);
-
- /* Decrement the number of elements left in selection */
- iter->elmt_left -= (start_io_left - io_left);
-
- /* Increment the number of sequences generated */
- *nseq += curr_seq;
-
- /* Increment the number of elements used */
- *nelem += start_io_left - io_left;
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5S__hyper_get_seq_list_opt() */
-
-
-/*--------------------------------------------------------------------------
- NAME
- H5S__hyper_get_seq_list_single
- PURPOSE
- Create a list of offsets & lengths for a selection
- USAGE
- herr_t H5S__hyper_get_seq_list_single(space, flags, iter, maxseq, maxelem, nseq, nelem, off, len)
- H5S_t *space; IN: Dataspace containing selection to use.
- unsigned flags; IN: Flags for extra information about operation
- H5S_sel_iter_t *iter; IN/OUT: Selection iterator describing last
- position of interest in selection.
- size_t maxseq; IN: Maximum number of sequences to generate
- size_t maxelem; IN: Maximum number of elements to include in the
- generated sequences
- size_t *nseq; OUT: Actual number of sequences generated
- size_t *nelem; OUT: Actual number of elements in sequences generated
- hsize_t *off; OUT: Array of offsets
- size_t *len; OUT: Array of lengths
- RETURNS
- Non-negative on success/Negative on failure.
- DESCRIPTION
- Use the selection in the dataspace to generate a list of byte offsets and
- lengths for the region(s) selected. Start/Restart from the position in the
- ITER parameter. The number of sequences generated is limited by the MAXSEQ
- parameter and the number of sequences actually generated is stored in the
- NSEQ parameter.
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
-static herr_t
-H5S__hyper_get_seq_list_single(const H5S_t *space, H5S_sel_iter_t *iter,
- size_t maxseq, size_t maxelem, size_t *nseq, size_t *nelem,
- hsize_t *off, size_t *len)
-{
- const H5S_hyper_dim_t *tdiminfo; /* Temporary pointer to diminfo information */
- const hssize_t *sel_off; /* Selection offset in dataspace */
- hsize_t *mem_size; /* Size of the source buffer */
- hsize_t base_offset[H5O_LAYOUT_NDIMS]; /* Base coordinate offset in dataspace */
- hsize_t offset[H5O_LAYOUT_NDIMS]; /* Coordinate offset in dataspace */
- hsize_t slab[H5O_LAYOUT_NDIMS]; /* Hyperslab size */
- hsize_t fast_dim_block; /* Local copies of fastest changing dimension info */
- hsize_t acc; /* Accumulator */
- hsize_t loc; /* Coordinate offset */
- size_t tot_blk_count; /* Total number of blocks left to output */
- size_t elem_size; /* Size of each element iterating over */
- size_t io_left; /* The number of elements left in I/O operation */
- size_t actual_elem; /* The actual number of elements to count */
- unsigned ndims; /* Number of dimensions of dataset */
- unsigned fast_dim; /* Rank of the fastest changing dimension for the dataspace */
- unsigned skip_dim; /* Rank of the dimension to skip along */
- unsigned u; /* Local index variable */
- int i; /* Local index variable */
-
- FUNC_ENTER_STATIC_NOERR
-
- /* Check args */
- HDassert(space);
- HDassert(iter);
- HDassert(maxseq > 0);
- HDassert(maxelem > 0);
- HDassert(nseq);
- HDassert(nelem);
- HDassert(off);
- HDassert(len);
-
- /* Set a local copy of the diminfo pointer */
- tdiminfo = iter->u.hyp.diminfo;
-
- /* Check if this is a "flattened" regular hyperslab selection */
- if(iter->u.hyp.iter_rank != 0 && iter->u.hyp.iter_rank < space->extent.rank) {
- /* Set the aliases for a few important dimension ranks */
- ndims = iter->u.hyp.iter_rank;
-
- /* Set the local copy of the selection offset */
- sel_off = iter->u.hyp.sel_off;
-
- /* Set up the pointer to the size of the memory space */
- mem_size = iter->u.hyp.size;
- } /* end if */
- else {
- /* Set the aliases for a few important dimension ranks */
- ndims = space->extent.rank;
-
- /* Set the local copy of the selection offset */
- sel_off = space->select.offset;
-
- /* Set up the pointer to the size of the memory space */
- mem_size = space->extent.size;
- } /* end else */
- fast_dim = ndims - 1;
-
- /* initialize row sizes for each dimension */
- elem_size = iter->elmt_size;
- for(i = (int)fast_dim, acc = elem_size; i >= 0; i--) {
- slab[i] = acc;
- acc *= mem_size[i];
- } /* end for */
-
- /* Copy the base location of the block */
- /* (Add in the selection offset) */
- for(u = 0; u < ndims; u++)
- base_offset[u] = (hsize_t)((hssize_t)tdiminfo[u].start + sel_off[u]);
-
- /* Copy the location of the point to get */
- /* (Add in the selection offset) */
- for(u = 0; u < ndims; u++)
- offset[u] = (hsize_t)((hssize_t)iter->u.hyp.off[u] + sel_off[u]);
-
- /* Compute the initial buffer offset */
- for(u = 0, loc = 0; u < ndims; u++)
- loc += offset[u] * slab[u];
-
- /* Set local copies of information for the fastest changing dimension */
- fast_dim_block = tdiminfo[fast_dim].block;
-
- /* Calculate the number of elements to sequence through */
- H5_CHECK_OVERFLOW(iter->elmt_left, hsize_t, size_t);
- io_left = MIN((size_t)iter->elmt_left, maxelem);
-
- /* Compute the number of blocks which would fit into the buffer */
- H5_CHECK_OVERFLOW(io_left / fast_dim_block, hsize_t, size_t);
- tot_blk_count = (size_t)(io_left / fast_dim_block);
-
- /* Don't go over the maximum number of sequences allowed */
- tot_blk_count = MIN(tot_blk_count, maxseq);
-
- /* Set the number of elements to write each time */
- H5_CHECKED_ASSIGN(actual_elem, size_t, fast_dim_block, hsize_t);
-
- /* Check for blocks to operate on */
- if(tot_blk_count > 0) {
- size_t actual_bytes; /* The actual number of bytes to copy */
-
- /* Set the number of actual bytes */
- actual_bytes = actual_elem * elem_size;
-
- /* Check for 1-dim selection */
- if(0 == fast_dim) {
- /* Sanity checks */
- HDassert(1 == tot_blk_count);
- HDassert(io_left == actual_elem);
-
- /* Store the sequence information */
- *off++ = loc;
- *len++ = actual_bytes;
- } /* end if */
- else {
- hsize_t skip_slab; /* Temporary copy of slab[fast_dim - 1] */
- size_t blk_count; /* Total number of blocks left to output */
+ } /* end if */
- /* Find first dimension w/block >1 */
- skip_dim = fast_dim;
- for(i = (int)(fast_dim - 1); i >= 0; i--)
- if(tdiminfo[i].block > 1) {
- skip_dim = (unsigned)i;
- break;
+ /* Check if the projected space was not changed since we started the
+ * first iteration of the loop, if so we do not need to continue
+ * looping and can just copy the result */
+ if(udata->ps_clean_bitmap & (((uint32_t)1) << depth)) {
+ HDassert(u == 0);
+ if(udata->skip == old_skip) {
+ /* First case: algorithm added only elements */
+ HDassert(udata->nelem >= old_nelem);
+ udata->nelem += (count - 1) * (udata->nelem - old_nelem);
} /* end if */
- skip_slab = slab[skip_dim];
-
- /* Check for being able to use fast algorithm for 1-D */
- if(0 == skip_dim) {
- /* Create sequences until an entire row can't be used */
- blk_count = tot_blk_count;
- while(blk_count > 0) {
- /* Store the sequence information */
- *off++ = loc;
- *len++ = actual_bytes;
-
- /* Increment offset in destination buffer */
- loc += skip_slab;
-
- /* Decrement block count */
- blk_count--;
- } /* end while */
+ else if(udata->nelem == 0) {
+ /* Second case: algorithm added only skip. In this case,
+ * nelem must be 0 since otherwise adding skip would have
+ * triggered a change in the projected space */
+ HDassert(old_nelem == 0);
+ HDassert(udata->skip > old_skip);
+ udata->skip += (count - 1) * (udata->skip - old_skip);
+ } /* end if */
+ else {
+ /* Third case: agorithm added skip and nelem (in that
+ * order). Add the same skip and nelem once for each item
+ * remaining in count. */
+ hsize_t skip_add;
+ hsize_t nelem_add;
+
+ HDassert(udata->nelem > 0);
+ HDassert(udata->skip > old_skip);
+ HDassert(old_nelem == 0);
+
+ skip_add = udata->skip - old_skip;
+ nelem_add = udata->nelem - old_nelem;
+ for(u = 1; u < count; u++) {
+ H5S_HYPER_PROJ_INT_ADD_SKIP(udata, skip_add, FAIL);
+ udata->nelem += nelem_add;
+ } /* end for */
+ } /* end else */
- /* Move to the next location */
- offset[skip_dim] += tot_blk_count;
+ /* End loop since we already took care of it */
+ break;
} /* end if */
- else {
- hsize_t tmp_block[H5O_LAYOUT_NDIMS];/* Temporary block offset */
- hsize_t skip[H5O_LAYOUT_NDIMS]; /* Bytes to skip between blocks */
- int temp_dim; /* Temporary rank holder */
-
- /* Set the starting block location */
- for(u = 0; u < ndims; u++)
- tmp_block[u] = iter->u.hyp.off[u] - tdiminfo[u].start;
-
- /* Compute the amount to skip between sequences */
- for(u = 0; u < ndims; u++)
- skip[u] = (mem_size[u] - tdiminfo[u].block) * slab[u];
-
- /* Create sequences until an entire row can't be used */
- blk_count = tot_blk_count;
- while(blk_count > 0) {
- /* Store the sequence information */
- *off++ = loc;
- *len++ = actual_bytes;
-
- /* Set temporary dimension for advancing offsets */
- temp_dim = (int)skip_dim;
-
- /* Increment offset in destination buffer */
- loc += skip_slab;
-
- /* Increment the offset and count for the other dimensions */
- while(temp_dim >= 0) {
- /* Move to the next row in the curent dimension */
- offset[temp_dim]++;
- tmp_block[temp_dim]++;
-
- /* If this block is still in the range of blocks to output for the dimension, break out of loop */
- if(tmp_block[temp_dim] < tdiminfo[temp_dim].block)
- break;
- else {
- offset[temp_dim] = base_offset[temp_dim];
- loc += skip[temp_dim];
- tmp_block[temp_dim] = 0;
- } /* end else */
-
- /* Decrement dimension count */
- temp_dim--;
- } /* end while */
-
- /* Decrement block count */
- blk_count--;
- } /* end while */
- } /* end else */
- } /* end else */
-
- /* Update the iterator, if there were any blocks used */
-
- /* Decrement the number of elements left in selection */
- iter->elmt_left -= tot_blk_count * actual_elem;
-
- /* Check if there are elements left in iterator */
- if(iter->elmt_left > 0) {
- /* Update the iterator with the location we stopped */
- /* (Subtract out the selection offset) */
- for(u = 0; u < ndims; u++)
- iter->u.hyp.off[u] = (hsize_t)((hssize_t)offset[u] - sel_off[u]);
- } /* end if */
-
- /* Increment the number of sequences generated */
- *nseq += tot_blk_count;
-
- /* Increment the number of elements used */
- *nelem += tot_blk_count * actual_elem;
- } /* end if */
-
- /* Check for partial block, with room for another sequence */
- if(io_left > (tot_blk_count * actual_elem) && tot_blk_count < maxseq) {
- size_t elmt_remainder; /* Elements remaining */
-
- /* Compute elements left */
- elmt_remainder = io_left - (tot_blk_count * actual_elem);
- HDassert(elmt_remainder < fast_dim_block);
- HDassert(elmt_remainder > 0);
-
- /* Store the sequence information */
- *off++ = loc;
- *len++ = elmt_remainder * elem_size;
-
- /* Update the iterator with the location we stopped */
- iter->u.hyp.off[fast_dim] += (hsize_t)elmt_remainder;
-
- /* Decrement the number of elements left in selection */
- iter->elmt_left -= elmt_remainder;
-
- /* Increment the number of sequences generated */
- (*nseq)++;
-
- /* Increment the number of elements used */
- *nelem += elmt_remainder;
+ } /* end for */
} /* end if */
-
- /* Sanity check */
- HDassert(*nseq > 0);
- HDassert(*nelem > 0);
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5S__hyper_get_seq_list_single() */
-
-
-/*--------------------------------------------------------------------------
- NAME
- H5S__hyper_get_seq_list
- PURPOSE
- Create a list of offsets & lengths for a selection
- USAGE
- herr_t H5S__hyper_get_seq_list(space,flags,iter,maxseq,maxelem,nseq,nelem,off,len)
- H5S_t *space; IN: Dataspace containing selection to use.
- unsigned flags; IN: Flags for extra information about operation
- H5S_sel_iter_t *iter; IN/OUT: Selection iterator describing last
- position of interest in selection.
- size_t maxseq; IN: Maximum number of sequences to generate
- size_t maxelem; IN: Maximum number of elements to include in the
- generated sequences
- size_t *nseq; OUT: Actual number of sequences generated
- size_t *nelem; OUT: Actual number of elements in sequences generated
- hsize_t *off; OUT: Array of offsets
- size_t *len; OUT: Array of lengths
- RETURNS
- Non-negative on success/Negative on failure.
- DESCRIPTION
- Use the selection in the dataspace to generate a list of byte offsets and
- lengths for the region(s) selected. Start/Restart from the position in the
- ITER parameter. The number of sequences generated is limited by the MAXSEQ
- parameter and the number of sequences actually generated is stored in the
- NSEQ parameter.
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
-static herr_t
-H5S__hyper_get_seq_list(const H5S_t *space, unsigned H5_ATTR_UNUSED flags, H5S_sel_iter_t *iter,
- size_t maxseq, size_t maxelem, size_t *nseq, size_t *nelem,
- hsize_t *off, size_t *len)
-{
- herr_t ret_value = FAIL; /* return value */
-
- FUNC_ENTER_STATIC_NOERR
-
- /* Check args */
- HDassert(space);
- HDassert(iter);
- HDassert(iter->elmt_left > 0);
- HDassert(maxseq > 0);
- HDassert(maxelem > 0);
- HDassert(nseq);
- HDassert(nelem);
- HDassert(off);
- HDassert(len);
- HDassert(space->select.sel_info.hslab->unlim_dim < 0);
-
- /* Check for the special case of just one H5Sselect_hyperslab call made */
- if(space->select.sel_info.hslab->diminfo_valid) {
- const H5S_hyper_dim_t *tdiminfo; /* Temporary pointer to diminfo information */
- const hssize_t *sel_off; /* Selection offset in dataspace */
- hsize_t *mem_size; /* Size of the source buffer */
- unsigned ndims; /* Number of dimensions of dataset */
- unsigned fast_dim; /* Rank of the fastest changing dimension for the dataspace */
- hbool_t single_block; /* Whether the selection is a single block */
- unsigned u; /* Local index variable */
-
- /* Set a local copy of the diminfo pointer */
- tdiminfo = iter->u.hyp.diminfo;
-
- /* Check if this is a "flattened" regular hyperslab selection */
- if(iter->u.hyp.iter_rank != 0 && iter->u.hyp.iter_rank < space->extent.rank) {
- /* Set the aliases for a few important dimension ranks */
- ndims = iter->u.hyp.iter_rank;
-
- /* Set the local copy of the selection offset */
- sel_off = iter->u.hyp.sel_off;
-
- /* Set up the pointer to the size of the memory space */
- mem_size = iter->u.hyp.size;
- } /* end if */
- else {
- /* Set the aliases for a few important dimension ranks */
- ndims = space->extent.rank;
-
- /* Set the local copy of the selection offset */
- sel_off = space->select.offset;
-
- /* Set up the pointer to the size of the memory space */
- mem_size = space->extent.size;
- } /* end else */
- fast_dim = ndims - 1;
-
- /* Check if we stopped in the middle of a sequence of elements */
- if((iter->u.hyp.off[fast_dim] - tdiminfo[fast_dim].start) % tdiminfo[fast_dim].stride != 0 ||
- ((iter->u.hyp.off[fast_dim] != tdiminfo[fast_dim].start) && tdiminfo[fast_dim].count == 1)) {
- hsize_t slab[H5O_LAYOUT_NDIMS]; /* Hyperslab size */
- hsize_t loc; /* Coordinate offset */
- hsize_t acc; /* Accumulator */
- size_t leftover; /* The number of elements left over from the last sequence */
- size_t actual_elem; /* The actual number of elements to count */
- size_t elem_size; /* Size of each element iterating over */
- int i; /* Local index variable */
-
-
- /* Calculate the number of elements left in the sequence */
- if(tdiminfo[fast_dim].count == 1) {
- H5_CHECKED_ASSIGN(leftover, size_t, tdiminfo[fast_dim].block - (iter->u.hyp.off[fast_dim] - tdiminfo[fast_dim].start), hsize_t);
- } /* end if */
- else {
- H5_CHECKED_ASSIGN(leftover, size_t, tdiminfo[fast_dim].block - ((iter->u.hyp.off[fast_dim] - tdiminfo[fast_dim].start) % tdiminfo[fast_dim].stride), hsize_t);
- } /* end else */
-
- /* Make certain that we don't write too many */
- actual_elem = MIN3(leftover, (size_t)iter->elmt_left, maxelem);
-
- /* Initialize row sizes for each dimension */
- elem_size = iter->elmt_size;
- for(i = (int)fast_dim, acc = elem_size; i >= 0; i--) {
- slab[i] = acc;
- acc *= mem_size[i];
- } /* end for */
-
- /* Compute the initial buffer offset */
- for(u = 0, loc = 0; u < ndims; u++)
- loc += ((hsize_t)((hssize_t)iter->u.hyp.off[u] + sel_off[u])) * slab[u];
-
- /* Add a new sequence */
- off[0] = loc;
- H5_CHECKED_ASSIGN(len[0], size_t, actual_elem * elem_size, hsize_t);
-
- /* Increment sequence array locations */
- off++;
- len++;
-
- /* Advance the hyperslab iterator */
- H5S__hyper_iter_next(iter, actual_elem);
-
- /* Decrement the number of elements left in selection */
- iter->elmt_left -= actual_elem;
-
- /* Decrement element/sequence limits */
- maxelem -= actual_elem;
- maxseq--;
-
- /* Set the number of sequences generated and elements used */
- *nseq = 1;
- *nelem = actual_elem;
-
- /* Check for using up all the sequences/elements */
- if(0 == iter->elmt_left || 0 == maxelem || 0 == maxseq)
- return(SUCCEED);
- } /* end if */
- else {
- /* Reset the number of sequences generated and elements used */
- *nseq = 0;
- *nelem = 0;
- } /* end else */
-
- /* Check for a single block selected */
- single_block = TRUE;
- for(u = 0; u < ndims; u++)
- if(1 != tdiminfo[u].count) {
- single_block = FALSE;
- break;
+ else if(depth > 0)
+ /* Just count skipped elements */
+ H5S_HYPER_PROJ_INT_ADD_SKIP(udata, H5S__hyper_spans_nelem_helper((H5S_hyper_span_info_t *)ss_span_info, udata->op_gen) * count, FAIL); /* Casting away const OK -NAF */
+
+ /* Clean up if we are done */
+ if(depth == 0) {
+ /* Add remaining elements */
+ if(udata->nelem > 0)
+ if(H5S__hyper_proj_int_build_proj(udata) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't add elements to projected selection")
+
+ /* Append remaining span trees */
+ for(u = udata->ds_rank - 1; u > 0; u--)
+ if(udata->ps_span_info[u]) {
+ if(H5S__hyper_append_span(&udata->ps_span_info[u - 1],
+ udata->ds_rank - u + 1, udata->ds_low[u - 1],
+ udata->ds_low[u - 1],
+ udata->ps_span_info[u]) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+ H5S__hyper_free_span_info(udata->ps_span_info[u]);
+ udata->ps_span_info[u] = NULL;
} /* end if */
-
- /* Check for single block selection */
- if(single_block)
- /* Use single-block optimized call to generate sequence list */
- ret_value = H5S__hyper_get_seq_list_single(space, iter, maxseq, maxelem, nseq, nelem, off, len);
- else
- /* Use optimized call to generate sequence list */
- ret_value = H5S__hyper_get_seq_list_opt(space, iter, maxseq, maxelem, nseq, nelem, off, len);
} /* end if */
- else
- /* Call the general sequence generator routine */
- ret_value = H5S__hyper_get_seq_list_gen(space, iter, maxseq, maxelem, nseq, nelem, off, len);
+done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5S__hyper_get_seq_list() */
+} /* end H5S__hyper_proj_int_iterate() */
+
-
/*--------------------------------------------------------------------------
NAME
H5S__hyper_project_intersection
@@ -9251,11 +11401,12 @@ H5S__hyper_get_seq_list(const H5S_t *space, unsigned H5_ATTR_UNUSED flags, H5S_s
DESCRIPTION
Projects the intersection of of the selections of src_space and
src_intersect_space within the selection of src_space as a selection
- within the selection of dst_space. The result is placed in the
- selection of proj_space. Note src_space, dst_space, and
- src_intersect_space do not need to use hyperslab selections, but they
- cannot use point selections. The result is always a hyperslab
- selection.
+ within the selection of dst_space. The result is placed in the selection
+ of proj_space. Note src_space, dst_space, and src_intersect_space do not
+ need to use hyperslab selections, but they cannot use point selections.
+ The result is always a hyperslab or none selection. Note also that
+ proj_space can share some span trees with dst_space, so proj_space
+ must not be subsequently modified if dst_space must be preserved.
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
EXAMPLES
@@ -9265,46 +11416,11 @@ herr_t
H5S__hyper_project_intersection(const H5S_t *src_space, const H5S_t *dst_space,
const H5S_t *src_intersect_space, H5S_t *proj_space)
{
- hsize_t ss_off[H5S_PROJECT_INTERSECT_NSEQS]; /* Offset array for src_space */
- size_t ss_len[H5S_PROJECT_INTERSECT_NSEQS]; /* Length array for src_space */
- size_t ss_nseq; /* Number of sequences for src_space */
- size_t ss_nelem; /* Number of elements for src_space */
- size_t ss_i = (size_t)0; /* Index into offset/length arrays for src_space */
- hbool_t advance_ss = FALSE; /* Whether to advance ss_i on the next iteration */
- H5S_sel_iter_t *ss_iter = NULL; /* Selection iterator for src_space */
- hbool_t ss_iter_init = FALSE; /* Whether ss_iter is initialized */
- hsize_t ss_sel_off = (hsize_t)0; /* Offset within src_space selection */
- hsize_t ds_off[H5S_PROJECT_INTERSECT_NSEQS]; /* Offset array for dst_space */
- size_t ds_len[H5S_PROJECT_INTERSECT_NSEQS]; /* Length array for dst_space */
- size_t ds_nseq; /* Number of sequences for dst_space */
- size_t ds_nelem; /* Number of elements for dst_space */
- size_t ds_i = (size_t)0; /* Index into offset/length arrays for dst_space */
- H5S_sel_iter_t *ds_iter = NULL; /* Selection iterator for dst_space */
- hbool_t ds_iter_init = FALSE; /* Whether ds_iter is initialized */
- hsize_t ds_sel_off = (hsize_t)0; /* Offset within dst_space selection */
- hsize_t sis_off[H5S_PROJECT_INTERSECT_NSEQS]; /* Offset array for src_intersect_space */
- size_t sis_len[H5S_PROJECT_INTERSECT_NSEQS]; /* Length array for src_intersect_space */
- size_t sis_nseq; /* Number of sequences for src_intersect_space */
- size_t sis_nelem; /* Number of elements for src_intersect_space */
- size_t sis_i = (size_t)0; /* Index into offset/length arrays for src_intersect_space */
- hbool_t advance_sis = FALSE; /* Whether to advance sis_i on the next iteration */
- H5S_sel_iter_t *sis_iter = NULL; /* Selection iterator for src_intersect_space */
- hbool_t sis_iter_init = FALSE; /* Whether sis_iter is initialized */
- hsize_t int_sel_off; /* Offset within intersected selections (ss/sis and ds/ps) */
- size_t int_len; /* Length of segment in intersected selections */
- hsize_t proj_off; /* Segment offset in proj_space */
- size_t proj_len; /* Segment length in proj_space */
- size_t proj_len_rem; /* Remaining length in proj_space for segment */
- hsize_t proj_down_dims[H5S_MAX_RANK]; /* "Down" dimensions in proj_space */
- H5S_hyper_span_info_t *curr_span_tree[H5S_MAX_RANK]; /* Current span tree being built (in each dimension) */
- H5S_hyper_span_t *prev_span[H5S_MAX_RANK]; /* Previous span in tree (in each dimension) */
- hsize_t curr_span_up_dim[H5S_MAX_RANK]; /* "Up" dimensions for current span */
- unsigned proj_rank; /* Rank of proj_space */
- hsize_t low; /* Low value of span */
- hsize_t high; /* High value of span */
- size_t span_len; /* Length of span */
- size_t nelem; /* Number of elements returned for get_seq_list op */
- unsigned i; /* Local index variable */
+ H5S_hyper_project_intersect_ud_t udata; /* User data for subroutines */
+ const H5S_hyper_span_info_t *ss_span_info;
+ const H5S_hyper_span_info_t *ds_span_info;
+ H5S_hyper_span_info_t *ss_span_info_buf = NULL;
+ H5S_hyper_span_info_t *ds_span_info_buf = NULL;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
@@ -9314,302 +11430,99 @@ H5S__hyper_project_intersection(const H5S_t *src_space, const H5S_t *dst_space,
HDassert(dst_space);
HDassert(src_intersect_space);
HDassert(proj_space);
-
+
/* Assert that src_space and src_intersect_space have same extent and there
* are no point selections */
- HDassert(H5S_GET_EXTENT_NDIMS(src_space)
- == H5S_GET_EXTENT_NDIMS(src_intersect_space));
- HDassert(!HDmemcmp(src_space->extent.size, src_intersect_space->extent.size,
- (size_t)H5S_GET_EXTENT_NDIMS(src_space)
- * sizeof(src_space->extent.size[0])));
+ HDassert(H5S_GET_EXTENT_NDIMS(src_space) == H5S_GET_EXTENT_NDIMS(src_intersect_space));
+ HDassert(H5S_GET_SELECT_NPOINTS(src_space) == H5S_GET_SELECT_NPOINTS(dst_space));
HDassert(H5S_GET_SELECT_TYPE(src_space) != H5S_SEL_POINTS);
HDassert(H5S_GET_SELECT_TYPE(dst_space) != H5S_SEL_POINTS);
- HDassert(H5S_GET_SELECT_TYPE(src_intersect_space) != H5S_SEL_POINTS);
-
- /* Initialize prev_space, curr_span_tree, and curr_span_up_dim */
- for(i = 0; i < H5S_MAX_RANK; i++) {
- curr_span_tree[i] = NULL;
- prev_span[i] = NULL;
- curr_span_up_dim[i] = (hsize_t)0;
- } /* end for */
-
- /* Save rank of projected space */
- proj_rank = proj_space->extent.rank;
- HDassert(proj_rank > 0);
-
- /* Get numbers of elements */
- ss_nelem = (size_t)H5S_GET_SELECT_NPOINTS(src_space);
- ds_nelem = (size_t)H5S_GET_SELECT_NPOINTS(dst_space);
- sis_nelem = (size_t)H5S_GET_SELECT_NPOINTS(src_intersect_space);
- HDassert(ss_nelem == ds_nelem);
-
- /* Calculate proj_down_dims (note loop relies on unsigned i wrapping around)
- */
- if(H5VM_array_down(proj_rank, proj_space->extent.size, proj_down_dims) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't compute 'down' chunk size value")
+ HDassert(H5S_GET_SELECT_TYPE(src_intersect_space) == H5S_SEL_HYPERSLABS);
- /* Remove current selection from proj_space */
- if(H5S_SELECT_RELEASE(proj_space) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release selection")
-
- /* If any selections are empty, skip to the end so "none" is selected */
- if((ss_nelem == 0) || (ds_nelem == 0) || (sis_nelem == 0))
- goto loop_end;
-
- /* Allocate space for the hyperslab selection information (note this sets
- * diminfo_valid to FALSE, diminfo arrays to 0, and span list to NULL) */
- if((proj_space->select.sel_info.hslab = H5FL_CALLOC(H5S_hyper_sel_t)) == NULL)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate hyperslab info")
-
- /* Set selection type */
- proj_space->select.type = H5S_sel_hyper;
+ /* Set up ss_span_info */
+ if(H5S_GET_SELECT_TYPE(src_space) == H5S_SEL_HYPERSLABS) {
+ /* Make certain the selection has a span tree */
+ if(NULL == src_space->select.sel_info.hslab->span_lst)
+ if(H5S__hyper_generate_spans((H5S_t *)src_space) < 0) /* Casting away const OK -NAF */
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "can't construct span tree for source hyperslab selection")
- /* Set unlim_dim */
- proj_space->select.sel_info.hslab->unlim_dim = -1;
-
- /* Allocate the source space iterator */
- if(NULL == (ss_iter = H5FL_MALLOC(H5S_sel_iter_t)))
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate source space iterator")
-
- /* Initialize source space iterator */
- if(H5S_select_iter_init(ss_iter, src_space, (size_t)1) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator")
- ss_iter_init = TRUE;
-
- /* Get sequence list for source space */
- if(H5S_SELECT_GET_SEQ_LIST(src_space, 0u, ss_iter, H5S_PROJECT_INTERSECT_NSEQS, ss_nelem, &ss_nseq, &nelem, ss_off, ss_len) < 0)
- HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed")
- ss_nelem -= nelem;
- HDassert(ss_nseq > 0);
-
- /* Allocate the destination space iterator */
- if(NULL == (ds_iter = H5FL_MALLOC(H5S_sel_iter_t)))
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate destination space iterator")
-
- /* Initialize destination space iterator */
- if(H5S_select_iter_init(ds_iter, dst_space, (size_t)1) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator")
- ds_iter_init = TRUE;
-
- /* Get sequence list for destination space */
- if(H5S_SELECT_GET_SEQ_LIST(dst_space, 0u, ds_iter, H5S_PROJECT_INTERSECT_NSEQS, ds_nelem, &ds_nseq, &nelem, ds_off, ds_len) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator")
- ds_nelem -= nelem;
- HDassert(ds_nseq > 0);
-
- /* Allocate the source intersect space iterator */
- if(NULL == (sis_iter = H5FL_MALLOC(H5S_sel_iter_t)))
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate source intersect space iterator")
-
- /* Initialize source intersect space iterator */
- if(H5S_select_iter_init(sis_iter, src_intersect_space, (size_t)1) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator")
- sis_iter_init = TRUE;
-
- /* Get sequence list for source intersect space */
- if(H5S_SELECT_GET_SEQ_LIST(src_intersect_space, 0u, sis_iter, H5S_PROJECT_INTERSECT_NSEQS, sis_nelem, &sis_nseq, &nelem, sis_off, sis_len) < 0)
- HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed")
- sis_nelem -= nelem;
- HDassert(sis_nseq > 0);
-
- /* Loop until we run out of sequences in either the source or source
- * intersect space */
- while(1) {
- while(advance_ss || (ss_off[ss_i] + ss_len[ss_i] <= sis_off[sis_i])) {
- /* Either we finished the current source sequence or the
- * sequences do not intersect. Advance source space. */
- ss_sel_off += (hsize_t)ss_len[ss_i];
- if(++ss_i == ss_nseq) {
- if(ss_nelem > 0) {
- /* Try to grab more sequences from src_space */
- if(H5S_SELECT_GET_SEQ_LIST(src_space, 0u, ss_iter, H5S_PROJECT_INTERSECT_NSEQS, ss_nelem, &ss_nseq, &nelem, ss_off, ss_len) < 0)
- HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed")
- HDassert(ss_len[0] > 0);
-
- /* Update ss_nelem */
- HDassert(nelem > 0);
- HDassert(nelem <= ss_nelem);
- ss_nelem -= nelem;
-
- /* Reset source space index */
- ss_i = 0;
- } /* end if */
- else
- /* There are no more sequences in src_space, so we can exit
- * the loop. Use goto instead of break so we exit the outer
- * loop. */
- goto loop_end;
- } /* end if */
-
- /* Reset advance_ss */
- advance_ss = FALSE;
- } /* end if */
- if(advance_sis
- || (sis_off[sis_i] + sis_len[sis_i] <= ss_off[ss_i])) {
- do {
- /* Either we finished the current source intersect sequence or
- * the sequences do not intersect. Advance source intersect
- * space. */
- if(++sis_i == sis_nseq) {
- if(sis_nelem > 0) {
- /* Try to grab more sequences from src_intersect_space
- */
- if(H5S_SELECT_GET_SEQ_LIST(src_intersect_space, 0u, sis_iter, H5S_PROJECT_INTERSECT_NSEQS, sis_nelem, &sis_nseq, &nelem, sis_off, sis_len) < 0)
- HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed")
- HDassert(sis_len[0] > 0);
-
- /* Update ss_nelem */
- HDassert(nelem > 0);
- HDassert(nelem <= sis_nelem);
- sis_nelem -= nelem;
-
- /* Reset source space index */
- sis_i = 0;
- } /* end if */
- else
- /* There are no more sequences in src_intersect_space,
- * so we can exit the loop. Use goto instead of break
- * so we exit the outer loop. */
- goto loop_end;
- } /* end if */
- } while(sis_off[sis_i] + sis_len[sis_i] <= ss_off[ss_i]);
+ /* Simply point to existing span tree */
+ ss_span_info = src_space->select.sel_info.hslab->span_lst;
+ } /* end if */
+ else {
+ /* Create temporary span tree from all selection */
+ HDassert(H5S_GET_SELECT_TYPE(src_space) == H5S_SEL_ALL);
- /* Reset advance_sis */
- advance_sis = FALSE;
- } /* end if */
- else {
- /* Sequences intersect, add intersection to projected space */
- /* Calculate intersection sequence in terms of offset within source
- * selection and advance any sequences we complete */
- if(ss_off[ss_i] >= sis_off[sis_i])
- int_sel_off = ss_sel_off;
- else
- int_sel_off = sis_off[sis_i] - ss_off[ss_i] + ss_sel_off;
- if((ss_off[ss_i] + (hsize_t)ss_len[ss_i]) <= (sis_off[sis_i]
- + (hsize_t)sis_len[sis_i])) {
- int_len = (size_t)((hsize_t)ss_len[ss_i] + ss_sel_off - int_sel_off);
- advance_ss = TRUE;
- } /* end if */
- else
- int_len = (size_t)(sis_off[sis_i] + (hsize_t)sis_len[sis_i] - ss_off[ss_i] + ss_sel_off - int_sel_off);
- if((ss_off[ss_i] + (hsize_t)ss_len[ss_i]) >= (sis_off[sis_i]
- + (hsize_t)sis_len[sis_i]))
- advance_sis = TRUE;
-
- /* Project intersection sequence to destination selection */
- while(int_len > (size_t)0) {
- while(ds_sel_off + (hsize_t)ds_len[ds_i] <= int_sel_off) {
- /* Intersection is not projected to this destination
- * sequence, advance destination space */
- ds_sel_off += (hsize_t)ds_len[ds_i];
- if(++ds_i == ds_nseq) {
- HDassert(ds_nelem > 0);
-
- /* Try to grab more sequences from dst_space */
- if(H5S_SELECT_GET_SEQ_LIST(dst_space, 0u, ds_iter, H5S_PROJECT_INTERSECT_NSEQS, ds_nelem, &ds_nseq, &nelem, ds_off, ds_len) < 0)
- HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed")
- HDassert(ds_len[0] > 0);
-
- /* Update ss_nelem */
- HDassert(nelem > 0);
- HDassert(nelem <= ds_nelem);
- ds_nelem -= nelem;
-
- /* Reset source space index */
- ds_i = 0;
- } /* end if */
- } /* end while */
+ if(NULL == (ss_span_info_buf = H5S__hyper_make_spans(H5S_GET_EXTENT_NDIMS(src_space),
+ H5S_hyper_zeros_g, H5S_hyper_zeros_g, H5S_hyper_ones_g, src_space->extent.size)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't create span tree for ALL source space")
+ ss_span_info = ss_span_info_buf;
+ } /* end else */
- /* Add sequence to projected space */
- HDassert(ds_sel_off <= int_sel_off);
- proj_off = ds_off[ds_i] + int_sel_off - ds_sel_off;
- proj_len = proj_len_rem = (size_t)MIN(int_len,
- (size_t)(ds_sel_off + (hsize_t)ds_len[ds_i]
- - int_sel_off));
-
- /* Add to span tree */
- while(proj_len_rem > (size_t)0) {
- /* Check for more than one full row (in every dim) and
- * append multiple spans at once? -NAF */
- /* Append spans in higher dimensions if we're going ouside
- * the plane of the span currently being built (i.e. it's
- * finished being built) */
- for(i = proj_rank - 1; ((i > 0)
- && ((proj_off / proj_down_dims[i - 1])
- != curr_span_up_dim[i - 1])); i--) {
- if(curr_span_tree[i]) {
- HDassert(prev_span[i]);
-
- /* Append complete lower dimension span tree to
- * current dimension */
- low = curr_span_up_dim[i - 1] % proj_space->extent.size[i - 1];
- if(H5S__hyper_append_span(&prev_span[i - 1], &curr_span_tree[i - 1], low, low, curr_span_tree[i], NULL) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+ /* Set up ds_span_info */
+ if(H5S_GET_SELECT_TYPE(dst_space) == H5S_SEL_HYPERSLABS) {
+ /* Make certain the selection has a span tree */
+ if(NULL == dst_space->select.sel_info.hslab->span_lst)
+ if(H5S__hyper_generate_spans((H5S_t *)dst_space) < 0) /* Casting away const OK -NAF */
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "can't construct span tree for dsetination hyperslab selection")
- /* Reset lower dimension's span tree and previous
- * span since we just committed it and will start
- * over with a new one */
- if(H5S__hyper_free_span_info(curr_span_tree[i]) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTFREE, FAIL, "can't free span info")
- curr_span_tree[i] = NULL;
- prev_span[i] = NULL;
- } /* end if */
+ /* Simply point to existing span tree */
+ ds_span_info = dst_space->select.sel_info.hslab->span_lst;
+ } /* end if */
+ else {
+ /* Create temporary span tree from all selection */
+ HDassert(H5S_GET_SELECT_TYPE(dst_space) == H5S_SEL_ALL);
- /* Update curr_span_up_dim */
- curr_span_up_dim[i - 1] = proj_off / proj_down_dims[i - 1];
- } /* end for */
+ if(NULL == (ds_span_info_buf = H5S__hyper_make_spans(H5S_GET_EXTENT_NDIMS(dst_space),
+ H5S_hyper_zeros_g, H5S_hyper_zeros_g, H5S_hyper_ones_g, dst_space->extent.size)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't create span tree for ALL destination space")
+ ds_span_info = ds_span_info_buf;
+ } /* end else */
- /* Compute bounds for new span in lowest dimension */
- low = proj_off % proj_space->extent.size[proj_rank - 1];
- span_len = MIN(proj_len_rem,
- (size_t)(proj_space->extent.size[proj_rank - 1]
- - low));
- HDassert(proj_len_rem >= span_len);
- high = low + (hsize_t)span_len - (hsize_t)1;
+ /* Make certain the source intersect selection has a span tree */
+ if(NULL == src_intersect_space->select.sel_info.hslab->span_lst)
+ if(H5S__hyper_generate_spans((H5S_t *)src_intersect_space) < 0) /* Casting away const OK -NAF */
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "can't construct span tree for source intersect hyperslab selection")
- /* Append span in lowest dimension */
- if(H5S__hyper_append_span(&prev_span[proj_rank - 1], &curr_span_tree[proj_rank - 1], low, high, NULL, NULL) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+ /* Initialize udata */
+ HDmemset(&udata, 0, sizeof(udata));
+ udata.ds_span[0] = ds_span_info->head;
+ udata.ds_low[0] = udata.ds_span[0]->low;
+ udata.ss_rank = H5S_GET_EXTENT_NDIMS(src_space);
+ udata.ds_rank = H5S_GET_EXTENT_NDIMS(dst_space);
+ udata.op_gen = H5S__hyper_get_op_gen();
- /* Update remaining offset and length */
- proj_off += (hsize_t)span_len;
- proj_len_rem -= span_len;
- } /* end while */
+ /* Iterate over selections and build projected span tree */
+ if(H5S__hyper_proj_int_iterate(ss_span_info, src_intersect_space->select.sel_info.hslab->span_lst, 1, 0, &udata) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOMPARE, FAIL, "selection iteration failed")
- /* Update intersection sequence */
- int_sel_off += (hsize_t)proj_len;
- int_len -= proj_len;
- } /* end while */
- } /* end else */
- } /* end while */
+ /* Remove current selection from proj_space */
+ if(H5S_SELECT_RELEASE(proj_space) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release selection")
-loop_end:
- /* Add remaining spans to span tree */
- for(i = proj_rank - 1; i > 0; i--)
- if(curr_span_tree[i]) {
- HDassert(prev_span[i]);
+ /* Check for elements in projected space */
+ if(udata.ps_span_info[0]) {
+ /* Allocate space for the hyperslab selection information (note this sets
+ * diminfo_valid to FALSE, diminfo arrays to 0, and span list to NULL) */
+ if(NULL == (proj_space->select.sel_info.hslab = H5FL_CALLOC(H5S_hyper_sel_t)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate hyperslab info")
- /* Append remaining span tree to higher dimension */
- low = curr_span_up_dim[i - 1] % proj_space->extent.size[i - 1];
- if(H5S__hyper_append_span(&prev_span[i - 1], &curr_span_tree[i - 1], low, low, curr_span_tree[i], NULL) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+ /* Set selection type */
+ proj_space->select.type = H5S_sel_hyper;
- /* Reset span tree */
- if(H5S__hyper_free_span_info(curr_span_tree[i]) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTFREE, FAIL, "can't free span info")
- curr_span_tree[i] = NULL;
- } /* end if */
+ /* Set unlim_dim */
+ proj_space->select.sel_info.hslab->unlim_dim = -1;
- /* Add span tree to proj_space */
- if(curr_span_tree[0]) {
- proj_space->select.sel_info.hslab->span_lst = curr_span_tree[0];
- curr_span_tree[0] = NULL;
+ /* Set span tree */
+ proj_space->select.sel_info.hslab->span_lst = udata.ps_span_info[0];
+ udata.ps_span_info[0] = NULL;
/* Set the number of elements in current selection */
proj_space->select.num_elem = H5S__hyper_spans_nelem(proj_space->select.sel_info.hslab->span_lst);
- /* Attempt to rebuild "optimized" start/stride/count/block information.
- * from resulting hyperslab span tree */
+ /* Attempt to build "optimized" start/stride/count/block information
+ * from resulting hyperslab span tree.
+ */
H5S__hyper_rebuild(proj_space);
} /* end if */
else
@@ -9618,155 +11531,44 @@ loop_end:
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't convert selection")
done:
- /* Release source selection iterator */
- if(ss_iter_init && H5S_SELECT_ITER_RELEASE(ss_iter) < 0)
- HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator")
- if(ss_iter)
- ss_iter = H5FL_FREE(H5S_sel_iter_t, ss_iter);
-
- /* Release destination selection iterator */
- if(ds_iter_init && H5S_SELECT_ITER_RELEASE(ds_iter) < 0)
- HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator")
- if(ds_iter)
- ds_iter = H5FL_FREE(H5S_sel_iter_t, ds_iter);
-
- /* Release source intersect selection iterator */
- if(sis_iter_init && H5S_SELECT_ITER_RELEASE(sis_iter) < 0)
- HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator")
- if(sis_iter)
- sis_iter = H5FL_FREE(H5S_sel_iter_t, sis_iter);
+ /* Free ss_span_info_buf */
+ if(ss_span_info_buf) {
+ H5S__hyper_free_span_info(ss_span_info_buf);
+ ss_span_info_buf = NULL;
+ } /* end if */
+
+ /* Free ds_span_info_buf */
+ if(ds_span_info_buf) {
+ H5S__hyper_free_span_info(ds_span_info_buf);
+ ds_span_info_buf = NULL;
+ } /* end if */
/* Cleanup on error */
if(ret_value < 0) {
- /* Remove current selection from proj_space */
- if(H5S_SELECT_RELEASE(proj_space) < 0)
- HDONE_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release selection")
+ unsigned u;
/* Free span trees */
- for(i = 0; i < proj_rank; i++)
- if(curr_span_tree[i]) {
- if(H5S__hyper_free_span_info(curr_span_tree[i]) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTFREE, FAIL, "can't free span info")
- curr_span_tree[i] = NULL;
+ for(u = 0; u < udata.ds_rank; u++)
+ if(udata.ps_span_info[u]) {
+ H5S__hyper_free_span_info(udata.ps_span_info[u]);
+ udata.ps_span_info[u] = NULL;
} /* end if */
} /* end if */
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5S__hyper_project_intersection() */
-
-
-/*--------------------------------------------------------------------------
- NAME
- H5S__hyper_subtract
- PURPOSE
- Subtract one hyperslab selection from another
- USAGE
- herr_t H5S__hyper_subtract(space,subtract_space)
- H5S_t *space; IN/OUT: Selection to be operated on
- H5S_t *subtract_space; IN: Selection that will be subtracted from space
- RETURNS
- Non-negative on success/Negative on failure.
- DESCRIPTION
- Removes any and all portions of space that are also present in
- subtract_space. In essence, performs an A_NOT_B operation with the
- two selections.
-
- Note this function basically duplicates a subset of the functionality
- of H5S_select_select(). It should probably be removed when that
- function is enabled.
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
-herr_t
-H5S__hyper_subtract(H5S_t *space, H5S_t *subtract_space)
-{
- H5S_hyper_span_info_t *a_not_b = NULL; /* Span tree for hyperslab spans in old span tree and not in new span tree */
- H5S_hyper_span_info_t *a_and_b = NULL; /* Span tree for hyperslab spans in both old and new span trees */
- H5S_hyper_span_info_t *b_not_a = NULL; /* Span tree for hyperslab spans in new span tree and not in old span tree */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT
-
- /* Check args */
- HDassert(space);
- HDassert(subtract_space);
-
- /* Check that the space selections both have span trees */
- if(space->select.sel_info.hslab->span_lst == NULL)
- if(H5S__hyper_generate_spans(space) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "dataspace does not have span tree")
- if(subtract_space->select.sel_info.hslab->span_lst == NULL)
- if(H5S__hyper_generate_spans(subtract_space) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "dataspace does not have span tree")
-
- /* Generate lists of spans which overlap and don't overlap */
- if(H5S__hyper_clip_spans(space->select.sel_info.hslab->span_lst, subtract_space->select.sel_info.hslab->span_lst, &a_not_b, &a_and_b, &b_not_a)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL, "can't clip hyperslab information")
-
- /* Reset the other dataspace selection information */
- if(H5S_SELECT_RELEASE(space) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release selection")
-
- /* Allocate space for the hyperslab selection information */
- if((space->select.sel_info.hslab = H5FL_CALLOC(H5S_hyper_sel_t)) == NULL)
- HGOTO_ERROR(H5E_DATASPACE, H5E_NOSPACE, FAIL, "can't allocate hyperslab info")
-
- /* Set unlim_dim */
- space->select.sel_info.hslab->unlim_dim = -1;
-
- /* Check for anything returned in a_not_b */
- if(a_not_b) {
- /* Update spans in space */
- space->select.sel_info.hslab->span_lst = a_not_b;
- a_not_b = NULL;
-
- /* Update number of elements */
- space->select.num_elem = H5S__hyper_spans_nelem(space->select.sel_info.hslab->span_lst);
-
- /* Attempt to rebuild "optimized" start/stride/count/block information.
- * from resulting hyperslab span tree */
- H5S__hyper_rebuild(space);
- } /* end if */
- else {
- H5S_hyper_span_info_t *spans; /* Empty hyperslab span tree */
-
- /* Set number of elements */
- space->select.num_elem = 0;
-
- /* Allocate a span info node */
- if(NULL == (spans = H5FL_MALLOC(H5S_hyper_span_info_t)))
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate hyperslab span")
-
- /* Set the reference count */
- spans->count = 1;
-
- /* Reset the scratch pad space */
- spans->scratch = 0;
+#ifndef NDEBUG
+ /* Verify there are no more span trees */
+ {
+ unsigned u;
- /* Set to empty tree */
- spans->head = NULL;
-
- /* Set pointer to empty span tree */
- space->select.sel_info.hslab->span_lst = spans;
- } /* end if */
-
-done:
- /* Free span trees */
- if(a_and_b)
- H5S__hyper_free_span_info(a_and_b);
- if(b_not_a)
- H5S__hyper_free_span_info(b_not_a);
- if(a_not_b) {
- HDassert(ret_value < 0);
- H5S__hyper_free_span_info(b_not_a);
- } /* end if */
+ for(u = 0; u < H5S_MAX_RANK; u++)
+ HDassert(!udata.ps_span_info[u]);
+ } /* end block */
+#endif /* NDEBUG */
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5S__hyper_subtract() */
+} /* end H5S__hyper_project_intersection() */
+
-
/*--------------------------------------------------------------------------
NAME
H5S__hyper_get_clip_diminfo
@@ -9791,11 +11593,11 @@ done:
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-void
+static void
H5S__hyper_get_clip_diminfo(hsize_t start, hsize_t stride, hsize_t *count,
hsize_t *block, hsize_t clip_size)
{
- FUNC_ENTER_PACKAGE_NOERR
+ FUNC_ENTER_STATIC_NOERR
/* Check for selection outside clip size */
if(start >= clip_size) {
@@ -9819,9 +11621,9 @@ H5S__hyper_get_clip_diminfo(hsize_t start, hsize_t stride, hsize_t *count,
} /* end else */
FUNC_LEAVE_NOAPI_VOID
-} /* end H5S_hyper_get_clip_diminfo() */
+} /* end H5S__hyper_get_clip_diminfo() */
+
-
/*--------------------------------------------------------------------------
NAME
H5S_hyper_clip_unlim
@@ -9835,9 +11637,8 @@ H5S__hyper_get_clip_diminfo(hsize_t start, hsize_t stride, hsize_t *count,
RETURNS
Non-negative on success/Negative on failure.
DESCRIPTION
- This function changes the unlimited selection into a limited selection
- with the extent of the formerly unlimited dimension specified by
- * clip_size.
+ This function changes the unlimited selection into a fixed-dimension selection
+ with the extent of the formerly unlimited dimension specified by clip_size.
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
Note this function does not take the offset into account.
@@ -9847,11 +11648,11 @@ H5S__hyper_get_clip_diminfo(hsize_t start, hsize_t stride, hsize_t *count,
herr_t
H5S_hyper_clip_unlim(H5S_t *space, hsize_t clip_size)
{
- H5S_hyper_sel_t *hslab; /* Convenience pointer to hyperslab info */
- hsize_t orig_count; /* Original count in unlimited dimension */
- int orig_unlim_dim; /* Original unliminted dimension */
- H5S_hyper_dim_t *diminfo; /* Convenience pointer to opt_diminfo in unlimited dimension */
- herr_t ret_value = SUCCEED;
+ H5S_hyper_sel_t *hslab = NULL; /* Convenience pointer to hyperslab info */
+ hsize_t orig_count; /* Original count in unlimited dimension */
+ int orig_unlim_dim; /* Original unliminted dimension */
+ H5S_hyper_dim_t *diminfo = NULL; /* Convenience pointer to diminfo.opt in unlimited dimension */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
@@ -9865,7 +11666,8 @@ H5S_hyper_clip_unlim(H5S_t *space, hsize_t clip_size)
/* Save original unlimited dimension */
orig_unlim_dim = hslab->unlim_dim;
- diminfo = &hslab->opt_diminfo[orig_unlim_dim];
+ /* Set up convenience pointer */
+ diminfo = &hslab->diminfo.opt[orig_unlim_dim];
/* Save original count in unlimited dimension */
orig_count = diminfo->count;
@@ -9881,19 +11683,22 @@ H5S_hyper_clip_unlim(H5S_t *space, hsize_t clip_size)
/* Convert to "none" selection */
if(H5S_select_none(space) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't convert selection")
+
+ /* Reset the convenience pointers */
+ hslab = NULL;
+ diminfo = NULL;
} /* end if */
/* Check for single block in unlimited dimension */
else if(orig_count == (hsize_t)1) {
/* Calculate number of elements */
space->select.num_elem = diminfo->block * hslab->num_elem_non_unlim;
- /* Mark that opt_diminfo is valid */
- hslab->diminfo_valid = TRUE;
+ /* Mark that diminfo.opt is valid */
+ hslab->diminfo_valid = H5S_DIMINFO_VALID_YES;
} /* end if */
else {
/* Calculate number of elements */
- space->select.num_elem = diminfo->count * diminfo->block
- * hslab->num_elem_non_unlim;
+ space->select.num_elem = diminfo->count * diminfo->block * hslab->num_elem_non_unlim;
/* Check if last block is partial. If superset is set, just keep the
* last block complete to speed computation. */
@@ -9902,7 +11707,7 @@ H5S_hyper_clip_unlim(H5S_t *space, hsize_t clip_size)
> (clip_size - diminfo->start)) {
hsize_t start[H5S_MAX_RANK];
hsize_t block[H5S_MAX_RANK];
- unsigned i;
+ unsigned u;
/* Last block is partial, need to construct compound selection */
/* Fill start with zeros */
@@ -9910,11 +11715,11 @@ H5S_hyper_clip_unlim(H5S_t *space, hsize_t clip_size)
/* Set block to clip_size in unlimited dimension, H5S_MAX_SIZE in
* others so only unlimited dimension is clipped */
- for(i = 0; i < space->extent.rank; i++)
- if((int)i == orig_unlim_dim)
- block[i] = clip_size;
+ for(u = 0; u < space->extent.rank; u++)
+ if((int)u == orig_unlim_dim)
+ block[u] = clip_size;
else
- block[i] = H5S_MAX_SIZE;
+ block[u] = H5S_MAX_SIZE;
/* Generate span tree in selection */
if(!hslab->span_lst)
@@ -9922,23 +11727,29 @@ H5S_hyper_clip_unlim(H5S_t *space, hsize_t clip_size)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to generate span tree")
/* Indicate that the regular dimensions are no longer valid */
- hslab->diminfo_valid = FALSE;
+ hslab->diminfo_valid = H5S_DIMINFO_VALID_NO;
- /* "And" selection with calculated block to perform clip operation
- */
+ /* "And" selection with calculated block to perform clip operation */
if(H5S__generate_hyperslab(space, H5S_SELECT_AND, start, H5S_hyper_ones_g, H5S_hyper_ones_g, block) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't generate hyperslabs")
} /* end if */
else
- /* Last block is complete, simply mark that opt_diminfo is valid */
- hslab->diminfo_valid = TRUE;
+ /* Last block is complete, simply mark that diminfo.opt is valid */
+ hslab->diminfo_valid = H5S_DIMINFO_VALID_YES;
} /* end else */
+ /* Update the upper bound, if the diminfo is valid */
+ if(hslab && (H5S_DIMINFO_VALID_YES == hslab->diminfo_valid))
+ hslab->diminfo.high_bounds[orig_unlim_dim] =
+ hslab->diminfo.opt[orig_unlim_dim].start +
+ hslab->diminfo.opt[orig_unlim_dim].stride * (hslab->diminfo.opt[orig_unlim_dim].count - 1) +
+ (hslab->diminfo.opt[orig_unlim_dim].block - 1);
+
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_hyper_clip_unlim() */
-
+
/*--------------------------------------------------------------------------
NAME
H5S__hyper_get_clip_extent_real
@@ -9982,7 +11793,7 @@ H5S__hyper_get_clip_extent_real(const H5S_t *clip_space, hsize_t num_slices,
HDassert(clip_space->select.sel_info.hslab);
HDassert(clip_space->select.sel_info.hslab->unlim_dim >= 0);
- diminfo = &clip_space->select.sel_info.hslab->opt_diminfo[clip_space->select.sel_info.hslab->unlim_dim];
+ diminfo = &clip_space->select.sel_info.hslab->diminfo.opt[clip_space->select.sel_info.hslab->unlim_dim];
if(num_slices == 0)
ret_value = incl_trail ? diminfo->start : 0;
@@ -10020,7 +11831,7 @@ H5S__hyper_get_clip_extent_real(const H5S_t *clip_space, hsize_t num_slices,
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S__hyper_get_clip_extent_real() */
-
+
/*--------------------------------------------------------------------------
NAME
H5S_hyper_get_clip_extent
@@ -10083,7 +11894,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_hyper_get_clip_extent() */
-
+
/*--------------------------------------------------------------------------
NAME
H5S_hyper_get_clip_extent_match
@@ -10136,7 +11947,7 @@ H5S_hyper_get_clip_extent_match(const H5S_t *clip_space,
HDassert(clip_space->select.sel_info.hslab->num_elem_non_unlim
== match_space->select.sel_info.hslab->num_elem_non_unlim);
- match_diminfo = &match_space->select.sel_info.hslab->opt_diminfo[match_space->select.sel_info.hslab->unlim_dim];
+ match_diminfo = &match_space->select.sel_info.hslab->diminfo.opt[match_space->select.sel_info.hslab->unlim_dim];
/* Get initial count and block */
count = match_diminfo->count;
@@ -10173,7 +11984,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_hyper_get_clip_extent_match() */
-
+
/*--------------------------------------------------------------------------
NAME
H5S_hyper_get_unlim_block
@@ -10200,13 +12011,13 @@ H5S_t *
H5S_hyper_get_unlim_block(const H5S_t *space, hsize_t block_index)
{
H5S_hyper_sel_t *hslab; /* Convenience pointer to hyperslab info */
- H5S_t *space_out = NULL;
- hsize_t start[H5S_MAX_RANK];
+ H5S_t *space_out = NULL; /* Dataspace to return */
+ hsize_t start[H5S_MAX_RANK];/* Hyperslab selection info for unlim. selection */
hsize_t stride[H5S_MAX_RANK];
hsize_t count[H5S_MAX_RANK];
hsize_t block[H5S_MAX_RANK];
- unsigned i;
- H5S_t *ret_value = NULL;
+ unsigned u; /* Local index variable */
+ H5S_t *ret_value = NULL; /* Return value */
FUNC_ENTER_NOAPI(NULL)
@@ -10215,29 +12026,29 @@ H5S_hyper_get_unlim_block(const H5S_t *space, hsize_t block_index)
hslab = space->select.sel_info.hslab;
HDassert(hslab);
HDassert(hslab->unlim_dim >= 0);
- HDassert(hslab->opt_diminfo[hslab->unlim_dim].count == H5S_UNLIMITED);
+ HDassert(hslab->diminfo.opt[hslab->unlim_dim].count == H5S_UNLIMITED);
/* Set start to select block_indexth block in unlimited dimension and set
* count to 1 in that dimension to only select that block. Copy all other
* diminfo parameters. */
- for(i = 0; i < space->extent.rank; i++) {
- if((int)i == hslab->unlim_dim){
- start[i] = hslab->opt_diminfo[i].start + (block_index
- * hslab->opt_diminfo[i].stride);
- count[i] = (hsize_t)1;
+ for(u = 0; u < space->extent.rank; u++) {
+ if((int)u == hslab->unlim_dim){
+ start[u] = hslab->diminfo.opt[u].start + (block_index
+ * hslab->diminfo.opt[u].stride);
+ count[u] = (hsize_t)1;
} /* end if */
else {
- start[i] = hslab->opt_diminfo[i].start;
- count[i] = hslab->opt_diminfo[i].count;
+ start[u] = hslab->diminfo.opt[u].start;
+ count[u] = hslab->diminfo.opt[u].count;
} /* end else */
- stride[i] = hslab->opt_diminfo[i].stride;
- block[i] = hslab->opt_diminfo[i].block;
+ stride[u] = hslab->diminfo.opt[u].stride;
+ block[u] = hslab->diminfo.opt[u].block;
} /* end for */
/* Create output space, copy extent */
if(NULL == (space_out = H5S_create(H5S_SIMPLE)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, NULL, "unable to create output dataspace")
- if(H5S_extent_copy_real(&space_out->extent, &space->extent, TRUE) < 0)
+ if(H5S__extent_copy_real(&space_out->extent, &space->extent, TRUE) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, NULL, "unable to copy destination space extent")
/* Select block as defined by start/stride/count/block computed above */
@@ -10256,7 +12067,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_hyper_get_unlim_block */
-
+
/*--------------------------------------------------------------------------
NAME
H5S_hyper_get_first_inc_block
@@ -10286,7 +12097,7 @@ H5S_hyper_get_first_inc_block(const H5S_t *space, hsize_t clip_size,
hbool_t *partial)
{
H5S_hyper_sel_t *hslab; /* Convenience pointer to hyperslab info */
- H5S_hyper_dim_t *diminfo; /* Convenience pointer to opt_diminfo in unlimited dimension */
+ H5S_hyper_dim_t *diminfo; /* Convenience pointer to diminfo.opt in unlimited dimension */
hsize_t ret_value = 0;
FUNC_ENTER_NOAPI(0)
@@ -10296,9 +12107,9 @@ H5S_hyper_get_first_inc_block(const H5S_t *space, hsize_t clip_size,
hslab = space->select.sel_info.hslab;
HDassert(hslab);
HDassert(hslab->unlim_dim >= 0);
- HDassert(hslab->opt_diminfo[hslab->unlim_dim].count == H5S_UNLIMITED);
+ HDassert(hslab->diminfo.opt[hslab->unlim_dim].count == H5S_UNLIMITED);
- diminfo = &hslab->opt_diminfo[hslab->unlim_dim];
+ diminfo = &hslab->diminfo.opt[hslab->unlim_dim];
/* Check for selection outside of clip_size */
if(diminfo->start >= clip_size) {
@@ -10324,7 +12135,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_hyper_get_first_inc_block */
-
+
/*--------------------------------------------------------------------------
NAME
H5Sis_regular_hyperslab
@@ -10364,12 +12175,12 @@ H5Sis_regular_hyperslab(hid_t spaceid)
done:
FUNC_LEAVE_API(ret_value)
-} /* H5Sis_regular_hyperslab() */
+} /* end H5Sis_regular_hyperslab() */
+
-
/*--------------------------------------------------------------------------
NAME
- H5Sgetregular_hyperslab
+ H5Sget_regular_hyperslab
PURPOSE
Retrieve a regular hyperslab selection
USAGE
@@ -10415,18 +12226,18 @@ H5Sget_regular_hyperslab(hid_t spaceid, hsize_t start[], hsize_t stride[],
/* Retrieve hyperslab parameters */
if(start)
for(u = 0; u < space->extent.rank; u++)
- start[u] = space->select.sel_info.hslab->app_diminfo[u].start;
+ start[u] = space->select.sel_info.hslab->diminfo.app[u].start;
if(stride)
for(u = 0; u < space->extent.rank; u++)
- stride[u] = space->select.sel_info.hslab->app_diminfo[u].stride;
+ stride[u] = space->select.sel_info.hslab->diminfo.app[u].stride;
if(count)
for(u = 0; u < space->extent.rank; u++)
- count[u] = space->select.sel_info.hslab->app_diminfo[u].count;
+ count[u] = space->select.sel_info.hslab->diminfo.app[u].count;
if(block)
for(u = 0; u < space->extent.rank; u++)
- block[u] = space->select.sel_info.hslab->app_diminfo[u].block;
+ block[u] = space->select.sel_info.hslab->diminfo.app[u].block;
done:
FUNC_LEAVE_API(ret_value)
-} /* H5Sget_regular_hyperslab() */
+} /* end H5Sget_regular_hyperslab() */
diff --git a/src/H5Smpio.c b/src/H5Smpio.c
index 2bd275a..f605a8a 100644
--- a/src/H5Smpio.c
+++ b/src/H5Smpio.c
@@ -14,90 +14,101 @@
/*
* Programmer: rky 980813
*
- * Purpose: Functions to read/write directly between app buffer and file.
+ * Purpose: Create MPI data types for HDF5 selections.
*
- * Beware of the ifdef'ed print statements.
- * I didn't make them portable.
*/
+/****************/
+/* Module Setup */
+/****************/
+
#include "H5Smodule.h" /* This source code file is part of the H5S module */
+/***********/
+/* Headers */
+/***********/
#include "H5private.h" /* Generic Functions */
#include "H5Dprivate.h" /* Datasets */
#include "H5Eprivate.h" /* Error handling */
-#include "H5Fprivate.h" /* File access */
-#include "H5FDprivate.h" /* File drivers */
-#include "H5Iprivate.h" /* IDs */
+#include "H5FLprivate.h" /* Free Lists */
#include "H5MMprivate.h" /* Memory management */
-#include "H5Oprivate.h" /* Object headers */
-#include "H5Pprivate.h" /* Property lists */
#include "H5Spkg.h" /* Dataspaces */
#include "H5VMprivate.h" /* Vector and array functions */
#ifdef H5_HAVE_PARALLEL
-static herr_t H5S_mpio_all_type(const H5S_t *space, size_t elmt_size,
+/****************/
+/* Local Macros */
+/****************/
+#define H5S_MPIO_INITIAL_ALLOC_COUNT 256
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+/* Node in linked list of MPI data types created during traversal of irregular hyperslab selection */
+typedef struct H5S_mpio_mpitype_node_t {
+ MPI_Datatype type; /* MPI Datatype */
+ struct H5S_mpio_mpitype_node_t *next; /* Pointer to next node in list */
+} H5S_mpio_mpitype_node_t;
+
+/* List to track MPI data types generated during traversal of irregular hyperslab selection */
+typedef struct H5S_mpio_mpitype_list_t {
+ H5S_mpio_mpitype_node_t *head; /* Pointer to head of list */
+ H5S_mpio_mpitype_node_t *tail; /* Pointer to tail of list */
+} H5S_mpio_mpitype_list_t;
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+static herr_t H5S__mpio_all_type(const H5S_t *space, size_t elmt_size,
MPI_Datatype *new_type, int *count, hbool_t *is_derived_type);
-static herr_t H5S_mpio_none_type(MPI_Datatype *new_type, int *count,
+static herr_t H5S__mpio_none_type(MPI_Datatype *new_type, int *count,
hbool_t *is_derived_type);
-static herr_t H5S_mpio_create_point_datatype(size_t elmt_size, hsize_t num_points,
+static herr_t H5S__mpio_create_point_datatype(size_t elmt_size, hsize_t num_points,
MPI_Aint *disp, MPI_Datatype *new_type);
-static herr_t H5S_mpio_point_type(const H5S_t *space, size_t elmt_size,
+static herr_t H5S__mpio_point_type(const H5S_t *space, size_t elmt_size,
MPI_Datatype *new_type, int *count, hbool_t *is_derived_type,
hbool_t do_permute, hsize_t **permute_map, hbool_t *is_permuted);
-static herr_t H5S_mpio_permute_type(const H5S_t *space, size_t elmt_size,
+static herr_t H5S__mpio_permute_type(const H5S_t *space, size_t elmt_size,
hsize_t **permute_map, MPI_Datatype *new_type, int *count,
hbool_t *is_derived_type);
-static herr_t H5S_mpio_hyper_type(const H5S_t *space, size_t elmt_size,
+static herr_t H5S__mpio_reg_hyper_type(const H5S_t *space, size_t elmt_size,
MPI_Datatype *new_type, int *count, hbool_t *is_derived_type);
-static herr_t H5S_mpio_span_hyper_type(const H5S_t *space, size_t elmt_size,
+static herr_t H5S__mpio_span_hyper_type(const H5S_t *space, size_t elmt_size,
MPI_Datatype *new_type, int *count, hbool_t *is_derived_type);
-static herr_t H5S_obtain_datatype(const hsize_t down[], H5S_hyper_span_t* span,
- const MPI_Datatype *elmt_type, MPI_Datatype *span_type, size_t elmt_size);
-static herr_t H5S_mpio_create_large_type (hsize_t, MPI_Aint, MPI_Datatype , MPI_Datatype *);
+static herr_t H5S__release_datatype(H5S_mpio_mpitype_list_t *type_list);
+static herr_t H5S__obtain_datatype(H5S_hyper_span_info_t *spans, const hsize_t *down,
+ size_t elmt_size, const MPI_Datatype *elmt_type, MPI_Datatype *span_type,
+ H5S_mpio_mpitype_list_t *type_list, uint64_t op_gen);
-#define H5S_MPIO_INITIAL_ALLOC_COUNT 256
+/*****************************/
+/* Library Private Variables */
+/*****************************/
-#define TWO_GIG_LIMIT 2147483648
-#ifndef H5S_MAX_MPI_COUNT
-#define H5S_MAX_MPI_COUNT 536870911 /* (2^29)-1 */
-#endif
+/*********************/
+/* Package Variables */
+/*********************/
-static hsize_t bigio_count = H5S_MAX_MPI_COUNT;
-/*-------------------------------------------------------------------------
- * Function: H5S_mpio_set_bigio_count
- *
- * Purpose: Allow us to programatically change the switch point
- * when we utilize derived datatypes. This is of
- * particular interest for allowing nightly testing
- *
- * Return: the current/previous value of bigio_count.
- *
- * Programmer: Richard Warren, March 10, 2017
- *
- *-------------------------------------------------------------------------
- */
-hsize_t
-H5S_mpio_set_bigio_count(hsize_t new_count)
-{
- hsize_t orig_count = bigio_count;
- if ((new_count > 0) && (new_count < TWO_GIG_LIMIT)) {
- bigio_count = new_count;
- }
- return orig_count;
-}
+/* Declare a free list to manage the H5S_mpio_mpitype_node_t struct */
+H5FL_DEFINE_STATIC(H5S_mpio_mpitype_node_t);
/*-------------------------------------------------------------------------
- * Function: H5S_mpio_all_type
+ * Function: H5S__mpio_all_type
*
* Purpose: Translate an HDF5 "all" selection into an MPI type.
*
- * Return: non-negative on success, negative on failure.
+ * Return: Non-negative on success, negative on failure.
*
* Outputs: *new_type the MPI type corresponding to the selection
* *count how many objects of the new_type in selection
@@ -105,24 +116,20 @@ H5S_mpio_set_bigio_count(hsize_t new_count)
* *is_derived_type 0 if MPI primitive type, 1 if derived
*
* Programmer: rky 980813
- * Modifications:
- * Mohamad Chaarawi
- * Adding support for large datatypes (beyond the limit of a
- * 32 bit integer.
- *
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5S_mpio_all_type(const H5S_t *space, size_t elmt_size,
+H5S__mpio_all_type(const H5S_t *space, size_t elmt_size,
MPI_Datatype *new_type, int *count, hbool_t *is_derived_type)
{
hsize_t total_bytes;
hssize_t snelmts; /* Total number of elmts (signed) */
hsize_t nelmts; /* Total number of elmts */
+ hsize_t bigio_count; /* Transition point to create derived type */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
/* Check args */
HDassert(space);
@@ -133,34 +140,34 @@ H5S_mpio_all_type(const H5S_t *space, size_t elmt_size,
H5_CHECKED_ASSIGN(nelmts, hsize_t, snelmts, hssize_t);
total_bytes = (hsize_t)elmt_size * nelmts;
+ bigio_count = H5_mpi_get_bigio_count();
+
/* Verify that the size can be expressed as a 32 bit integer */
if(bigio_count >= total_bytes) {
- /* fill in the return values */
- *new_type = MPI_BYTE;
- H5_CHECKED_ASSIGN(*count, int, total_bytes, hsize_t);
- *is_derived_type = FALSE;
- }
+ /* fill in the return values */
+ *new_type = MPI_BYTE;
+ H5_CHECKED_ASSIGN(*count, int, total_bytes, hsize_t);
+ *is_derived_type = FALSE;
+ } /* end if */
else {
- /* Create a LARGE derived datatype for this transfer */
- if (H5S_mpio_create_large_type (total_bytes, 0, MPI_BYTE, new_type) < 0) {
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,
- "couldn't create a large datatype from the all selection")
- }
- *count = 1;
- *is_derived_type = TRUE;
- }
+ /* Create a LARGE derived datatype for this transfer */
+ if(H5_mpio_create_large_type(total_bytes, 0, MPI_BYTE, new_type) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "couldn't create a large datatype from the all selection")
+ *count = 1;
+ *is_derived_type = TRUE;
+ } /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_mpio_all_type() */
+} /* H5S__mpio_all_type() */
/*-------------------------------------------------------------------------
- * Function: H5S_mpio_none_type
+ * Function: H5S__mpio_none_type
*
* Purpose: Translate an HDF5 "none" selection into an MPI type.
*
- * Return: non-negative on success, negative on failure.
+ * Return: Non-negative on success, negative on failure.
*
* Outputs: *new_type the MPI type corresponding to the selection
* *count how many objects of the new_type in selection
@@ -172,9 +179,9 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5S_mpio_none_type(MPI_Datatype *new_type, int *count, hbool_t *is_derived_type)
+H5S__mpio_none_type(MPI_Datatype *new_type, int *count, hbool_t *is_derived_type)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
/* fill in the return values */
*new_type = MPI_BYTE;
@@ -182,15 +189,15 @@ H5S_mpio_none_type(MPI_Datatype *new_type, int *count, hbool_t *is_derived_type)
*is_derived_type = FALSE;
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5S_mpio_none_type() */
+} /* H5S__mpio_none_type() */
/*-------------------------------------------------------------------------
- * Function: H5S_mpio_create_point_datatype
+ * Function: H5S__mpio_create_point_datatype
*
* Purpose: Create a derived datatype for point selections.
*
- * Return: non-negative on success, negative on failure.
+ * Return: Non-negative on success, negative on failure.
*
* Outputs: *new_type the MPI type corresponding to the selection
*
@@ -198,167 +205,156 @@ H5S_mpio_none_type(MPI_Datatype *new_type, int *count, hbool_t *is_derived_type)
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5S_mpio_create_point_datatype (size_t elmt_size, hsize_t num_points,
- MPI_Aint *disp, MPI_Datatype *new_type)
+static herr_t
+H5S__mpio_create_point_datatype(size_t elmt_size, hsize_t num_points,
+ MPI_Aint *disp, MPI_Datatype *new_type)
{
MPI_Datatype elmt_type; /* MPI datatype for individual element */
hbool_t elmt_type_created = FALSE; /* Whether the element MPI datatype was created */
- int mpi_code; /* MPI error code */
+ int *inner_blocks = NULL; /* Arrays for MPI datatypes when "large" datatype needed */
+ MPI_Aint *inner_disps = NULL;
+ MPI_Datatype *inner_types = NULL;
+#if MPI_VERSION < 3
int *blocks = NULL; /* Array of block sizes for MPI hindexed create call */
hsize_t u; /* Local index variable */
+#endif
+ hsize_t bigio_count; /* Transition point to create derived type */
+ int mpi_code; /* MPI error code */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
/* Create an MPI datatype for an element */
if(MPI_SUCCESS != (mpi_code = MPI_Type_contiguous((int)elmt_size, MPI_BYTE, &elmt_type)))
HMPI_GOTO_ERROR(FAIL, "MPI_Type_contiguous failed", mpi_code)
elmt_type_created = TRUE;
+ bigio_count = H5_mpi_get_bigio_count();
+
/* Check whether standard or BIGIO processing will be employeed */
if(bigio_count >= num_points) {
#if MPI_VERSION >= 3
- /* Create an MPI datatype for the whole point selection */
- if(MPI_SUCCESS != (mpi_code = MPI_Type_create_hindexed_block((int)num_points, 1, disp, elmt_type, new_type)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_indexed_block failed", mpi_code)
+ /* Create an MPI datatype for the whole point selection */
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_create_hindexed_block((int)num_points, 1, disp, elmt_type, new_type)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_indexed_block failed", mpi_code)
#else
- /* Allocate block sizes for MPI datatype call */
- if(NULL == (blocks = (int *)H5MM_malloc(sizeof(int) * num_points)))
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of blocks")
+ /* Allocate block sizes for MPI datatype call */
+ if(NULL == (blocks = (int *)H5MM_malloc(sizeof(int) * num_points)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of blocks")
- for(u = 0; u < num_points; u++)
- blocks[u] = 1;
+ for(u = 0; u < num_points; u++)
+ blocks[u] = 1;
- /* Create an MPI datatype for the whole point selection */
- if(MPI_SUCCESS != (mpi_code = MPI_Type_create_hindexed((int)num_points, blocks, disp, elmt_type, new_type)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hindexed failed", mpi_code)
+ /* Create an MPI datatype for the whole point selection */
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_create_hindexed((int)num_points, blocks, disp, elmt_type, new_type)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hindexed failed", mpi_code)
#endif
- /* Commit MPI datatype for later use */
- if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(new_type)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code)
- }
- else {
- /* use LARGE_DATATYPE::
- * We'll create an hindexed_block type for every 2G point count and then combine
- * those and any remaining points into a single large datatype.
- */
- int total_types, i;
- int remaining_points;
- int num_big_types;
- hsize_t leftover;
-
- int *inner_blocks;
- MPI_Aint *inner_disps;
- MPI_Datatype *inner_types = NULL;
+ /* Commit MPI datatype for later use */
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(new_type)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code)
+ } /* end if */
+ else {
+ /* use LARGE_DATATYPE::
+ * We'll create an hindexed_block type for every 2G point count and then combine
+ * those and any remaining points into a single large datatype.
+ */
+ int total_types, i;
+ int remaining_points;
+ int num_big_types;
+ hsize_t leftover;
- /* Calculate how many Big MPI datatypes are needed to represent the buffer */
- num_big_types = (int)(num_points/bigio_count);
+ /* Calculate how many Big MPI datatypes are needed to represent the buffer */
+ num_big_types = (int)(num_points / bigio_count);
- leftover = (hsize_t)num_points - (hsize_t)num_big_types * (hsize_t)bigio_count;
- H5_CHECKED_ASSIGN(remaining_points, int, leftover, hsize_t);
+ leftover = (hsize_t)num_points - (hsize_t)num_big_types * (hsize_t)bigio_count;
+ H5_CHECKED_ASSIGN(remaining_points, int, leftover, hsize_t);
- total_types = (int)(remaining_points) ? (num_big_types + 1) : num_big_types;
+ total_types = (int)(remaining_points) ? (num_big_types + 1) : num_big_types;
- /* Allocate array if MPI derived types needed */
- if(NULL == (inner_types = (MPI_Datatype *)H5MM_malloc((sizeof(MPI_Datatype) * (size_t)total_types))))
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of blocks")
+ /* Allocate array if MPI derived types needed */
+ if(NULL == (inner_types = (MPI_Datatype *)H5MM_malloc((sizeof(MPI_Datatype) * (size_t)total_types))))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of blocks")
- if(NULL == (inner_blocks = (int *)H5MM_malloc(sizeof(int) * (size_t)total_types)))
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of blocks")
+ if(NULL == (inner_blocks = (int *)H5MM_malloc(sizeof(int) * (size_t)total_types)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of blocks")
- if(NULL == (inner_disps = (MPI_Aint *)H5MM_malloc(sizeof(MPI_Aint) * (size_t)total_types)))
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of blocks")
+ if(NULL == (inner_disps = (MPI_Aint *)H5MM_malloc(sizeof(MPI_Aint) * (size_t)total_types)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of blocks")
#if MPI_VERSION < 3
- /* Allocate block sizes for MPI datatype call */
- if(NULL == (blocks = (int *)H5MM_malloc(sizeof(int) * bigio_count)))
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of blocks")
+ /* Allocate block sizes for MPI datatype call */
+ if(NULL == (blocks = (int *)H5MM_malloc(sizeof(int) * bigio_count)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of blocks")
- for(u = 0; u < bigio_count; u++)
- blocks[u] = 1;
+ for(u = 0; u < bigio_count; u++)
+ blocks[u] = 1;
#endif
- for(i=0 ; i<num_big_types ; i++) {
+ for(i = 0; i < num_big_types; i++) {
#if MPI_VERSION >= 3
- if(MPI_SUCCESS != (mpi_code = MPI_Type_create_hindexed_block(bigio_count,
- 1,
- &disp[i*bigio_count],
- elmt_type,
- &inner_types[i]))) {
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hindexed_block failed", mpi_code);
- }
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_create_hindexed_block(bigio_count,
+ 1, &disp[i*bigio_count], elmt_type, &inner_types[i])))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hindexed_block failed", mpi_code)
#else
- if(MPI_SUCCESS != (mpi_code = MPI_Type_create_hindexed((int)bigio_count,
- blocks,
- &disp[i*bigio_count],
- elmt_type,
- &inner_types[i]))) {
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hindexed failed", mpi_code)
- }
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_create_hindexed((int)bigio_count,
+ blocks, &disp[i*bigio_count], elmt_type, &inner_types[i])))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hindexed failed", mpi_code)
#endif
- inner_blocks[i] = 1;
- inner_disps[i] = 0;
- }
+ inner_blocks[i] = 1;
+ inner_disps[i] = 0;
+ } /* end for*/
- if(remaining_points) {
+ if(remaining_points) {
#if MPI_VERSION >= 3
- if(MPI_SUCCESS != (mpi_code = MPI_Type_create_hindexed_block(remaining_points,
- 1,
- &disp[num_big_types*bigio_count],
- elmt_type,
- &inner_types[num_big_types]))) {
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hindexed_block failed", mpi_code);
- }
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_create_hindexed_block(remaining_points,
+ 1, &disp[num_big_types*bigio_count], elmt_type, &inner_types[num_big_types])))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hindexed_block failed", mpi_code)
#else
- if(MPI_SUCCESS != (mpi_code = MPI_Type_create_hindexed((int)remaining_points,
- blocks,
- &disp[num_big_types*bigio_count],
- elmt_type,
- &inner_types[num_big_types]))) {
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hindexed failed", mpi_code)
- }
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_create_hindexed((int)remaining_points,
+ blocks, &disp[num_big_types*bigio_count], elmt_type, &inner_types[num_big_types])))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hindexed failed", mpi_code)
#endif
- inner_blocks[num_big_types] = 1;
- inner_disps[num_big_types] = 0;
- }
-
- if(MPI_SUCCESS != (mpi_code = MPI_Type_create_struct(total_types,
- inner_blocks,
- inner_disps,
- inner_types,
- new_type))) {
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_struct", mpi_code);
- }
- for(i=0 ; i<total_types ; i++)
- MPI_Type_free(&inner_types[i]);
-
- H5MM_free(inner_types);
- H5MM_free(inner_blocks);
- H5MM_free(inner_disps);
-
- /* Commit MPI datatype for later use */
- if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(new_type)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code)
- }
+ inner_blocks[num_big_types] = 1;
+ inner_disps[num_big_types] = 0;
+ } /* end if */
+
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_create_struct(total_types,
+ inner_blocks, inner_disps, inner_types, new_type)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_struct", mpi_code)
+ for(i = 0; i < total_types; i++)
+ MPI_Type_free(&inner_types[i]);
+
+ /* Commit MPI datatype for later use */
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(new_type)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code)
+ } /* end else */
+
done:
if(elmt_type_created)
MPI_Type_free(&elmt_type);
+#if MPI_VERSION < 3
if(blocks)
H5MM_free(blocks);
+#endif
+ if(inner_types)
+ H5MM_free(inner_types);
+ if(inner_blocks)
+ H5MM_free(inner_blocks);
+ if(inner_disps)
+ H5MM_free(inner_disps);
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_mpio_create_point_datatype() */
+} /* H5S__mpio_create_point_datatype() */
/*-------------------------------------------------------------------------
- * Function: H5S_mpio_point_type
+ * Function: H5S__mpio_point_type
*
* Purpose: Translate an HDF5 "point" selection into an MPI type.
* Create a permutation array to handle out-of-order point selections.
*
- * Return: non-negative on success, negative on failure.
+ * Return: Non-negative on success, negative on failure.
*
* Outputs: *new_type the MPI type corresponding to the selection
* *count how many objects of the new_type in selection
@@ -373,7 +369,7 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5S_mpio_point_type(const H5S_t *space, size_t elmt_size, MPI_Datatype *new_type,
+H5S__mpio_point_type(const H5S_t *space, size_t elmt_size, MPI_Datatype *new_type,
int *count, hbool_t *is_derived_type, hbool_t do_permute, hsize_t **permute,
hbool_t *is_permuted)
{
@@ -384,7 +380,7 @@ H5S_mpio_point_type(const H5S_t *space, size_t elmt_size, MPI_Datatype *new_type
hsize_t u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
/* Check args */
HDassert(space);
@@ -406,23 +402,23 @@ H5S_mpio_point_type(const H5S_t *space, size_t elmt_size, MPI_Datatype *new_type
/* Iterate through list of elements */
curr = space->select.sel_info.pnt_lst->head;
for(u = 0 ; u < num_points ; u++) {
- /* calculate the displacement of the current point */
+ /* Calculate the displacement of the current point */
disp[u] = H5VM_array_offset(space->extent.rank, space->extent.size, curr->pnt);
disp[u] *= elmt_size;
- /* This is a File Space used to set the file view, so adjust the displacements
+ /* This is a File Space used to set the file view, so adjust the displacements
* to have them monotonically non-decreasing.
- * Generate the permutation array by indicating at each point being selected,
- * the position it will shifted in the new displacement. Example:
- * Suppose 4 points with corresponding are selected
- * Pt 1: disp=6 ; Pt 2: disp=3 ; Pt 3: disp=0 ; Pt 4: disp=4
+ * Generate the permutation array by indicating at each point being selected,
+ * the position it will shifted in the new displacement. Example:
+ * Suppose 4 points with corresponding are selected
+ * Pt 1: disp=6 ; Pt 2: disp=3 ; Pt 3: disp=0 ; Pt 4: disp=4
* The permute map to sort the displacements in order will be:
* point 1: map[0] = L, indicating that this point is not moved (1st point selected)
- * point 2: map[1] = 0, indicating that this point is moved to the first position,
+ * point 2: map[1] = 0, indicating that this point is moved to the first position,
* since disp_pt1(6) > disp_pt2(3)
- * point 3: map[2] = 0, move to position 0, bec it has the lowest disp between
+ * point 3: map[2] = 0, move to position 0, bec it has the lowest disp between
* the points selected so far.
- * point 4: map[3] = 2, move the 2nd position since point 1 has a higher disp,
+ * point 4: map[3] = 2, move the 2nd position since point 1 has a higher disp,
* but points 2 and 3 have lower displacements.
*/
if(do_permute) {
@@ -447,7 +443,7 @@ H5S_mpio_point_type(const H5S_t *space, size_t elmt_size, MPI_Datatype *new_type
HDmemmove(disp + m + 1, disp + m, (u - m) * sizeof(MPI_Aint));
disp[m] = temp;
} /* end if */
- (*permute)[u] = m;
+ (*permute)[u] = m;
} /* end if */
else
(*permute)[u] = num_points;
@@ -455,7 +451,7 @@ H5S_mpio_point_type(const H5S_t *space, size_t elmt_size, MPI_Datatype *new_type
/* this is a memory space, and no permutation is necessary to create
the derived datatype */
else {
- ;/* do nothing */
+ ; /* do nothing */
} /* end else */
/* get the next point */
@@ -463,7 +459,7 @@ H5S_mpio_point_type(const H5S_t *space, size_t elmt_size, MPI_Datatype *new_type
} /* end for */
/* Create the MPI datatype for the set of element displacements */
- if(H5S_mpio_create_point_datatype(elmt_size, num_points, disp, new_type) < 0)
+ if(H5S__mpio_create_point_datatype(elmt_size, num_points, disp, new_type) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "couldn't create an MPI Datatype from point selection")
/* Set values about MPI datatype created */
@@ -481,11 +477,11 @@ done:
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_mpio_point_type() */
+} /* H5S__mpio_point_type() */
/*-------------------------------------------------------------------------
- * Function: H5S_mpio_permute_type
+ * Function: H5S__mpio_permute_type
*
* Purpose: Translate an HDF5 "all/hyper/point" selection into an MPI type,
* while applying the permutation map. This function is called if
@@ -493,10 +489,10 @@ done:
* selection and so the memory datatype has to be permuted using the
* permutation map created by the file selection.
*
- * Note: This routine is called from H5S_mpio_space_type(), which is
+ * Note: This routine is called from H5_mpio_space_type(), which is
* called first for the file dataspace and creates
*
- * Return: non-negative on success, negative on failure.
+ * Return: Non-negative on success, negative on failure.
*
* Outputs: *new_type the MPI type corresponding to the selection
* *count how many objects of the new_type in selection
@@ -508,7 +504,7 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5S_mpio_permute_type(const H5S_t *space, size_t elmt_size, hsize_t **permute,
+H5S__mpio_permute_type(const H5S_t *space, size_t elmt_size, hsize_t **permute,
MPI_Datatype *new_type, int *count, hbool_t *is_derived_type)
{
MPI_Aint *disp = NULL; /* Datatype displacement for each point*/
@@ -520,7 +516,7 @@ H5S_mpio_permute_type(const H5S_t *space, size_t elmt_size, hsize_t **permute,
hsize_t u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
/* Check args */
HDassert(space);
@@ -535,7 +531,7 @@ H5S_mpio_permute_type(const H5S_t *space, size_t elmt_size, hsize_t **permute,
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of displacements")
/* Initialize selection iterator */
- if(H5S_select_iter_init(&sel_iter, space, elmt_size) < 0)
+ if(H5S_select_iter_init(&sel_iter, space, elmt_size, 0) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator")
sel_iter_init = TRUE; /* Selection iteration info has been initialized */
@@ -552,7 +548,7 @@ H5S_mpio_permute_type(const H5S_t *space, size_t elmt_size, hsize_t **permute,
size_t curr_seq; /* Current sequence being worked on */
/* Get the sequences of bytes */
- if(H5S_SELECT_GET_SEQ_LIST(space, 0, &sel_iter, (size_t)H5D_IO_VECTOR_SIZE, max_elem, &nseq, &nelem, off, len) < 0)
+ if(H5S_SELECT_ITER_GET_SEQ_LIST(&sel_iter, (size_t)H5D_IO_VECTOR_SIZE, max_elem, &nseq, &nelem, off, len) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "sequence length generation failed")
/* Loop, while sequences left to process */
@@ -571,12 +567,12 @@ H5S_mpio_permute_type(const H5S_t *space, size_t elmt_size, hsize_t **permute,
/* Set the displacement of the current point */
disp[u] = curr_off;
- /* This is a memory displacement, so for each point selected,
+ /* This is a memory displacement, so for each point selected,
* apply the map that was generated by the file selection */
if((*permute)[u] != num_points) {
MPI_Aint temp = disp[u];
- HDmemmove(disp + (*permute)[u] + 1, disp + (*permute)[u],
+ HDmemmove(disp + (*permute)[u] + 1, disp + (*permute)[u],
(u - (*permute)[u]) * sizeof(MPI_Aint));
disp[(*permute)[u]] = temp;
} /* end if */
@@ -597,7 +593,7 @@ H5S_mpio_permute_type(const H5S_t *space, size_t elmt_size, hsize_t **permute,
} /* end while */
/* Create the MPI datatype for the set of element displacements */
- if(H5S_mpio_create_point_datatype(elmt_size, num_points, disp, new_type) < 0)
+ if(H5S__mpio_create_point_datatype(elmt_size, num_points, disp, new_type) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "couldn't create an MPI Datatype from point selection")
/* Set values about MPI datatype created */
@@ -619,15 +615,15 @@ done:
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_mpio_permute_type() */
+} /* H5S__mpio_permute_type() */
/*-------------------------------------------------------------------------
- * Function: H5S_mpio_hyper_type
+ * Function: H5S__mpio_reg_hyper_type
*
- * Purpose: Translate an HDF5 hyperslab selection into an MPI type.
+ * Purpose: Translate a regular HDF5 hyperslab selection into an MPI type.
*
- * Return: non-negative on success, negative on failure.
+ * Return: Non-negative on success, negative on failure.
*
* Outputs: *new_type the MPI type corresponding to the selection
* *count how many objects of the new_type in selection
@@ -635,14 +631,11 @@ done:
* *is_derived_type 0 if MPI primitive type, 1 if derived
*
* Programmer: rky 980813
- * Modifications:
- * Mohamad Chaarawi
- * Adding support for large datatypes (beyond the limit of a
- * 32 bit integer.
+ *
*-------------------------------------------------------------------------
*/
static herr_t
-H5S_mpio_hyper_type(const H5S_t *space, size_t elmt_size,
+H5S__mpio_reg_hyper_type(const H5S_t *space, size_t elmt_size,
MPI_Datatype *new_type, int *count, hbool_t *is_derived_type)
{
H5S_sel_iter_t sel_iter; /* Selection iteration info */
@@ -656,6 +649,7 @@ H5S_mpio_hyper_type(const H5S_t *space, size_t elmt_size,
hsize_t count;
} d[H5S_MAX_RANK];
+ hsize_t bigio_count; /* Transition point to create derived type */
hsize_t offset[H5S_MAX_RANK];
hsize_t max_xtent[H5S_MAX_RANK];
H5S_hyper_dim_t *diminfo; /* [rank] */
@@ -668,14 +662,15 @@ H5S_mpio_hyper_type(const H5S_t *space, size_t elmt_size,
int mpi_code; /* MPI return code */
herr_t ret_value = SUCCEED;
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
/* Check args */
HDassert(space);
HDassert(sizeof(MPI_Aint) >= sizeof(elmt_size));
+ bigio_count = H5_mpi_get_bigio_count();
/* Initialize selection iterator */
- if(H5S_select_iter_init(&sel_iter, space, elmt_size) < 0)
+ if(H5S_select_iter_init(&sel_iter, space, elmt_size, 0) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator")
sel_iter_init = TRUE; /* Selection iteration info has been initialized */
@@ -683,16 +678,15 @@ H5S_mpio_hyper_type(const H5S_t *space, size_t elmt_size,
diminfo = sel_iter.u.hyp.diminfo;
HDassert(diminfo);
- /* make a local copy of the dimension info so we can operate with them */
+ /* Make a local copy of the dimension info so we can operate with them */
/* Check if this is a "flattened" regular hyperslab selection */
if(sel_iter.u.hyp.iter_rank != 0 && sel_iter.u.hyp.iter_rank < space->extent.rank) {
/* Flattened selection */
rank = sel_iter.u.hyp.iter_rank;
- HDassert(rank <= H5S_MAX_RANK); /* within array bounds */
#ifdef H5S_DEBUG
- if(H5DEBUG(S))
- HDfprintf(H5DEBUG(S), "%s: Flattened selection\n",FUNC);
+if(H5DEBUG(S))
+ HDfprintf(H5DEBUG(S), "%s: Flattened selection\n",FUNC);
#endif
for(u = 0; u < rank; ++u) {
H5_CHECK_OVERFLOW(diminfo[u].start, hsize_t, hssize_t)
@@ -701,33 +695,30 @@ H5S_mpio_hyper_type(const H5S_t *space, size_t elmt_size,
d[u].block = diminfo[u].block;
d[u].count = diminfo[u].count;
d[u].xtent = sel_iter.u.hyp.size[u];
+
#ifdef H5S_DEBUG
- if(H5DEBUG(S)){
- HDfprintf(H5DEBUG(S), "%s: start=%Hd stride=%Hu count=%Hu block=%Hu xtent=%Hu",
- FUNC, d[u].start, d[u].strid, d[u].count, d[u].block, d[u].xtent );
- if (u==0)
- HDfprintf(H5DEBUG(S), " rank=%u\n", rank );
- else
- HDfprintf(H5DEBUG(S), "\n" );
- }
+if(H5DEBUG(S)) {
+ HDfprintf(H5DEBUG(S), "%s: start=%Hd stride=%Hu count=%Hu block=%Hu xtent=%Hu",
+ FUNC, d[u].start, d[u].strid, d[u].count, d[u].block, d[u].xtent);
+ if(u == 0)
+ HDfprintf(H5DEBUG(S), " rank=%u\n", rank);
+ else
+ HDfprintf(H5DEBUG(S), "\n");
+}
#endif
- if(0 == d[u].block)
- goto empty;
- if(0 == d[u].count)
- goto empty;
- if(0 == d[u].xtent)
- goto empty;
+
+ /* Sanity check */
+ HDassert(d[u].block > 0);
+ HDassert(d[u].count > 0);
+ HDassert(d[u].xtent > 0);
} /* end for */
} /* end if */
else {
/* Non-flattened selection */
rank = space->extent.rank;
- HDassert(rank <= H5S_MAX_RANK); /* within array bounds */
- if(0 == rank)
- goto empty;
#ifdef H5S_DEBUG
- if(H5DEBUG(S))
- HDfprintf(H5DEBUG(S),"%s: Non-flattened selection\n",FUNC);
+if(H5DEBUG(S))
+ HDfprintf(H5DEBUG(S),"%s: Non-flattened selection\n",FUNC);
#endif
for(u = 0; u < rank; ++u) {
H5_CHECK_OVERFLOW(diminfo[u].start, hsize_t, hssize_t)
@@ -736,22 +727,22 @@ H5S_mpio_hyper_type(const H5S_t *space, size_t elmt_size,
d[u].block = diminfo[u].block;
d[u].count = diminfo[u].count;
d[u].xtent = space->extent.size[u];
+
#ifdef H5S_DEBUG
- if(H5DEBUG(S)){
+if(H5DEBUG(S)) {
HDfprintf(H5DEBUG(S), "%s: start=%Hd stride=%Hu count=%Hu block=%Hu xtent=%Hu",
- FUNC, d[u].start, d[u].strid, d[u].count, d[u].block, d[u].xtent );
- if (u==0)
- HDfprintf(H5DEBUG(S), " rank=%u\n", rank );
+ FUNC, d[u].start, d[u].strid, d[u].count, d[u].block, d[u].xtent);
+ if(u == 0)
+ HDfprintf(H5DEBUG(S), " rank=%u\n", rank);
else
- HDfprintf(H5DEBUG(S), "\n" );
- }
+ HDfprintf(H5DEBUG(S), "\n");
+}
#endif
- if(0 == d[u].block)
- goto empty;
- if(0 == d[u].count)
- goto empty;
- if(0 == d[u].xtent)
- goto empty;
+
+ /* Sanity check */
+ HDassert(d[u].block > 0);
+ HDassert(d[u].count > 0);
+ HDassert(d[u].xtent > 0);
} /* end for */
} /* end else */
@@ -762,56 +753,52 @@ H5S_mpio_hyper_type(const H5S_t *space, size_t elmt_size,
offset[rank - 1] = 1;
max_xtent[rank - 1] = d[rank - 1].xtent;
#ifdef H5S_DEBUG
- if(H5DEBUG(S)) {
- i = ((int)rank) - 1;
- HDfprintf(H5DEBUG(S), " offset[%2d]=%Hu; max_xtent[%2d]=%Hu\n",
- i, offset[i], i, max_xtent[i]);
- }
+if(H5DEBUG(S)) {
+ i = ((int)rank) - 1;
+ HDfprintf(H5DEBUG(S), " offset[%2d]=%Hu; max_xtent[%2d]=%Hu\n", i, offset[i], i, max_xtent[i]);
+}
#endif
for(i = ((int)rank) - 2; i >= 0; --i) {
offset[i] = offset[i + 1] * d[i + 1].xtent;
max_xtent[i] = max_xtent[i + 1] * d[i].xtent;
#ifdef H5S_DEBUG
- if(H5DEBUG(S))
- HDfprintf(H5DEBUG(S), " offset[%2d]=%Hu; max_xtent[%2d]=%Hu\n",
- i, offset[i], i, max_xtent[i]);
+if(H5DEBUG(S))
+ HDfprintf(H5DEBUG(S), " offset[%2d]=%Hu; max_xtent[%2d]=%Hu\n", i, offset[i], i, max_xtent[i]);
#endif
} /* end for */
/* Create a type covering the selected hyperslab.
* Multidimensional dataspaces are stored in row-major order.
* The type is built from the inside out, going from the
- * fastest-changing (i.e., inner) dimension * to the slowest (outer). */
+ * fastest-changing (i.e., inner) dimension * to the slowest (outer).
+ */
/*******************************************************
* Construct contig type for inner contig dims:
*******************************************************/
#ifdef H5S_DEBUG
- if(H5DEBUG(S)) {
+if(H5DEBUG(S)) {
HDfprintf(H5DEBUG(S), "%s: Making contig type %Zu MPI_BYTEs\n", FUNC, elmt_size);
for(i = ((int)rank) - 1; i >= 0; --i)
HDfprintf(H5DEBUG(S), "d[%d].xtent=%Hu \n", i, d[i].xtent);
- }
+}
#endif
/* LARGE_DATATYPE::
- * Check if the number of elements to form the inner type fits into a 32 bit integer.
+ * Check if the number of elements to form the inner type fits into a 32 bit integer.
* If yes then just create the innertype with MPI_Type_contiguous.
* Otherwise create a compound datatype by iterating as many times as needed
* for the innertype to be created.
*/
if(bigio_count >= elmt_size) {
- /* Use a single MPI datatype that has a 32 bit size */
- if(MPI_SUCCESS != (mpi_code = MPI_Type_contiguous((int)elmt_size, MPI_BYTE, &inner_type)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_contiguous failed", mpi_code)
- }
- else {
- /* Create the compound datatype for this operation (> 2GB) */
- if (H5S_mpio_create_large_type (elmt_size, 0, MPI_BYTE, &inner_type) < 0) {
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,
- "couldn't ccreate a large inner datatype in hyper selection")
- }
- }
+ /* Use a single MPI datatype that has a 32 bit size */
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_contiguous((int)elmt_size, MPI_BYTE, &inner_type)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Type_contiguous failed", mpi_code)
+ } /* end if */
+ else
+ /* Create the compound datatype for this operation (> 2GB) */
+ if(H5_mpio_create_large_type(elmt_size, 0, MPI_BYTE, &inner_type) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "couldn't create a large inner datatype in hyper selection")
/*******************************************************
* Construct the type by walking the hyperslab dims
@@ -819,106 +806,103 @@ H5S_mpio_hyper_type(const H5S_t *space, size_t elmt_size,
*******************************************************/
for(i = ((int)rank) - 1; i >= 0; --i) {
#ifdef H5S_DEBUG
- if(H5DEBUG(S))
- HDfprintf(H5DEBUG(S), "%s: Dimension i=%d \n"
- "start=%Hd count=%Hu block=%Hu stride=%Hu, xtent=%Hu max_xtent=%d\n",
- FUNC, i, d[i].start, d[i].count, d[i].block, d[i].strid, d[i].xtent, max_xtent[i]);
+if(H5DEBUG(S))
+ HDfprintf(H5DEBUG(S), "%s: Dimension i=%d \n"
+ "start=%Hd count=%Hu block=%Hu stride=%Hu, xtent=%Hu max_xtent=%d\n",
+ FUNC, i, d[i].start, d[i].count, d[i].block, d[i].strid, d[i].xtent, max_xtent[i]);
#endif
#ifdef H5S_DEBUG
- if(H5DEBUG(S))
- HDfprintf(H5DEBUG(S), "%s: i=%d Making vector-type \n", FUNC,i);
+if(H5DEBUG(S))
+ HDfprintf(H5DEBUG(S), "%s: i=%d Making vector-type \n", FUNC,i);
#endif
/****************************************
- * Build vector type of the selection.
- ****************************************/
- if (bigio_count >= d[i].count &&
- bigio_count >= d[i].block &&
- bigio_count >= d[i].strid) {
-
- /* All the parameters fit into 32 bit integers so create the vector type normally */
- mpi_code = MPI_Type_vector((int)(d[i].count), /* count */
- (int)(d[i].block), /* blocklength */
- (int)(d[i].strid), /* stride */
- inner_type, /* old type */
- &outer_type); /* new type */
-
- MPI_Type_free(&inner_type);
- if(mpi_code != MPI_SUCCESS)
- HMPI_GOTO_ERROR(FAIL, "couldn't create MPI vector type", mpi_code)
- }
+ * Build vector type of the selection.
+ ****************************************/
+ if(bigio_count >= d[i].count &&
+ bigio_count >= d[i].block && bigio_count >= d[i].strid) {
+ /* All the parameters fit into 32 bit integers so create the vector type normally */
+ mpi_code = MPI_Type_vector((int)(d[i].count), /* count */
+ (int)(d[i].block), /* blocklength */
+ (int)(d[i].strid), /* stride */
+ inner_type, /* old type */
+ &outer_type); /* new type */
+
+ MPI_Type_free(&inner_type);
+ if(mpi_code != MPI_SUCCESS)
+ HMPI_GOTO_ERROR(FAIL, "couldn't create MPI vector type", mpi_code)
+ } /* end if */
else {
- /* Things get a bit more complicated and require LARGE_DATATYPE processing
- * There are two MPI datatypes that need to be created:
- * 1) an internal contiguous block; and
- * 2) a collection of elements where an element is a contiguous block(1).
- * Remember that the input arguments to the MPI-IO functions use integer
- * values to represent element counts. We ARE allowed however, in the
- * more recent MPI implementations to use constructed datatypes whereby
- * the total number of bytes in a transfer could be :
- * (2GB-1)number_of_blocks * the_datatype_extent.
- */
+ /* Things get a bit more complicated and require LARGE_DATATYPE processing
+ * There are two MPI datatypes that need to be created:
+ * 1) an internal contiguous block; and
+ * 2) a collection of elements where an element is a contiguous block(1).
+ * Remember that the input arguments to the MPI-IO functions use integer
+ * values to represent element counts. We ARE allowed however, in the
+ * more recent MPI implementations to use constructed datatypes whereby
+ * the total number of bytes in a transfer could be :
+ * (2GB-1)number_of_blocks * the_datatype_extent.
+ */
MPI_Aint stride_in_bytes, inner_extent;
MPI_Datatype block_type;
- /* create a contiguous datatype inner_type x number of BLOCKS.
- * Again we need to check that the number of BLOCKS can fit into
+ /* Create a contiguous datatype inner_type x number of BLOCKS.
+ * Again we need to check that the number of BLOCKS can fit into
* a 32 bit integer */
- if (bigio_count < d[i].block) {
- if (H5S_mpio_create_large_type(d[i].block, 0, inner_type,
- &block_type) < 0) {
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,
- "couldn't ccreate a large block datatype in hyper selection")
- }
- }
- else {
- if(MPI_SUCCESS != (mpi_code = MPI_Type_contiguous((int)d[i].block,
- inner_type,
- &block_type)))
+ if(bigio_count < d[i].block) {
+ if(H5_mpio_create_large_type(d[i].block, 0, inner_type, &block_type) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "couldn't create a large block datatype in hyper selection")
+ } /* end if */
+ else
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_contiguous((int)d[i].block, inner_type, &block_type)))
HMPI_GOTO_ERROR(FAIL, "MPI_Type_contiguous failed", mpi_code)
- }
- MPI_Type_extent (inner_type, &inner_extent);
+ /* As of version 4.0, OpenMPI now turns off MPI-1 API calls by default,
+ * so we're using the MPI-2 version even though we don't need the lb
+ * value.
+ */
+ {
+ MPI_Aint unused_lb_arg;
+ MPI_Type_get_extent(inner_type, &unused_lb_arg, &inner_extent);
+ }
stride_in_bytes = inner_extent * (MPI_Aint)d[i].strid;
/* If the element count is larger than what a 32 bit integer can hold,
* we call the large type creation function to handle that
*/
- if (bigio_count < d[i].count) {
- if (H5S_mpio_create_large_type (d[i].count, stride_in_bytes, block_type,
- &outer_type) < 0) {
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,
- "couldn't create a large outer datatype in hyper selection")
- }
- }
+ if(bigio_count < d[i].count) {
+ if(H5_mpio_create_large_type(d[i].count, stride_in_bytes, block_type, &outer_type) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "couldn't create a large outer datatype in hyper selection")
+ } /* end if */
/* otherwise a regular create_hvector will do */
- else {
- mpi_code = MPI_Type_create_hvector((int)d[i].count, /* count */
- 1, /* blocklength */
- stride_in_bytes, /* stride in bytes*/
- block_type, /* old type */
- &outer_type); /* new type */
- if(MPI_SUCCESS != mpi_code)
+ else
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_create_hvector((int)d[i].count, /* count */
+ 1, /* blocklength */
+ stride_in_bytes, /* stride in bytes*/
+ block_type, /* old type */
+ &outer_type))) /* new type */
HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hvector failed", mpi_code)
- }
+
MPI_Type_free(&block_type);
MPI_Type_free(&inner_type);
- }
- /****************************************
- * Then build the dimension type as (start, vector type, xtent).
- ****************************************/
- /* calculate start and extent values of this dimension */
+ } /* end else */
+
+ /****************************************
+ * Then build the dimension type as (start, vector type, xtent).
+ ****************************************/
+
+ /* Calculate start and extent values of this dimension */
start_disp = d[i].start * offset[i] * elmt_size;
new_extent = (MPI_Aint)elmt_size * max_xtent[i];
if(MPI_SUCCESS != (mpi_code = MPI_Type_get_extent(outer_type, &lb, &extent_len)))
HMPI_GOTO_ERROR(FAIL, "MPI_Type_get_extent failed", mpi_code)
/*************************************************
- * Restructure this datatype ("outer_type")
- * so that it still starts at 0, but its extent
- * is the full extent in this dimension.
- *************************************************/
+ * Restructure this datatype ("outer_type")
+ * so that it still starts at 0, but its extent
+ * is the full extent in this dimension.
+ *************************************************/
if(start_disp > 0 || extent_len < new_extent) {
MPI_Datatype interm_type;
int block_len = 1;
@@ -950,13 +934,6 @@ H5S_mpio_hyper_type(const H5S_t *space, size_t elmt_size,
/* fill in the remaining return values */
*count = 1; /* only have to move one of these suckers! */
*is_derived_type = TRUE;
- HGOTO_DONE(SUCCEED);
-
-empty:
- /* special case: empty hyperslab */
- *new_type = MPI_BYTE;
- *count = 0;
- *is_derived_type = FALSE;
done:
/* Release selection iterator */
@@ -965,21 +942,20 @@ done:
HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator")
#ifdef H5S_DEBUG
- if(H5DEBUG(S))
- HDfprintf(H5DEBUG(S), "Leave %s, count=%ld is_derived_type=%t\n",
- FUNC, *count, *is_derived_type );
+if(H5DEBUG(S))
+ HDfprintf(H5DEBUG(S), "Leave %s, count=%ld is_derived_type=%t\n", FUNC, *count, *is_derived_type);
#endif
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5S_mpio_hyper_type() */
+} /* end H5S__mpio_reg_hyper_type() */
/*-------------------------------------------------------------------------
- * Function: H5S_mpio_span_hyper_type
+ * Function: H5S__mpio_span_hyper_type
*
* Purpose: Translate an HDF5 irregular hyperslab selection into an
MPI type.
*
- * Return: non-negative on success, negative on failure.
+ * Return: Non-negative on success, negative on failure.
*
* Outputs: *new_type the MPI type corresponding to the selection
* *count how many objects of the new_type in selection
@@ -988,24 +964,23 @@ done:
*
* Programmer: kyang
*
- * Modifications:
- * Mohamad Chaarawi
- * Adding support for large datatypes (beyond the limit of a
- * 32 bit integer.
*-------------------------------------------------------------------------
*/
static herr_t
-H5S_mpio_span_hyper_type(const H5S_t *space, size_t elmt_size,
+H5S__mpio_span_hyper_type(const H5S_t *space, size_t elmt_size,
MPI_Datatype *new_type, int *count, hbool_t *is_derived_type)
{
+ H5S_mpio_mpitype_list_t type_list; /* List to track MPI data types created */
MPI_Datatype elmt_type; /* MPI datatype for an element */
hbool_t elmt_type_is_derived = FALSE; /* Whether the element type has been created */
MPI_Datatype span_type; /* MPI datatype for overall span tree */
+ hsize_t bigio_count; /* Transition point to create derived type */
hsize_t down[H5S_MAX_RANK]; /* 'down' sizes for each dimension */
+ uint64_t op_gen; /* Operation generation value */
int mpi_code; /* MPI return code */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
/* Check args */
HDassert(space);
@@ -1013,30 +988,36 @@ H5S_mpio_span_hyper_type(const H5S_t *space, size_t elmt_size,
HDassert(space->select.sel_info.hslab->span_lst);
HDassert(space->select.sel_info.hslab->span_lst->head);
+ bigio_count = H5_mpi_get_bigio_count();
/* Create the base type for an element */
- if (bigio_count >= elmt_size) {
- if(MPI_SUCCESS != (mpi_code = MPI_Type_contiguous((int)elmt_size, MPI_BYTE, &elmt_type))) {
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_contiguous failed", mpi_code)
- }
- }
- else {
- if (H5S_mpio_create_large_type (elmt_size, 0, MPI_BYTE, &elmt_type) < 0) {
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,
- "couldn't create a large element datatype in span_hyper selection")
- }
- }
+ if(bigio_count >= elmt_size) {
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_contiguous((int)elmt_size, MPI_BYTE, &elmt_type)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Type_contiguous failed", mpi_code)
+ } /* end if */
+ else
+ if(H5_mpio_create_large_type(elmt_size, 0, MPI_BYTE, &elmt_type) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "couldn't create a large element datatype in span_hyper selection")
elmt_type_is_derived = TRUE;
/* Compute 'down' sizes for each dimension */
if(H5VM_array_down(space->extent.rank, space->extent.size, down) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGETSIZE, FAIL, "couldn't compute 'down' dimension sizes")
- /* Obtain derived data type */
- if(H5S_obtain_datatype(down, space->select.sel_info.hslab->span_lst->head, &elmt_type, &span_type, elmt_size) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "couldn't obtain MPI derived data type")
- if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(&span_type)))
+ /* Acquire an operation generation value for creating MPI datatypes */
+ op_gen = H5S__hyper_get_op_gen();
+
+ /* Obtain derived MPI data type */
+ type_list.head = type_list.tail = NULL;
+ if(H5S__obtain_datatype(space->select.sel_info.hslab->span_lst, down, elmt_size, &elmt_type, &span_type, &type_list, op_gen) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "couldn't obtain MPI derived data type")
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_dup(span_type, new_type)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code)
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(new_type)))
HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code)
- *new_type = span_type;
+
+ /* Release MPI data types generated during span tree traversal */
+ if(H5S__release_datatype(&type_list) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "couldn't release MPI derived data type")
/* fill in the remaining return values */
*count = 1;
@@ -1049,16 +1030,62 @@ done:
HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code)
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5S_mpio_span_hyper_type() */
+} /* end H5S__mpio_span_hyper_type() */
/*-------------------------------------------------------------------------
- * Function: H5S_obtain_datatype
+ * Function: H5S__release_datatype
+ *
+ * Purpose: Release the MPI derived datatypes for span-tree hyperslab selection
*
- * Purpose: Obtain an MPI derived datatype based on span-tree
- * implementation
+ * Return: Non-negative on success, negative on failure.
+ *
+ * Programmer: Quincey Koziol, February 2, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5S__release_datatype(H5S_mpio_mpitype_list_t *type_list)
+{
+ H5S_mpio_mpitype_node_t *curr; /* Pointer to head of list */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity check */
+ HDassert(type_list);
+
+ /* Iterate over the list, freeing the MPI data types */
+ curr = type_list->head;
+ while(curr) {
+ H5S_mpio_mpitype_node_t *next; /* Pointer to next node in list */
+ int mpi_code; /* MPI return status code */
+
+ /* Release the MPI data type for this span tree */
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_free(&curr->type)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Type_free failed", mpi_code)
+
+ /* Get pointer to next node in list */
+ next = curr->next;
+
+ /* Free the current node */
+ curr = H5FL_FREE(H5S_mpio_mpitype_node_t, curr);
+
+ /* Advance to next node */
+ curr = next;
+ } /* end while */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S__release_datatype() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5S__obtain_datatype
*
- * Return: non-negative on success, negative on failure.
+ * Purpose: Obtain an MPI derived datatype for span-tree hyperslab selection
+ *
+ * Return: Non-negative on success, negative on failure.
*
* Outputs: *span_type the MPI type corresponding to the selection
*
@@ -1067,208 +1094,222 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5S_obtain_datatype(const hsize_t *down, H5S_hyper_span_t *span,
- const MPI_Datatype *elmt_type, MPI_Datatype *span_type, size_t elmt_size)
+H5S__obtain_datatype(H5S_hyper_span_info_t *spans, const hsize_t *down,
+ size_t elmt_size, const MPI_Datatype *elmt_type, MPI_Datatype *span_type,
+ H5S_mpio_mpitype_list_t *type_list, uint64_t op_gen)
{
+ H5S_hyper_span_t *span; /* Hyperslab span to iterate with */
+ hsize_t bigio_count; /* Transition point to create derived type */
+
size_t alloc_count = 0; /* Number of span tree nodes allocated at this level */
size_t outercount = 0; /* Number of span tree nodes at this level */
MPI_Datatype *inner_type = NULL;
hbool_t inner_types_freed = FALSE; /* Whether the inner_type MPI datatypes have been freed */
- hbool_t span_type_valid = FALSE; /* Whether the span_type MPI datatypes is valid */
- hbool_t large_block = FALSE; /* Wether the block length is larger than 32 bit integer */
int *blocklen = NULL;
MPI_Aint *disp = NULL;
- H5S_hyper_span_t *tspan = NULL; /* Temporary pointer to span tree node */
+ size_t u; /* Local index variable */
int mpi_code; /* MPI return status code */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
/* Sanity check */
- HDassert(span);
+ HDassert(spans);
+ HDassert(type_list);
+
+ bigio_count = H5_mpi_get_bigio_count();
+ /* Check if we've visited this span tree before */
+ if(spans->op_gen != op_gen) {
+ H5S_mpio_mpitype_node_t *type_node; /* Pointer to new node in MPI data type list */
+
+ /* Allocate the initial displacement & block length buffers */
+ alloc_count = H5S_MPIO_INITIAL_ALLOC_COUNT;
+ if(NULL == (disp = (MPI_Aint *)H5MM_malloc(alloc_count * sizeof(MPI_Aint))))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of displacements")
+ if(NULL == (blocklen = (int *)H5MM_malloc(alloc_count * sizeof(int))))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of block lengths")
+
+ /* If this is the fastest changing dimension, it is the base case for derived datatype. */
+ span = spans->head;
+ if(NULL == span->down) {
+ hbool_t large_block = FALSE; /* Wether the block length is larger than 32 bit integer */
+
+ outercount = 0;
+ while(span) {
+ hsize_t nelmts; /* # of elements covered by current span */
+
+ /* Check if we need to increase the size of the buffers */
+ if(outercount >= alloc_count) {
+ MPI_Aint *tmp_disp; /* Temporary pointer to new displacement buffer */
+ int *tmp_blocklen; /* Temporary pointer to new block length buffer */
+
+ /* Double the allocation count */
+ alloc_count *= 2;
+
+ /* Re-allocate the buffers */
+ if(NULL == (tmp_disp = (MPI_Aint *)H5MM_realloc(disp, alloc_count * sizeof(MPI_Aint))))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of displacements")
+ disp = tmp_disp;
+ if(NULL == (tmp_blocklen = (int *)H5MM_realloc(blocklen, alloc_count * sizeof(int))))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of block lengths")
+ blocklen = tmp_blocklen;
+ } /* end if */
- /* Allocate the initial displacement & block length buffers */
- alloc_count = H5S_MPIO_INITIAL_ALLOC_COUNT;
- if(NULL == (disp = (MPI_Aint *)H5MM_malloc(alloc_count * sizeof(MPI_Aint))))
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of displacements")
- if(NULL == (blocklen = (int *)H5MM_malloc(alloc_count * sizeof(int))))
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of block lengths")
-
- /* if this is the fastest changing dimension, it is the base case for derived datatype. */
- if(NULL == span->down) {
- tspan = span;
- outercount = 0;
- while(tspan) {
- /* Check if we need to increase the size of the buffers */
- if(outercount >= alloc_count) {
- MPI_Aint *tmp_disp; /* Temporary pointer to new displacement buffer */
- int *tmp_blocklen; /* Temporary pointer to new block length buffer */
-
- /* Double the allocation count */
- alloc_count *= 2;
-
- /* Re-allocate the buffers */
- if(NULL == (tmp_disp = (MPI_Aint *)H5MM_realloc(disp, alloc_count * sizeof(MPI_Aint))))
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of displacements")
- disp = tmp_disp;
- if(NULL == (tmp_blocklen = (int *)H5MM_realloc(blocklen, alloc_count * sizeof(int))))
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of block lengths")
- blocklen = tmp_blocklen;
+ /* Compute the number of elements to attempt in this span */
+ nelmts = (span->high - span->low) + 1;
+
+ /* Store displacement & block length */
+ disp[outercount] = (MPI_Aint)elmt_size * span->low;
+ H5_CHECK_OVERFLOW(nelmts, hsize_t, int)
+ blocklen[outercount] = (int)nelmts;
+
+ if(bigio_count < (hsize_t)blocklen[outercount])
+ large_block = TRUE; /* at least one block type is large, so set this flag to true */
+
+ span = span->next;
+ outercount++;
+ } /* end while */
+
+ /* Everything fits into integers, so cast them and use hindexed */
+ if(bigio_count >= outercount && large_block == FALSE) {
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_create_hindexed((int)outercount, blocklen, disp, *elmt_type, &spans->u.down_type)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hindexed failed", mpi_code)
} /* end if */
+ else { /* LARGE_DATATYPE:: Something doesn't fit into a 32 bit integer */
+ for(u = 0 ; u < outercount; u++) {
+ MPI_Datatype temp_type = MPI_DATATYPE_NULL;
+
+ /* create the block type from elmt_type while checking the 32 bit int limit */
+ if((hsize_t)(blocklen[u]) > bigio_count) {
+ if(H5_mpio_create_large_type(blocklen[u], 0, *elmt_type, &temp_type) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "couldn't create a large element datatype in span_hyper selection")
+ } /* end if */
+ else
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_contiguous((int)blocklen[u], *elmt_type, &temp_type)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Type_contiguous failed", mpi_code)
+
+ /* Combine the current datatype that is created with this current block type */
+ if(0 == u) /* first iteration, there is no combined datatype yet */
+ spans->u.down_type = temp_type;
+ else {
+ int bl[2] = {1, 1};
+ MPI_Aint ds[2] = {disp[u - 1], disp[u]};
+ MPI_Datatype dt[2] = {spans->u.down_type, temp_type};
+
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_create_struct(2, /* count */
+ bl, /* blocklength */
+ ds, /* stride in bytes*/
+ dt, /* old type */
+ &spans->u.down_type))) /* new type */
+ HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_struct failed", mpi_code)
+
+ /* Release previous temporary datatype */
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_free(&temp_type)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Type_free failed", mpi_code)
+ } /* end else */
+ } /* end for */
+ } /* end else (LARGE_DATATYPE::) */
+ } /* end if */
+ else {
+ MPI_Aint stride; /* Distance between inner MPI datatypes */
- /* Store displacement & block length */
- disp[outercount] = (MPI_Aint)elmt_size * tspan->low;
- H5_CHECK_OVERFLOW(tspan->nelem, hsize_t, int)
- blocklen[outercount] = (int)tspan->nelem;
- tspan = tspan->next;
+ if(NULL == (inner_type = (MPI_Datatype *)H5MM_malloc(alloc_count * sizeof(MPI_Datatype))))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of inner MPI datatypes")
- if (bigio_count < blocklen[outercount]) {
- large_block = TRUE; /* at least one block type is large, so set this flag to true */
- }
+ /* Calculate the total bytes of the lower dimension */
+ stride = (*down) * elmt_size;
- outercount++;
- } /* end while */
-
- /* Everything fits into integers, so cast them and use hindexed */
- if (bigio_count >= outercount && large_block == FALSE) {
-
- if(MPI_SUCCESS != (mpi_code = MPI_Type_create_hindexed((int)outercount, blocklen, disp, *elmt_type, span_type)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hindexed failed", mpi_code)
- span_type_valid = TRUE;
- }
- else { /* LARGE_DATATYPE:: Something doesn't fit into a 32 bit integer */
- size_t i;
-
- for (i=0 ; i<outercount ; i++) {
- MPI_Datatype temp_type = MPI_DATATYPE_NULL, outer_type = MPI_DATATYPE_NULL;
- /* create the block type from elmt_type while checking the 32 bit int limit */
- if (blocklen[i] > bigio_count) {
- if (H5S_mpio_create_large_type (blocklen[i], 0, *elmt_type, &temp_type) < 0) {
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,
- "couldn't create a large element datatype in span_hyper selection")
- }
- }
- else {
- if(MPI_SUCCESS != (mpi_code = MPI_Type_contiguous((int)blocklen[i],
- *elmt_type,
- &temp_type)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_contiguous failed", mpi_code)
- }
-
- /* combine the current datatype that is created with this current block type */
- if (0 == i) { /* first iteration, there is no combined datatype yet */
- *span_type = temp_type;
- }
- else {
- int bl[2] = {1,1};
- MPI_Aint ds[2] = {disp[i-1],disp[i]};
- MPI_Datatype dt[2] = {*span_type, temp_type};
-
- if (MPI_SUCCESS != (mpi_code = MPI_Type_create_struct (2, /* count */
- bl, /* blocklength */
- ds, /* stride in bytes*/
- dt, /* old type */
- &outer_type))){ /* new type */
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_struct failed", mpi_code)
- }
- *span_type = outer_type;
- }
-
- if (outer_type != MPI_DATATYPE_NULL)
- MPI_Type_free(&outer_type);
- /* temp_type shouldn't be freed here...
- * Note that we have simply copied it above (not MPI_Type_dup)
- * into the 'span_type' argument of the caller.
- * The caller needs to deal with it there!
- */
- }
- } /* end (LARGE_DATATYPE::) */
+ /* Loop over span nodes */
+ outercount = 0;
+ while(span) {
+ MPI_Datatype down_type; /* Temporary MPI datatype for a span tree node's children */
+ hsize_t nelmts; /* # of elements covered by current span */
+
+ /* Check if we need to increase the size of the buffers */
+ if(outercount >= alloc_count) {
+ MPI_Aint *tmp_disp; /* Temporary pointer to new displacement buffer */
+ int *tmp_blocklen; /* Temporary pointer to new block length buffer */
+ MPI_Datatype *tmp_inner_type; /* Temporary pointer to inner MPI datatype buffer */
+
+ /* Double the allocation count */
+ alloc_count *= 2;
+
+ /* Re-allocate the buffers */
+ if(NULL == (tmp_disp = (MPI_Aint *)H5MM_realloc(disp, alloc_count * sizeof(MPI_Aint))))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of displacements")
+ disp = tmp_disp;
+ if(NULL == (tmp_blocklen = (int *)H5MM_realloc(blocklen, alloc_count * sizeof(int))))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of block lengths")
+ blocklen = tmp_blocklen;
+ if(NULL == (tmp_inner_type = (MPI_Datatype *)H5MM_realloc(inner_type, alloc_count * sizeof(MPI_Datatype))))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of inner MPI datatypes")
+ inner_type = tmp_inner_type;
+ } /* end if */
- } /* end if */
- else {
- size_t u; /* Local index variable */
+ /* Displacement should be in byte and should have dimension information */
+ /* First using MPI Type vector to build derived data type for this span only */
+ /* Need to calculate the disp in byte for this dimension. */
+ disp[outercount] = span->low * stride;
+ blocklen[outercount] = 1;
- if(NULL == (inner_type = (MPI_Datatype *)H5MM_malloc(alloc_count * sizeof(MPI_Datatype))))
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of inner MPI datatypes")
+ /* Generate MPI datatype for next dimension down */
+ if(H5S__obtain_datatype(span->down, down + 1, elmt_size, elmt_type, &down_type, type_list, op_gen) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "couldn't obtain MPI derived data type")
- tspan = span;
- outercount = 0;
- while(tspan) {
- MPI_Datatype down_type; /* Temporary MPI datatype for a span tree node's children */
- MPI_Aint stride; /* Distance between inner MPI datatypes */
+ /* Compute the number of elements to attempt in this span */
+ nelmts = (span->high - span->low) + 1;
- /* Check if we need to increase the size of the buffers */
- if(outercount >= alloc_count) {
- MPI_Aint *tmp_disp; /* Temporary pointer to new displacement buffer */
- int *tmp_blocklen; /* Temporary pointer to new block length buffer */
- MPI_Datatype *tmp_inner_type; /* Temporary pointer to inner MPI datatype buffer */
-
- /* Double the allocation count */
- alloc_count *= 2;
-
- /* Re-allocate the buffers */
- if(NULL == (tmp_disp = (MPI_Aint *)H5MM_realloc(disp, alloc_count * sizeof(MPI_Aint))))
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of displacements")
- disp = tmp_disp;
- if(NULL == (tmp_blocklen = (int *)H5MM_realloc(blocklen, alloc_count * sizeof(int))))
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of block lengths")
- blocklen = tmp_blocklen;
- if(NULL == (tmp_inner_type = (MPI_Datatype *)H5MM_realloc(inner_type, alloc_count * sizeof(MPI_Datatype))))
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate array of inner MPI datatypes")
- inner_type = tmp_inner_type;
- } /* end if */
+ /* Build the MPI datatype for this node */
+ H5_CHECK_OVERFLOW(nelmts, hsize_t, int)
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_create_hvector((int)nelmts, 1, stride, down_type, &inner_type[outercount])))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hvector failed", mpi_code)
- /* Displacement should be in byte and should have dimension information */
- /* First using MPI Type vector to build derived data type for this span only */
- /* Need to calculate the disp in byte for this dimension. */
- /* Calculate the total bytes of the lower dimension */
- disp[outercount] = tspan->low * (*down) * elmt_size;
- blocklen[outercount] = 1;
+ span = span->next;
+ outercount++;
+ } /* end while */
- /* Generate MPI datatype for next dimension down */
- if(H5S_obtain_datatype(down + 1, tspan->down->head, elmt_type, &down_type, elmt_size) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "couldn't obtain MPI derived data type")
+ /* Building the whole vector datatype */
+ H5_CHECK_OVERFLOW(outercount, size_t, int)
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_create_struct((int)outercount, blocklen, disp, inner_type, &spans->u.down_type)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_struct failed", mpi_code)
- /* Build the MPI datatype for this node */
- stride = (*down) * elmt_size;
- H5_CHECK_OVERFLOW(tspan->nelem, hsize_t, int)
- if(MPI_SUCCESS != (mpi_code = MPI_Type_create_hvector((int)tspan->nelem, 1, stride, down_type, &inner_type[outercount]))) {
- MPI_Type_free(&down_type);
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hvector failed", mpi_code)
- } /* end if */
+ /* Release inner node types */
+ for(u = 0; u < outercount; u++)
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_free(&inner_type[u])))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Type_free failed", mpi_code)
+ inner_types_freed = TRUE;
+ } /* end else */
+
+ /* Allocate space for the MPI data type list node */
+ if(NULL == (type_node = H5FL_MALLOC(H5S_mpio_mpitype_node_t)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate MPI data type list node")
- /* Release MPI datatype for next dimension down */
- if(MPI_SUCCESS != (mpi_code = MPI_Type_free(&down_type)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_free failed", mpi_code)
-
- tspan = tspan->next;
- outercount++;
- } /* end while */
-
- /* building the whole vector datatype */
- H5_CHECK_OVERFLOW(outercount, size_t, int)
- if(MPI_SUCCESS != (mpi_code = MPI_Type_create_struct((int)outercount, blocklen, disp, inner_type, span_type)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_struct failed", mpi_code)
- span_type_valid = TRUE;
-
- /* Release inner node types */
- for(u = 0; u < outercount; u++)
- if(MPI_SUCCESS != (mpi_code = MPI_Type_free(&inner_type[u])))
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_free failed", mpi_code)
- inner_types_freed = TRUE;
+ /* Set up MPI type node */
+ type_node->type = spans->u.down_type;
+ type_node->next = NULL;
+
+ /* Add MPI type node to list */
+ if(type_list->head == NULL)
+ type_list->head = type_list->tail = type_node;
+ else {
+ type_list->tail->next = type_node;
+ type_list->tail = type_node;
+ } /* end else */
+
+ /* Remember that we've visited this span tree */
+ spans->op_gen = op_gen;
} /* end else */
+ /* Return MPI data type for span tree */
+ *span_type = spans->u.down_type;
+
done:
/* General cleanup */
if(inner_type != NULL) {
- if(!inner_types_freed) {
- size_t u; /* Local index variable */
-
+ if(!inner_types_freed)
for(u = 0; u < outercount; u++)
if(MPI_SUCCESS != (mpi_code = MPI_Type_free(&inner_type[u])))
HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code)
- } /* end if */
-
H5MM_free(inner_type);
} /* end if */
if(blocklen != NULL)
@@ -1276,15 +1317,8 @@ done:
if(disp != NULL)
H5MM_free(disp);
- /* Error cleanup */
- if(ret_value < 0) {
- if(span_type_valid)
- if(MPI_SUCCESS != (mpi_code = MPI_Type_free(span_type)))
- HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code)
- } /* end if */
-
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5S_obtain_datatype() */
+} /* end H5S__obtain_datatype() */
/*-------------------------------------------------------------------------
@@ -1293,7 +1327,7 @@ done:
* Purpose: Translate an HDF5 dataspace selection into an MPI type.
* Currently handle only hyperslab and "all" selections.
*
- * Return: non-negative on success, negative on failure.
+ * Return: Non-negative on success, negative on failure.
*
* Outputs: *new_type the MPI type corresponding to the selection
* *count how many objects of the new_type in selection
@@ -1305,7 +1339,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5S_mpio_space_type(const H5S_t *space, size_t elmt_size, MPI_Datatype *new_type,
+H5S_mpio_space_type(const H5S_t *space, size_t elmt_size, MPI_Datatype *new_type,
int *count, hbool_t *is_derived_type, hbool_t do_permute, hsize_t **permute_map,
hbool_t *is_permuted)
{
@@ -1326,10 +1360,10 @@ H5S_mpio_space_type(const H5S_t *space, size_t elmt_size, MPI_Datatype *new_type
* out-of-order point selection, then permute this selection which
* should be a memory selection to match the file space permutation.
*/
- if(TRUE == *is_permuted) {
+ if(TRUE == *is_permuted) {
switch(H5S_GET_SELECT_TYPE(space)) {
case H5S_SEL_NONE:
- if(H5S_mpio_none_type(new_type, count, is_derived_type) < 0)
+ if(H5S__mpio_none_type(new_type, count, is_derived_type) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "couldn't convert 'none' selection to MPI type")
break;
@@ -1339,7 +1373,7 @@ H5S_mpio_space_type(const H5S_t *space, size_t elmt_size, MPI_Datatype *new_type
/* Sanity check */
HDassert(!do_permute);
- if(H5S_mpio_permute_type(space, elmt_size, permute_map, new_type, count, is_derived_type) < 0)
+ if(H5S__mpio_permute_type(space, elmt_size, permute_map, new_type, count, is_derived_type) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "couldn't convert 'all' selection to MPI type")
break;
@@ -1354,29 +1388,28 @@ H5S_mpio_space_type(const H5S_t *space, size_t elmt_size, MPI_Datatype *new_type
else {
switch(H5S_GET_SELECT_TYPE(space)) {
case H5S_SEL_NONE:
- if(H5S_mpio_none_type(new_type, count, is_derived_type) < 0)
+ if(H5S__mpio_none_type(new_type, count, is_derived_type) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,"couldn't convert 'none' selection to MPI type")
break;
case H5S_SEL_ALL:
- if(H5S_mpio_all_type(space, elmt_size, new_type, count, is_derived_type) < 0)
+ if(H5S__mpio_all_type(space, elmt_size, new_type, count, is_derived_type) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,"couldn't convert 'all' selection to MPI type")
break;
case H5S_SEL_POINTS:
- if(H5S_mpio_point_type(space, elmt_size, new_type, count, is_derived_type, do_permute, permute_map, is_permuted) < 0)
+ if(H5S__mpio_point_type(space, elmt_size, new_type, count, is_derived_type, do_permute, permute_map, is_permuted) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "couldn't convert 'point' selection to MPI type")
break;
case H5S_SEL_HYPERSLABS:
if((H5S_SELECT_IS_REGULAR(space) == TRUE)) {
- if(H5S_mpio_hyper_type(space, elmt_size, new_type, count, is_derived_type) < 0)
+ if(H5S__mpio_reg_hyper_type(space, elmt_size, new_type, count, is_derived_type) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,"couldn't convert regular 'hyperslab' selection to MPI type")
} /* end if */
- else {
- if(H5S_mpio_span_hyper_type(space, elmt_size, new_type, count, is_derived_type) < 0)
+ else
+ if(H5S__mpio_span_hyper_type(space, elmt_size, new_type, count, is_derived_type) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,"couldn't convert irregular 'hyperslab' selection to MPI type")
- } /* end else */
break;
case H5S_SEL_ERROR:
@@ -1398,138 +1431,5 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_mpio_space_type() */
-
-/*-------------------------------------------------------------------------
- * Function: H5S_mpio_create_large_type
- *
- * Purpose: Create a large datatype of size larger than what a 32 bit integer
- * can hold.
- *
- * Return: non-negative on success, negative on failure.
- *
- * *new_type the new datatype created
- *
- * Programmer: Mohamad Chaarawi
- *
- *-------------------------------------------------------------------------
- */
-static herr_t H5S_mpio_create_large_type (hsize_t num_elements,
- MPI_Aint stride_bytes,
- MPI_Datatype old_type,
- MPI_Datatype *new_type)
-{
- int num_big_types; /* num times the 2G datatype will be repeated */
- int remaining_bytes; /* the number of bytes left that can be held in an int value */
- hsize_t leftover;
- int block_len[2];
- int mpi_code; /* MPI return code */
- MPI_Datatype inner_type, outer_type, leftover_type, type[2];
- MPI_Aint disp[2], old_extent;
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT
-
- /* Calculate how many Big MPI datatypes are needed to represent the buffer */
- num_big_types = (int)(num_elements/bigio_count);
- leftover = num_elements - num_big_types * (hsize_t)bigio_count;
- H5_CHECKED_ASSIGN(remaining_bytes, int, leftover, hsize_t);
-
- /* Create a contiguous datatype of size equal to the largest
- * number that a 32 bit integer can hold x size of old type.
- * If the displacement is 0, then the type is contiguous, otherwise
- * use type_hvector to create the type with the displacement provided
- */
- if (0 == stride_bytes) {
- if(MPI_SUCCESS != (mpi_code = MPI_Type_contiguous(bigio_count,
- old_type,
- &inner_type))) {
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_contiguous failed", mpi_code)
- }
- }
- else {
- if(MPI_SUCCESS != (mpi_code = MPI_Type_create_hvector (bigio_count,
- 1,
- stride_bytes,
- old_type,
- &inner_type))) {
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hvector failed", mpi_code)
- }
- }
-
- /* Create a contiguous datatype of the buffer (minus the remaining < 2GB part)
- * If a stride is present, use hvector type
- */
- if (0 == stride_bytes) {
- if(MPI_SUCCESS != (mpi_code = MPI_Type_contiguous(num_big_types,
- inner_type,
- &outer_type))) {
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_contiguous failed", mpi_code)
- }
- }
- else {
- if(MPI_SUCCESS != (mpi_code = MPI_Type_create_hvector (num_big_types,
- 1,
- stride_bytes,
- inner_type,
- &outer_type))) {
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hvector failed", mpi_code)
- }
- }
-
- MPI_Type_free(&inner_type);
-
- /* If there is a remaining part create a contiguous/vector datatype and then
- * use a struct datatype to encapsulate everything.
- */
- if(remaining_bytes) {
- if (stride_bytes == 0) {
- if(MPI_SUCCESS != (mpi_code = MPI_Type_contiguous (remaining_bytes,
- old_type,
- &leftover_type))) {
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_contiguous failed", mpi_code)
- }
- }
- else {
- if(MPI_SUCCESS != (mpi_code = MPI_Type_create_hvector
- ((int)(num_elements - (hsize_t)num_big_types*bigio_count),
- 1,
- stride_bytes,
- old_type,
- &leftover_type))) {
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hvector failed", mpi_code)
- }
- }
-
- MPI_Type_extent (old_type, &old_extent);
-
- /* Set up the arguments for MPI_Type_struct constructor */
- type[0] = outer_type;
- type[1] = leftover_type;
- block_len[0] = 1;
- block_len[1] = 1;
- disp[0] = 0;
- disp[1] = (old_extent+stride_bytes)*num_big_types*(MPI_Aint)bigio_count;
-
- if(MPI_SUCCESS != (mpi_code =
- MPI_Type_create_struct(2, block_len, disp, type, new_type))) {
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_struct failed", mpi_code)
- }
-
- MPI_Type_free(&outer_type);
- MPI_Type_free(&leftover_type);
- }
- else {
- /* There are no remaining bytes so just set the new type to
- * the outer type created */
- *new_type = outer_type;
- }
-
- if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(new_type)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code)
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5S_mpio_create_large_type */
-
#endif /* H5_HAVE_PARALLEL */
diff --git a/src/H5Snone.c b/src/H5Snone.c
index a8aaf7e..c262d18 100644
--- a/src/H5Snone.c
+++ b/src/H5Snone.c
@@ -18,166 +18,201 @@
* Purpose: "None" selection dataspace I/O functions.
*/
+/****************/
+/* Module Setup */
+/****************/
+
#include "H5Smodule.h" /* This source code file is part of the H5S module */
-#include "H5private.h"
-#include "H5Eprivate.h"
-#include "H5Iprivate.h"
-#include "H5Spkg.h"
-#include "H5VMprivate.h"
-#include "H5Dprivate.h"
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Iprivate.h" /* ID Functions */
+#include "H5Spkg.h" /* Dataspace functions */
+#include "H5VMprivate.h" /* Vector functions */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
-/* Static function prototypes */
+/********************/
+/* Local Prototypes */
+/********************/
/* Selection callbacks */
-static herr_t H5S_none_copy(H5S_t *dst, const H5S_t *src, hbool_t share_selection);
-static herr_t H5S_none_get_seq_list(const H5S_t *space, unsigned flags,
- H5S_sel_iter_t *iter, size_t maxseq, size_t maxbytes,
- size_t *nseq, size_t *nbytes, hsize_t *off, size_t *len);
-static herr_t H5S_none_release(H5S_t *space);
-static htri_t H5S_none_is_valid(const H5S_t *space);
-static hssize_t H5S_none_serial_size(const H5S_t *space);
-static herr_t H5S_none_serialize(const H5S_t *space, uint8_t **p);
-static herr_t H5S_none_deserialize(H5S_t *space, uint32_t version, uint8_t flags,
- const uint8_t **p);
-static herr_t H5S_none_bounds(const H5S_t *space, hsize_t *start, hsize_t *end);
-static herr_t H5S_none_offset(const H5S_t *space, hsize_t *off);
+static herr_t H5S__none_copy(H5S_t *dst, const H5S_t *src, hbool_t share_selection);
+static herr_t H5S__none_release(H5S_t *space);
+static htri_t H5S__none_is_valid(const H5S_t *space);
+static hssize_t H5S__none_serial_size(const H5S_t *space);
+static herr_t H5S__none_serialize(const H5S_t *space, uint8_t **p);
+static herr_t H5S__none_deserialize(H5S_t **space, const uint8_t **p);
+static herr_t H5S__none_bounds(const H5S_t *space, hsize_t *start, hsize_t *end);
+static herr_t H5S__none_offset(const H5S_t *space, hsize_t *off);
static int H5S__none_unlim_dim(const H5S_t *space);
-static htri_t H5S_none_is_contiguous(const H5S_t *space);
-static htri_t H5S_none_is_single(const H5S_t *space);
-static htri_t H5S_none_is_regular(const H5S_t *space);
-static herr_t H5S_none_adjust_u(H5S_t *space, const hsize_t *offset);
-static herr_t H5S_none_project_scalar(const H5S_t *space, hsize_t *offset);
-static herr_t H5S_none_project_simple(const H5S_t *space, H5S_t *new_space, hsize_t *offset);
-static herr_t H5S_none_iter_init(H5S_sel_iter_t *iter, const H5S_t *space);
+static htri_t H5S__none_is_contiguous(const H5S_t *space);
+static htri_t H5S__none_is_single(const H5S_t *space);
+static htri_t H5S__none_is_regular(const H5S_t *space);
+static htri_t H5S__none_shape_same(const H5S_t *space1, const H5S_t *space2);
+static htri_t H5S__none_intersect_block(const H5S_t *space, const hsize_t *start,
+ const hsize_t *end);
+static herr_t H5S__none_adjust_u(H5S_t *space, const hsize_t *offset);
+static herr_t H5S__none_project_scalar(const H5S_t *space, hsize_t *offset);
+static herr_t H5S__none_project_simple(const H5S_t *space, H5S_t *new_space,
+ hsize_t *offset);
+static herr_t H5S__none_iter_init(const H5S_t *space, H5S_sel_iter_t *iter);
/* Selection iteration callbacks */
-static herr_t H5S_none_iter_coords(const H5S_sel_iter_t *iter, hsize_t *coords);
-static herr_t H5S_none_iter_block(const H5S_sel_iter_t *iter, hsize_t *start, hsize_t *end);
-static hsize_t H5S_none_iter_nelmts(const H5S_sel_iter_t *iter);
-static htri_t H5S_none_iter_has_next_block(const H5S_sel_iter_t *iter);
-static herr_t H5S_none_iter_next(H5S_sel_iter_t *sel_iter, size_t nelem);
-static herr_t H5S_none_iter_next_block(H5S_sel_iter_t *sel_iter);
-static herr_t H5S_none_iter_release(H5S_sel_iter_t *sel_iter);
+static herr_t H5S__none_iter_coords(const H5S_sel_iter_t *iter, hsize_t *coords);
+static herr_t H5S__none_iter_block(const H5S_sel_iter_t *iter, hsize_t *start, hsize_t *end);
+static hsize_t H5S__none_iter_nelmts(const H5S_sel_iter_t *iter);
+static htri_t H5S__none_iter_has_next_block(const H5S_sel_iter_t *iter);
+static herr_t H5S__none_iter_next(H5S_sel_iter_t *sel_iter, size_t nelem);
+static herr_t H5S__none_iter_next_block(H5S_sel_iter_t *sel_iter);
+static herr_t H5S__none_iter_get_seq_list(H5S_sel_iter_t *iter, size_t maxseq,
+ size_t maxbytes, size_t *nseq, size_t *nbytes, hsize_t *off, size_t *len);
+static herr_t H5S__none_iter_release(H5S_sel_iter_t *sel_iter);
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
/* Selection properties for "none" selections */
const H5S_select_class_t H5S_sel_none[1] = {{
H5S_SEL_NONE,
/* Methods on selection */
- H5S_none_copy,
- H5S_none_get_seq_list,
- H5S_none_release,
- H5S_none_is_valid,
- H5S_none_serial_size,
- H5S_none_serialize,
- H5S_none_deserialize,
- H5S_none_bounds,
- H5S_none_offset,
+ H5S__none_copy,
+ H5S__none_release,
+ H5S__none_is_valid,
+ H5S__none_serial_size,
+ H5S__none_serialize,
+ H5S__none_deserialize,
+ H5S__none_bounds,
+ H5S__none_offset,
H5S__none_unlim_dim,
NULL,
- H5S_none_is_contiguous,
- H5S_none_is_single,
- H5S_none_is_regular,
- H5S_none_adjust_u,
- H5S_none_project_scalar,
- H5S_none_project_simple,
- H5S_none_iter_init,
+ H5S__none_is_contiguous,
+ H5S__none_is_single,
+ H5S__none_is_regular,
+ H5S__none_shape_same,
+ H5S__none_intersect_block,
+ H5S__none_adjust_u,
+ H5S__none_project_scalar,
+ H5S__none_project_simple,
+ H5S__none_iter_init,
}};
+
+/*******************/
+/* Local Variables */
+/*******************/
+
/* Iteration properties for "none" selections */
static const H5S_sel_iter_class_t H5S_sel_iter_none[1] = {{
H5S_SEL_NONE,
/* Methods on selection iterator */
- H5S_none_iter_coords,
- H5S_none_iter_block,
- H5S_none_iter_nelmts,
- H5S_none_iter_has_next_block,
- H5S_none_iter_next,
- H5S_none_iter_next_block,
- H5S_none_iter_release,
+ H5S__none_iter_coords,
+ H5S__none_iter_block,
+ H5S__none_iter_nelmts,
+ H5S__none_iter_has_next_block,
+ H5S__none_iter_next,
+ H5S__none_iter_next_block,
+ H5S__none_iter_get_seq_list,
+ H5S__none_iter_release,
}};
+
/*-------------------------------------------------------------------------
- * Function: H5S_none_iter_init
+ * Function: H5S__none_iter_init
*
* Purpose: Initializes iteration information for "none" selection.
*
- * Return: non-negative on success, negative on failure.
+ * Return: Non-negative on success, negative on failure.
*
* Programmer: Quincey Koziol
* Tuesday, June 16, 1998
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
static herr_t
-H5S_none_iter_init(H5S_sel_iter_t *iter, const H5S_t H5_ATTR_UNUSED *space)
+H5S__none_iter_init(const H5S_t H5_ATTR_UNUSED *space, H5S_sel_iter_t *iter)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
/* Check args */
- HDassert(space && H5S_SEL_NONE==H5S_GET_SELECT_TYPE(space));
+ HDassert(space && H5S_SEL_NONE == H5S_GET_SELECT_TYPE(space));
HDassert(iter);
/* Initialize type of selection iterator */
iter->type = H5S_sel_iter_none;
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5S_none_iter_init() */
+} /* end H5S__none_iter_init() */
/*-------------------------------------------------------------------------
- * Function: H5S_none_iter_coords
+ * Function: H5S__none_iter_coords
*
* Purpose: Retrieve the current coordinates of iterator for current
* selection
*
- * Return: non-negative on success, negative on failure
+ * Return: Non-negative on success, negative on failure
*
* Programmer: Quincey Koziol
* Tuesday, April 22, 2003
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
static herr_t
-H5S_none_iter_coords(const H5S_sel_iter_t H5_ATTR_UNUSED *iter, hsize_t H5_ATTR_UNUSED *coords)
+H5S__none_iter_coords(const H5S_sel_iter_t H5_ATTR_UNUSED *iter,
+ hsize_t H5_ATTR_UNUSED *coords)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
/* Check args */
HDassert(iter);
HDassert(coords);
FUNC_LEAVE_NOAPI(FAIL)
-} /* H5S_none_iter_coords() */
+} /* end H5S__none_iter_coords() */
/*-------------------------------------------------------------------------
- * Function: H5S_none_iter_block
+ * Function: H5S__none_iter_block
*
* Purpose: Retrieve the current block of iterator for current
* selection
*
- * Return: non-negative on success, negative on failure
+ * Return: Non-negative on success, negative on failure
*
* Programmer: Quincey Koziol
* Monday, June 2, 2003
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
static herr_t
-H5S_none_iter_block(const H5S_sel_iter_t H5_ATTR_UNUSED *iter, hsize_t H5_ATTR_UNUSED *start, hsize_t H5_ATTR_UNUSED *end)
+H5S__none_iter_block(const H5S_sel_iter_t H5_ATTR_UNUSED *iter,
+ hsize_t H5_ATTR_UNUSED *start, hsize_t H5_ATTR_UNUSED *end)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
/* Check args */
HDassert(iter);
@@ -185,42 +220,40 @@ H5S_none_iter_block(const H5S_sel_iter_t H5_ATTR_UNUSED *iter, hsize_t H5_ATTR_U
HDassert(end);
FUNC_LEAVE_NOAPI(FAIL)
-} /* H5S_none_iter_block() */
+} /* end H5S__none_iter_block() */
/*-------------------------------------------------------------------------
- * Function: H5S_none_iter_nelmts
+ * Function: H5S__none_iter_nelmts
*
* Purpose: Return number of elements left to process in iterator
*
- * Return: non-negative number of elements on success, zero on failure
+ * Return: Non-negative number of elements on success, zero on failure
*
* Programmer: Quincey Koziol
* Tuesday, June 16, 1998
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
static hsize_t
-H5S_none_iter_nelmts(const H5S_sel_iter_t H5_ATTR_UNUSED *iter)
+H5S__none_iter_nelmts(const H5S_sel_iter_t H5_ATTR_UNUSED *iter)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
/* Check args */
HDassert(iter);
FUNC_LEAVE_NOAPI(0)
-} /* H5S_none_iter_nelmts() */
+} /* end H5S__none_iter_nelmts() */
/*--------------------------------------------------------------------------
NAME
- H5S_none_iter_has_next_block
+ H5S__none_iter_has_next_block
PURPOSE
Check if there is another block left in the current iterator
USAGE
- htri_t H5S_none_iter_has_next_block(iter)
+ htri_t H5S__none_iter_has_next_block(iter)
const H5S_sel_iter_t *iter; IN: Pointer to selection iterator
RETURNS
Non-negative (TRUE/FALSE) on success/Negative on failure
@@ -232,24 +265,24 @@ H5S_none_iter_nelmts(const H5S_sel_iter_t H5_ATTR_UNUSED *iter)
REVISION LOG
--------------------------------------------------------------------------*/
static htri_t
-H5S_none_iter_has_next_block(const H5S_sel_iter_t H5_ATTR_UNUSED *iter)
+H5S__none_iter_has_next_block(const H5S_sel_iter_t H5_ATTR_UNUSED *iter)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
/* Check args */
HDassert(iter);
FUNC_LEAVE_NOAPI(FAIL)
-} /* H5S_none_iter_has_next_block() */
+} /* end H5S__none_iter_has_next_block() */
/*--------------------------------------------------------------------------
NAME
- H5S_none_iter_next
+ H5S__none_iter_next
PURPOSE
Increment selection iterator
USAGE
- herr_t H5S_none_iter_next(iter, nelem)
+ herr_t H5S__none_iter_next(iter, nelem)
H5S_sel_iter_t *iter; IN: Pointer to selection iterator
size_t nelem; IN: Number of elements to advance by
RETURNS
@@ -262,25 +295,25 @@ H5S_none_iter_has_next_block(const H5S_sel_iter_t H5_ATTR_UNUSED *iter)
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S_none_iter_next(H5S_sel_iter_t H5_ATTR_UNUSED *iter, size_t H5_ATTR_UNUSED nelem)
+H5S__none_iter_next(H5S_sel_iter_t H5_ATTR_UNUSED *iter, size_t H5_ATTR_UNUSED nelem)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
/* Check args */
HDassert(iter);
- HDassert(nelem>0);
+ HDassert(nelem > 0);
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5S_none_iter_next() */
+} /* end H5S__none_iter_next() */
/*--------------------------------------------------------------------------
NAME
- H5S_none_iter_next_block
+ H5S__none_iter_next_block
PURPOSE
Increment selection iterator to next block
USAGE
- herr_t H5S_none_iter_next(iter)
+ herr_t H5S__none_iter_next(iter)
H5S_sel_iter_t *iter; IN: Pointer to selection iterator
RETURNS
Non-negative on success/Negative on failure
@@ -292,24 +325,79 @@ H5S_none_iter_next(H5S_sel_iter_t H5_ATTR_UNUSED *iter, size_t H5_ATTR_UNUSED ne
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S_none_iter_next_block(H5S_sel_iter_t H5_ATTR_UNUSED *iter)
+H5S__none_iter_next_block(H5S_sel_iter_t H5_ATTR_UNUSED *iter)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
/* Check args */
HDassert(iter);
FUNC_LEAVE_NOAPI(FAIL)
-} /* H5S_none_iter_next_block() */
+} /* end H5S__none_iter_next_block() */
/*--------------------------------------------------------------------------
NAME
- H5S_none_iter_release
+ H5S__none_iter_get_seq_list
+ PURPOSE
+ Create a list of offsets & lengths for a selection
+ USAGE
+ herr_t H5S__none_iter_get_seq_list(iter,maxseq,maxelem,nseq,nelem,off,len)
+ H5S_sel_iter_t *iter; IN/OUT: Selection iterator describing last
+ position of interest in selection.
+ size_t maxseq; IN: Maximum number of sequences to generate
+ size_t maxelem; IN: Maximum number of elements to include in the
+ generated sequences
+ size_t *nseq; OUT: Actual number of sequences generated
+ size_t *nelem; OUT: Actual number of elements in sequences generated
+ hsize_t *off; OUT: Array of offsets
+ size_t *len; OUT: Array of lengths
+ RETURNS
+ Non-negative on success/Negative on failure.
+ DESCRIPTION
+ Use the selection in the dataspace to generate a list of byte offsets and
+ lengths for the region(s) selected. Start/Restart from the position in the
+ ITER parameter. The number of sequences generated is limited by the MAXSEQ
+ parameter and the number of sequences actually generated is stored in the
+ NSEQ parameter.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static herr_t
+H5S__none_iter_get_seq_list(H5S_sel_iter_t H5_ATTR_UNUSED *iter,
+ size_t H5_ATTR_UNUSED maxseq, size_t H5_ATTR_UNUSED maxelem, size_t *nseq,
+ size_t *nelem, hsize_t H5_ATTR_UNUSED *off, size_t H5_ATTR_UNUSED *len)
+{
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Check args */
+ HDassert(iter);
+ HDassert(maxseq > 0);
+ HDassert(maxelem > 0);
+ HDassert(nseq);
+ HDassert(nelem);
+ HDassert(off);
+ HDassert(len);
+
+ /* "none" selections don't generate sequences of bytes */
+ *nseq = 0;
+
+ /* They don't use any elements, either */
+ *nelem = 0;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5S__none_iter_get_seq_list() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S__none_iter_release
PURPOSE
Release "none" selection iterator information for a dataspace
USAGE
- herr_t H5S_none_iter_release(iter)
+ herr_t H5S__none_iter_release(iter)
H5S_sel_iter_t *iter; IN: Pointer to selection iterator
RETURNS
Non-negative on success/Negative on failure
@@ -321,24 +409,24 @@ H5S_none_iter_next_block(H5S_sel_iter_t H5_ATTR_UNUSED *iter)
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S_none_iter_release(H5S_sel_iter_t H5_ATTR_UNUSED * iter)
+H5S__none_iter_release(H5S_sel_iter_t H5_ATTR_UNUSED *iter)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
/* Check args */
HDassert(iter);
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5S_none_iter_release() */
+} /* end H5S__none_iter_release() */
/*--------------------------------------------------------------------------
NAME
- H5S_none_release
+ H5S__none_release
PURPOSE
Release none selection information for a dataspace
USAGE
- herr_t H5S_none_release(space)
+ herr_t H5S__none_release(space)
H5S_t *space; IN: Pointer to dataspace
RETURNS
Non-negative on success/Negative on failure
@@ -350,26 +438,27 @@ H5S_none_iter_release(H5S_sel_iter_t H5_ATTR_UNUSED * iter)
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S_none_release(H5S_t H5_ATTR_UNUSED * space)
+H5S__none_release(H5S_t H5_ATTR_UNUSED *space)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
/* Check args */
HDassert(space);
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5S_none_release() */
+} /* end H5S__none_release() */
/*--------------------------------------------------------------------------
NAME
- H5S_none_copy
+ H5S__none_copy
PURPOSE
Copy a selection from one dataspace to another
USAGE
- herr_t H5S_none_copy(dst, src)
+ herr_t H5S__none_copy(dst, src, share_selection)
H5S_t *dst; OUT: Pointer to the destination dataspace
H5S_t *src; IN: Pointer to the source dataspace
+ hbool_t; IN: Whether to share the selection between the dataspaces
RETURNS
Non-negative on success/Negative on failure
DESCRIPTION
@@ -381,9 +470,10 @@ H5S_none_release(H5S_t H5_ATTR_UNUSED * space)
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S_none_copy(H5S_t *dst, const H5S_t H5_ATTR_UNUSED *src, hbool_t H5_ATTR_UNUSED share_selection)
+H5S__none_copy(H5S_t *dst, const H5S_t H5_ATTR_UNUSED *src,
+ hbool_t H5_ATTR_UNUSED share_selection)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
HDassert(src);
HDassert(dst);
@@ -392,17 +482,17 @@ H5S_none_copy(H5S_t *dst, const H5S_t H5_ATTR_UNUSED *src, hbool_t H5_ATTR_UNUSE
dst->select.num_elem = 0;
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5S_none_copy() */
+} /* end H5S__none_copy() */
/*--------------------------------------------------------------------------
NAME
- H5S_none_is_valid
+ H5S__none_is_valid
PURPOSE
Check whether the selection fits within the extent, with the current
offset defined.
USAGE
- htri_t H5S_none_is_valid(space);
+ htri_t H5S__none_is_valid(space);
H5S_t *space; IN: Dataspace pointer to query
RETURNS
TRUE if the selection fits within the extent, FALSE if it does not and
@@ -416,24 +506,24 @@ H5S_none_copy(H5S_t *dst, const H5S_t H5_ATTR_UNUSED *src, hbool_t H5_ATTR_UNUSE
REVISION LOG
--------------------------------------------------------------------------*/
static htri_t
-H5S_none_is_valid(const H5S_t H5_ATTR_UNUSED *space)
+H5S__none_is_valid(const H5S_t H5_ATTR_UNUSED *space)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
HDassert(space);
FUNC_LEAVE_NOAPI(TRUE)
-} /* end H5S_none_is_valid() */
+} /* end H5S__none_is_valid() */
/*--------------------------------------------------------------------------
NAME
- H5S_none_serial_size
+ H5S__none_serial_size
PURPOSE
Determine the number of bytes needed to store the serialized "none"
selection information.
USAGE
- hssize_t H5S_none_serial_size(space)
+ hssize_t H5S__none_serial_size(space)
H5S_t *space; IN: Dataspace pointer to query
RETURNS
The number of bytes required on success, negative on an error.
@@ -446,9 +536,9 @@ H5S_none_is_valid(const H5S_t H5_ATTR_UNUSED *space)
REVISION LOG
--------------------------------------------------------------------------*/
static hssize_t
-H5S_none_serial_size(const H5S_t H5_ATTR_UNUSED *space)
+H5S__none_serial_size(const H5S_t H5_ATTR_UNUSED *space)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
HDassert(space);
@@ -457,16 +547,16 @@ H5S_none_serial_size(const H5S_t H5_ATTR_UNUSED *space)
* <length (4 bytes)> = 16 bytes
*/
FUNC_LEAVE_NOAPI(16)
-} /* end H5S_none_serial_size() */
+} /* end H5S__none_serial_size() */
/*--------------------------------------------------------------------------
NAME
- H5S_none_serialize
+ H5S__none_serialize
PURPOSE
Serialize the current selection into a user-provided buffer.
USAGE
- herr_t H5S_none_serialize(space, p)
+ herr_t H5S__none_serialize(space, p)
const H5S_t *space; IN: Dataspace with selection to serialize
uint8_t **p; OUT: Pointer to buffer to put serialized
selection. Will be advanced to end of
@@ -482,11 +572,11 @@ H5S_none_serial_size(const H5S_t H5_ATTR_UNUSED *space)
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S_none_serialize(const H5S_t *space, uint8_t **p)
+H5S__none_serialize(const H5S_t *space, uint8_t **p)
{
uint8_t *pp = (*p); /* Local pointer for decoding */
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
/* Check args */
HDassert(space);
@@ -495,7 +585,7 @@ H5S_none_serialize(const H5S_t *space, uint8_t **p)
/* Store the preamble information */
UINT32ENCODE(pp, (uint32_t)H5S_GET_SELECT_TYPE(space)); /* Store the type of selection */
- UINT32ENCODE(pp, (uint32_t)1); /* Store the version number */
+ UINT32ENCODE(pp, (uint32_t)H5S_NONE_VERSION_1); /* Store the version number */
UINT32ENCODE(pp, (uint32_t)0); /* Store the un-used padding */
UINT32ENCODE(pp, (uint32_t)0); /* Store the additional information length */
@@ -503,20 +593,18 @@ H5S_none_serialize(const H5S_t *space, uint8_t **p)
*p = pp;
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5S_none_serialize() */
+} /* end H5S__none_serialize() */
/*--------------------------------------------------------------------------
NAME
- H5S_none_deserialize
+ H5S__none_deserialize
PURPOSE
Deserialize the current selection from a user-provided buffer.
USAGE
- herr_t H5S_none_deserialize(space, version, flags, p)
- H5S_t *space; IN/OUT: Dataspace pointer to place
+ herr_t H5S__none_deserialize(space, version, flags, p)
+ H5S_t **space; IN/OUT: Dataspace pointer to place
selection into
- uint32_t version IN: Selection version
- uint8_t flags IN: Selection flags
uint8 **p; OUT: Pointer to buffer holding serialized
selection. Will be advanced to end of
serialized selection.
@@ -531,33 +619,61 @@ H5S_none_serialize(const H5S_t *space, uint8_t **p)
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S_none_deserialize(H5S_t *space, uint32_t H5_ATTR_UNUSED version, uint8_t H5_ATTR_UNUSED flags,
- const uint8_t H5_ATTR_UNUSED **p)
+H5S__none_deserialize(H5S_t **space, const uint8_t **p)
{
- herr_t ret_value = SUCCEED; /* return value */
+ H5S_t *tmp_space = NULL; /* Pointer to actual dataspace to use,
+ either *space or a newly allocated one */
+ uint32_t version; /* Version number */
+ herr_t ret_value = SUCCEED; /* return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
- HDassert(space);
HDassert(p);
HDassert(*p);
+ /* As part of the efforts to push all selection-type specific coding
+ to the callbacks, the coding for the allocation of a null dataspace
+ is moved from H5S_select_deserialize() in H5Sselect.c to here.
+ This is needed for decoding virtual layout in H5O__layout_decode() */
+ /* Allocate space if not provided */
+ if(!*space) {
+ if(NULL == (tmp_space = H5S_create(H5S_SIMPLE)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't create dataspace")
+ } /* end if */
+ else
+ tmp_space = *space;
+
+ /* Decode version */
+ UINT32DECODE(*p, version);
+
+ /* Skip over the remainder of the header */
+ *p += 8;
+
/* Change to "none" selection */
- if(H5S_select_none(space) < 0)
+ if(H5S_select_none(tmp_space) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection")
+ /* Return space to the caller if allocated */
+ if(!*space)
+ *space = tmp_space;
+
done:
+ /* Free temporary space if not passed to caller (only happens on error) */
+ if(!*space && tmp_space)
+ if(H5S_close(tmp_space) < 0)
+ HDONE_ERROR(H5E_DATASPACE, H5E_CANTFREE, FAIL, "can't close dataspace")
+
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_none_deserialize() */
+} /* end H5S__none_deserialize() */
/*--------------------------------------------------------------------------
NAME
- H5S_none_bounds
+ H5S__none_bounds
PURPOSE
Gets the bounding box containing the selection.
USAGE
- herr_t H5S_none_bounds(space, start, end)
+ herr_t H5S__none_bounds(space, start, end)
H5S_t *space; IN: Dataspace pointer of selection to query
hsize_t *start; OUT: Starting coordinate of bounding box
hsize_t *end; OUT: Opposite coordinate of bounding box
@@ -577,25 +693,26 @@ done:
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S_none_bounds(const H5S_t H5_ATTR_UNUSED *space, hsize_t H5_ATTR_UNUSED *start, hsize_t H5_ATTR_UNUSED *end)
+H5S__none_bounds(const H5S_t H5_ATTR_UNUSED *space, hsize_t H5_ATTR_UNUSED *start,
+ hsize_t H5_ATTR_UNUSED *end)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
HDassert(space);
HDassert(start);
HDassert(end);
FUNC_LEAVE_NOAPI(FAIL)
-} /* H5Sget_none_bounds() */
+} /* end H5Sget_none_bounds() */
/*--------------------------------------------------------------------------
NAME
- H5S_none_offset
+ H5S__none_offset
PURPOSE
Gets the linear offset of the first element for the selection.
USAGE
- herr_t H5S_none_offset(space, offset)
+ herr_t H5S__none_offset(space, offset)
const H5S_t *space; IN: Dataspace pointer of selection to query
hsize_t *offset; OUT: Linear offset of first element in selection
RETURNS
@@ -610,15 +727,15 @@ H5S_none_bounds(const H5S_t H5_ATTR_UNUSED *space, hsize_t H5_ATTR_UNUSED *start
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S_none_offset(const H5S_t H5_ATTR_UNUSED *space, hsize_t H5_ATTR_UNUSED *offset)
+H5S__none_offset(const H5S_t H5_ATTR_UNUSED *space, hsize_t H5_ATTR_UNUSED *offset)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
HDassert(space);
HDassert(offset);
FUNC_LEAVE_NOAPI(FAIL)
-} /* H5S_none_offset() */
+} /* end H5S__none_offset() */
/*--------------------------------------------------------------------------
@@ -651,11 +768,11 @@ H5S__none_unlim_dim(const H5S_t H5_ATTR_UNUSED *space)
/*--------------------------------------------------------------------------
NAME
- H5S_none_is_contiguous
+ H5S__none_is_contiguous
PURPOSE
Check if a "none" selection is contiguous within the dataspace extent.
USAGE
- htri_t H5S_none_is_contiguous(space)
+ htri_t H5S__none_is_contiguous(space)
H5S_t *space; IN: Dataspace pointer to check
RETURNS
TRUE/FALSE/FAIL
@@ -668,23 +785,23 @@ H5S__none_unlim_dim(const H5S_t H5_ATTR_UNUSED *space)
REVISION LOG
--------------------------------------------------------------------------*/
static htri_t
-H5S_none_is_contiguous(const H5S_t H5_ATTR_UNUSED *space)
+H5S__none_is_contiguous(const H5S_t H5_ATTR_UNUSED *space)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
HDassert(space);
FUNC_LEAVE_NOAPI(FALSE)
-} /* H5S_none_is_contiguous() */
+} /* end H5S__none_is_contiguous() */
/*--------------------------------------------------------------------------
NAME
- H5S_none_is_single
+ H5S__none_is_single
PURPOSE
Check if a "none" selection is a single block within the dataspace extent.
USAGE
- htri_t H5S_none_is_single(space)
+ htri_t H5S__none_is_single(space)
H5S_t *space; IN: Dataspace pointer to check
RETURNS
TRUE/FALSE/FAIL
@@ -697,23 +814,23 @@ H5S_none_is_contiguous(const H5S_t H5_ATTR_UNUSED *space)
REVISION LOG
--------------------------------------------------------------------------*/
static htri_t
-H5S_none_is_single(const H5S_t H5_ATTR_UNUSED *space)
+H5S__none_is_single(const H5S_t H5_ATTR_UNUSED *space)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
HDassert(space);
FUNC_LEAVE_NOAPI(FALSE)
-} /* H5S_none_is_single() */
+} /* end H5S__none_is_single() */
/*--------------------------------------------------------------------------
NAME
- H5S_none_is_regular
+ H5S__none_is_regular
PURPOSE
Check if a "none" selection is "regular"
USAGE
- htri_t H5S_none_is_regular(space)
+ htri_t H5S__none_is_regular(space)
const H5S_t *space; IN: Dataspace pointer to check
RETURNS
TRUE/FALSE/FAIL
@@ -727,24 +844,92 @@ H5S_none_is_single(const H5S_t H5_ATTR_UNUSED *space)
REVISION LOG
--------------------------------------------------------------------------*/
static htri_t
-H5S_none_is_regular(const H5S_t H5_ATTR_UNUSED *space)
+H5S__none_is_regular(const H5S_t H5_ATTR_UNUSED *space)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
/* Check args */
HDassert(space);
FUNC_LEAVE_NOAPI(TRUE)
-} /* H5S_none_is_regular() */
+} /* end H5S__none_is_regular() */
/*--------------------------------------------------------------------------
NAME
- H5S_none_adjust_u
+ H5S__none_shape_same
+ PURPOSE
+ Check if a two "none" selections are the same shape
+ USAGE
+ htri_t H5S__none_shape_same(space1, space2)
+ const H5S_t *space1; IN: First dataspace to check
+ const H5S_t *space2; IN: Second dataspace to check
+ RETURNS
+ TRUE / FALSE / FAIL
+ DESCRIPTION
+ Checks to see if the current selection in each dataspace are the same
+ shape.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static htri_t
+H5S__none_shape_same(const H5S_t H5_ATTR_UNUSED *space1,
+ const H5S_t H5_ATTR_UNUSED *space2)
+{
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Check args */
+ HDassert(space1);
+ HDassert(space2);
+
+ FUNC_LEAVE_NOAPI(TRUE)
+} /* end H5S__none_shape_same() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S__none_intersect_block
+ PURPOSE
+ Detect intersections of selection with block
+ USAGE
+ htri_t H5S__none_intersect_block(space, start, end)
+ const H5S_t *space; IN: Dataspace with selection to use
+ const hsize_t *start; IN: Starting coordinate for block
+ const hsize_t *end; IN: Ending coordinate for block
+ RETURNS
+ Non-negative TRUE / FALSE on success, negative on failure
+ DESCRIPTION
+ Quickly detect intersections with a block
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+htri_t
+H5S__none_intersect_block(const H5S_t H5_ATTR_UNUSED *space,
+ const hsize_t H5_ATTR_UNUSED *start, const hsize_t H5_ATTR_UNUSED *end)
+{
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Sanity check */
+ HDassert(space);
+ HDassert(H5S_SEL_NONE == H5S_GET_SELECT_TYPE(space));
+ HDassert(start);
+ HDassert(end);
+
+ FUNC_LEAVE_NOAPI(FALSE)
+} /* end H5S__none_intersect_block() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S__none_adjust_u
PURPOSE
Adjust an "none" selection by subtracting an offset
USAGE
- herr_t H5S_none_adjust_u(space, offset)
+ herr_t H5S__none_adjust_u(space, offset)
H5S_t *space; IN/OUT: Pointer to dataspace to adjust
const hsize_t *offset; IN: Offset to subtract
RETURNS
@@ -757,24 +942,24 @@ H5S_none_is_regular(const H5S_t H5_ATTR_UNUSED *space)
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S_none_adjust_u(H5S_t H5_ATTR_UNUSED *space, const hsize_t H5_ATTR_UNUSED *offset)
+H5S__none_adjust_u(H5S_t H5_ATTR_UNUSED *space, const hsize_t H5_ATTR_UNUSED *offset)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
/* Check args */
HDassert(space);
HDassert(offset);
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5S_none_adjust_u() */
+} /* end H5S__none_adjust_u() */
/*-------------------------------------------------------------------------
- * Function: H5S_none_project_scalar
+ * Function: H5S__none_project_scalar
*
* Purpose: Projects a 'none' selection into a scalar dataspace
*
- * Return: non-negative on success, negative on failure.
+ * Return: Non-negative on success, negative on failure.
*
* Programmer: Quincey Koziol
* Sunday, July 18, 2010
@@ -782,25 +967,25 @@ H5S_none_adjust_u(H5S_t H5_ATTR_UNUSED *space, const hsize_t H5_ATTR_UNUSED *off
*-------------------------------------------------------------------------
*/
static herr_t
-H5S_none_project_scalar(const H5S_t H5_ATTR_UNUSED *space, hsize_t H5_ATTR_UNUSED *offset)
+H5S__none_project_scalar(const H5S_t H5_ATTR_UNUSED *space, hsize_t H5_ATTR_UNUSED *offset)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
/* Check args */
HDassert(space && H5S_SEL_NONE == H5S_GET_SELECT_TYPE(space));
HDassert(offset);
FUNC_LEAVE_NOAPI(FAIL)
-} /* H5S_none_project_scalar() */
+} /* end H5S__none_project_scalar() */
/*-------------------------------------------------------------------------
- * Function: H5S_none_project_simple
+ * Function: H5S__none_project_simple
*
* Purpose: Projects an 'none' selection onto/into a simple dataspace
* of a different rank
*
- * Return: non-negative on success, negative on failure.
+ * Return: Non-negative on success, negative on failure.
*
* Programmer: Quincey Koziol
* Sunday, July 18, 2010
@@ -808,11 +993,12 @@ H5S_none_project_scalar(const H5S_t H5_ATTR_UNUSED *space, hsize_t H5_ATTR_UNUSE
*-------------------------------------------------------------------------
*/
static herr_t
-H5S_none_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *offset)
+H5S__none_project_simple(const H5S_t H5_ATTR_UNUSED *base_space,
+ H5S_t *new_space, hsize_t H5_ATTR_UNUSED *offset)
{
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
/* Check args */
HDassert(base_space && H5S_SEL_NONE == H5S_GET_SELECT_TYPE(base_space));
@@ -825,7 +1011,7 @@ H5S_none_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *offs
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_none_project_simple() */
+} /* end H5S__none_project_simple() */
/*--------------------------------------------------------------------------
@@ -867,7 +1053,7 @@ H5S_select_none(H5S_t *space)
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_select_none() */
+} /* end H5S_select_none() */
/*--------------------------------------------------------------------------
@@ -906,63 +1092,5 @@ H5Sselect_none(hid_t spaceid)
done:
FUNC_LEAVE_API(ret_value)
-} /* H5Sselect_none() */
-
-
-/*--------------------------------------------------------------------------
- NAME
- H5S_none_get_seq_list
- PURPOSE
- Create a list of offsets & lengths for a selection
- USAGE
- herr_t H5S_none_get_seq_list(space,flags,iter,maxseq,maxelem,nseq,nelem,off,len)
- H5S_t *space; IN: Dataspace containing selection to use.
- unsigned flags; IN: Flags for extra information about operation
- H5S_sel_iter_t *iter; IN/OUT: Selection iterator describing last
- position of interest in selection.
- size_t maxseq; IN: Maximum number of sequences to generate
- size_t maxelem; IN: Maximum number of elements to include in the
- generated sequences
- size_t *nseq; OUT: Actual number of sequences generated
- size_t *nelem; OUT: Actual number of elements in sequences generated
- hsize_t *off; OUT: Array of offsets
- size_t *len; OUT: Array of lengths
- RETURNS
- Non-negative on success/Negative on failure.
- DESCRIPTION
- Use the selection in the dataspace to generate a list of byte offsets and
- lengths for the region(s) selected. Start/Restart from the position in the
- ITER parameter. The number of sequences generated is limited by the MAXSEQ
- parameter and the number of sequences actually generated is stored in the
- NSEQ parameter.
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
-static herr_t
-H5S_none_get_seq_list(const H5S_t H5_ATTR_UNUSED *space, unsigned H5_ATTR_UNUSED flags, H5S_sel_iter_t H5_ATTR_UNUSED *iter,
- size_t H5_ATTR_UNUSED maxseq, size_t H5_ATTR_UNUSED maxelem, size_t *nseq, size_t *nelem,
- hsize_t H5_ATTR_UNUSED *off, size_t H5_ATTR_UNUSED *len)
-{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
-
- /* Check args */
- HDassert(space);
- HDassert(iter);
- HDassert(maxseq > 0);
- HDassert(maxelem > 0);
- HDassert(nseq);
- HDassert(nelem);
- HDassert(off);
- HDassert(len);
-
- /* "none" selections don't generate sequences of bytes */
- *nseq = 0;
-
- /* They don't use any elements, either */
- *nelem = 0;
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5S_none_get_seq_list() */
+} /* end H5Sselect_none() */
diff --git a/src/H5Spkg.h b/src/H5Spkg.h
index d895f40..278f08d 100644
--- a/src/H5Spkg.h
+++ b/src/H5Spkg.h
@@ -26,19 +26,53 @@
#ifndef _H5Spkg_H
#define _H5Spkg_H
+/* Get package's private header */
#include "H5Sprivate.h"
+/* Other private headers needed by this file */
+#include "H5Oprivate.h" /* Object headers */
+
/* Flags to indicate special dataspace features are active */
#define H5S_VALID_MAX 0x01
#define H5S_VALID_PERM 0x02
/* Flags for serialization of selections */
-#define H5S_SELECT_FLAG_UNLIM 0x01
-#define H5S_SELECT_FLAG_BITS (H5S_SELECT_FLAG_UNLIM)
+#define H5S_HYPER_REGULAR 0x01
+#define H5S_SELECT_FLAG_BITS (H5S_HYPER_REGULAR)
+
+/* Versions for H5S_SEL_HYPER selection info */
+#define H5S_HYPER_VERSION_1 1
+#define H5S_HYPER_VERSION_2 2
+#define H5S_HYPER_VERSION_3 3
+
+/* Versions for H5S_SEL_POINTS selection info */
+#define H5S_POINT_VERSION_1 1
+#define H5S_POINT_VERSION_2 2
+
+/* Versions for H5S_SEL_NONE selection info */
+#define H5S_NONE_VERSION_1 1
+
+/* Versions for H5S_SEL_ALL selection info */
+#define H5S_ALL_VERSION_1 1
+
+/* Encoded size of selection info for H5S_SEL_POINTS/H5S_SEL_HYPER */
+#define H5S_SELECT_INFO_ENC_SIZE_2 0x02 /* 2 bytes: 16 bits */
+#define H5S_SELECT_INFO_ENC_SIZE_4 0x04 /* 4 bytes: 32 bits */
+#define H5S_SELECT_INFO_ENC_SIZE_8 0x08 /* 8 bytes: 64 bits */
+#define H5S_SELECT_INFO_ENC_SIZE_BITS ( H5S_SELECT_INFO_ENC_SIZE_2 | \
+ H5S_SELECT_INFO_ENC_SIZE_4 | \
+ H5S_SELECT_INFO_ENC_SIZE_8 )
+
+#define H5S_UINT16_MAX 0x0000FFFF /* 2^16 - 1 = 65,535 */
+#define H5S_UINT32_MAX 0xFFFFFFFF /* 2^32 - 1 = 4,294,967,295 */
+#define H5S_UINT64_MAX ((hsize_t)(-1L)) /* 2^64 - 1 = 18,446,744,073,709,551,615 */
/* Length of stack-allocated sequences for "project intersect" routines */
#define H5S_PROJECT_INTERSECT_NSEQS 256
+/* Internal flags for initializing selection iterators */
+#define H5S_SEL_ITER_API_CALL 0x1000 /* Selection iterator created from API call */
+
/* Initial version of the dataspace information */
#define H5O_SDSPACE_VERSION_1 1
@@ -57,6 +91,15 @@
* H5S_UNLIMITED) */
#define H5S_MAX_SIZE ((hsize_t)(hssize_t)(-2))
+/* Macro for checking if two ranges overlap one another */
+/*
+ * Check for the inverse of whether the ranges are disjoint. If they are
+ * disjoint, then the low bound of one of the ranges must be greater than the
+ * high bound of the other.
+ */
+/* (Assumes that low & high bounds are _inclusive_) */
+#define H5S_RANGE_OVERLAP(L1, H1, L2, H2) (!((L1) > (H2) || (L2) > (H1)))
+
/*
* Dataspace extent information
@@ -77,63 +120,108 @@ struct H5S_extent_t {
/*
* Dataspace selection information
*/
+
/* Node in point selection list (typedef'd in H5Sprivate.h) */
struct H5S_pnt_node_t {
- hsize_t *pnt; /* Pointer to a selected point */
- struct H5S_pnt_node_t *next; /* pointer to next point in list */
+ struct H5S_pnt_node_t *next; /* Pointer to next point in list */
+ hsize_t pnt[]; /* Selected point */
+ /* (NOTE: This uses the C99 "flexible array member" feature) */
};
-/* Information about point selection list */
-typedef struct {
+/* Information about point selection list (typedef'd in H5Sprivate.h) */
+struct H5S_pnt_list_t {
+ /* The following two fields defines the bounding box of the whole set of points, relative to the offset */
+ hsize_t low_bounds[H5S_MAX_RANK]; /* The smallest element selected in each dimension */
+ hsize_t high_bounds[H5S_MAX_RANK]; /* The largest element selected in each dimension */
+
H5S_pnt_node_t *head; /* Pointer to head of point list */
-} H5S_pnt_list_t;
+ H5S_pnt_node_t *tail; /* Pointer to tail of point list */
+};
-/* Information about new-style hyperslab spans */
+/* Information about hyperslab spans */
-/* Information a particular hyperslab span */
+/* Information a particular hyperslab span (typedef'd in H5Sprivate.h) */
struct H5S_hyper_span_t {
- hsize_t low, high; /* Low & high bounds of span */
- hsize_t nelem; /* Number of elements in span (only needed during I/O) */
- hsize_t pstride; /* Pseudo-stride from start of previous span (only used during I/O) */
- struct H5S_hyper_span_info_t *down; /* Pointer to list of spans in next dimension down */
- struct H5S_hyper_span_t *next; /* Pointer to next span in list */
+ hsize_t low, high; /* Low & high bounds of elements selected for span, inclusive */
+ struct H5S_hyper_span_info_t *down; /* Pointer to list of spans in next dimension down */
+ struct H5S_hyper_span_t *next; /* Pointer to next span in list */
};
-/* Information about a list of hyperslab spans in one dimension */
+/* Information about a list of hyperslab spans in one dimension (typedef'd in H5Sprivate.h) */
struct H5S_hyper_span_info_t {
- unsigned count; /* Ref. count of number of spans which share this span */
- struct H5S_hyper_span_info_t *scratch; /* Scratch pointer
- * (used during copies, as mark
- * during precomputes for I/O &
- * to point to the last span in a
- * list during single element adds)
- */
- struct H5S_hyper_span_t *head; /* Pointer to list of spans in next dimension down */
+ unsigned count; /* Ref. count of number of spans which share this span */
+
+ /* The following two fields define the bounding box of this set of spans
+ * and all lower dimensions, relative to the offset.
+ */
+ /* (NOTE: The bounds arrays are _relative_ to the depth of the span_info
+ * node in the span tree, so the top node in a 5-D span tree will
+ * use indices 0-4 in the arrays to store it's bounds information,
+ * but the next level down in the span tree will use indices 0-3.
+ * So, each level in the span tree will have the 0th index in the
+ * arrays correspond to the bounds in "this" dimension, even if
+ * it's not the highest level in the span tree.
+ */
+ hsize_t *low_bounds; /* The smallest element selected in each dimension */
+ hsize_t *high_bounds; /* The largest element selected in each dimension */
+
+ /* "Operation generation" fields */
+ /* (Used during copies, 'adjust', 'nelem', and 'rebuild' operations) */
+ uint64_t op_gen; /* Generation of the scratch info */
+ union {
+ struct H5S_hyper_span_info_t *copied; /* Pointer to already copied span tree */
+ hsize_t nelmts; /* # of elements */
+ hsize_t nblocks; /* # of blocks */
+#ifdef H5_HAVE_PARALLEL
+ MPI_Datatype down_type; /* MPI datatype for span tree */
+#endif /* H5_HAVE_PARALLEL */
+ }u;
+
+ struct H5S_hyper_span_t *head; /* Pointer to the first span of list of spans in the current dimension */
+ struct H5S_hyper_span_t *tail; /* Pointer to the last span of list of spans in the current dimension */
+ hsize_t bounds[]; /* Array for storing low & high bounds */
+ /* (NOTE: This uses the C99 "flexible array member" feature) */
};
-/* Information about new-style hyperslab selection */
+/* Enum for diminfo_valid field in H5S_hyper_sel_t */
+typedef enum {
+ H5S_DIMINFO_VALID_IMPOSSIBLE, /* 0: diminfo is not valid and can never be valid with the current selection */
+ H5S_DIMINFO_VALID_NO, /* 1: diminfo is not valid but may or may not be possible to constuct */
+ H5S_DIMINFO_VALID_YES /* 2: diminfo is valid */
+} H5S_diminfo_valid_t;
+
+/* Information about 'diminfo' form of hyperslab selection */
typedef struct {
- hbool_t diminfo_valid; /* Whether the dataset has valid diminfo */
- H5S_hyper_dim_t opt_diminfo[H5S_MAX_RANK]; /* per-dim selection info */
- H5S_hyper_dim_t app_diminfo[H5S_MAX_RANK]; /* per-dim selection info */
- /* 'opt_diminfo' points to a [potentially] optimized version of the user's
- * hyperslab information. 'app_diminfo' points to the actual parameters
- * that the application used for setting the hyperslab selection. These
- * are only used for re-gurgitating the original values used to set the
- * hyperslab to the application when it queries the hyperslab selection
- * information. */
+ /* 'opt' points to a [potentially] optimized version of the user's
+ * regular hyperslab information. 'app' points to the actual parameters
+ * that the application used for setting the hyperslab selection.
+ *
+ * The 'app' values are only used for regurgitating the original values
+ * used to set the hyperslab to the application when it queries the
+ * hyperslab selection information.
+ */
+ H5S_hyper_dim_t app[H5S_MAX_RANK]; /* Application-set per-dim selection info */
+ H5S_hyper_dim_t opt[H5S_MAX_RANK]; /* Optimized per-dim selection info */
+
+ /* The following two fields defines the bounding box of the diminfo selection */
+ /* (relative to the offset) */
+ hsize_t low_bounds[H5S_MAX_RANK]; /* The smallest element selected in each dimension */
+ hsize_t high_bounds[H5S_MAX_RANK]; /* The largest element selected in each dimension */
+} H5S_hyper_diminfo_t;
+
+/* Information about hyperslab selection */
+typedef struct {
+ H5S_diminfo_valid_t diminfo_valid; /* Whether the dataset has valid diminfo */
+
+ H5S_hyper_diminfo_t diminfo; /* Dimension info form of hyperslab selection */
int unlim_dim; /* Dimension where selection is unlimited, or -1 if none */
hsize_t num_elem_non_unlim; /* # of elements in a "slice" excluding the unlimited dimension */
- H5S_hyper_span_info_t *span_lst; /* List of hyperslab span information */
+ H5S_hyper_span_info_t *span_lst; /* List of hyperslab span information of all dimensions */
} H5S_hyper_sel_t;
/* Selection information methods */
/* Method to copy a selection */
typedef herr_t (*H5S_sel_copy_func_t)(H5S_t *dst, const H5S_t *src, hbool_t share_selection);
-/* Method to retrieve a list of offset/length sequences for selection */
-typedef herr_t (*H5S_sel_get_seq_list_func_t)(const H5S_t *space, unsigned flags,
- H5S_sel_iter_t *iter, size_t maxseq, size_t maxbytes,
- size_t *nseq, size_t *nbytes, hsize_t *off, size_t *len);
/* Method to release current selection */
typedef herr_t (*H5S_sel_release_func_t)(H5S_t *space);
/* Method to determine if current selection is valid for dataspace */
@@ -143,8 +231,7 @@ typedef hssize_t (*H5S_sel_serial_size_func_t)(const H5S_t *space);
/* Method to store current selection in "serialized" form (a byte sequence suitable for storing on disk) */
typedef herr_t (*H5S_sel_serialize_func_t)(const H5S_t *space, uint8_t **p);
/* Method to create selection from "serialized" form (a byte sequence suitable for storing on disk) */
-typedef herr_t (*H5S_sel_deserialize_func_t)(H5S_t *space, uint32_t version, uint8_t flags,
- const uint8_t **p);
+typedef herr_t (*H5S_sel_deserialize_func_t)(H5S_t **space, const uint8_t **p);
/* Method to determine smallest n-D bounding box containing the current selection */
typedef herr_t (*H5S_sel_bounds_func_t)(const H5S_t *space, hsize_t *start, hsize_t *end);
/* Method to determine linear offset of initial element in selection within dataspace */
@@ -160,6 +247,10 @@ typedef htri_t (*H5S_sel_is_contiguous_func_t)(const H5S_t *space);
typedef htri_t (*H5S_sel_is_single_func_t)(const H5S_t *space);
/* Method to determine if current selection is "regular" */
typedef htri_t (*H5S_sel_is_regular_func_t)(const H5S_t *space);
+/* Method to determine if two dataspaces' selections are the same shape */
+typedef htri_t (*H5S_sel_shape_same_func_t)(const H5S_t *space1, const H5S_t *space2);
+/* Method to determine if selection intersects a block */
+typedef htri_t (*H5S_sel_intersect_block_func_t)(const H5S_t *space, const hsize_t *start, const hsize_t *end);
/* Method to adjust a selection by an offset */
typedef herr_t (*H5S_sel_adjust_u_func_t)(H5S_t *space, const hsize_t *offset);
/* Method to construct single element projection onto scalar dataspace */
@@ -167,7 +258,7 @@ typedef herr_t (*H5S_sel_project_scalar)(const H5S_t *space, hsize_t *offset);
/* Method to construct selection projection onto/into simple dataspace */
typedef herr_t (*H5S_sel_project_simple)(const H5S_t *space, H5S_t *new_space, hsize_t *offset);
/* Method to initialize iterator for current selection */
-typedef herr_t (*H5S_sel_iter_init_func_t)(H5S_sel_iter_t *sel_iter, const H5S_t *space);
+typedef herr_t (*H5S_sel_iter_init_func_t)(const H5S_t *space, H5S_sel_iter_t *sel_iter);
/* Selection class information */
typedef struct {
@@ -175,7 +266,6 @@ typedef struct {
/* Methods */
H5S_sel_copy_func_t copy; /* Method to make a copy of a selection */
- H5S_sel_get_seq_list_func_t get_seq_list; /* Method to retrieve a list of offset/length sequences for selection */
H5S_sel_release_func_t release; /* Method to release current selection */
H5S_sel_is_valid_func_t is_valid; /* Method to determine if current selection is valid for dataspace */
H5S_sel_serial_size_func_t serial_size; /* Method to determine number of bytes required to store current selection */
@@ -188,6 +278,8 @@ typedef struct {
H5S_sel_is_contiguous_func_t is_contiguous; /* Method to determine if current selection is contiguous */
H5S_sel_is_single_func_t is_single; /* Method to determine if current selection is a single block */
H5S_sel_is_regular_func_t is_regular; /* Method to determine if current selection is "regular" */
+ H5S_sel_shape_same_func_t shape_same; /* Method to determine if two dataspaces' selections are the same shape */
+ H5S_sel_intersect_block_func_t intersect_block; /* Method to determine if a dataspaces' selection intersects a block */
H5S_sel_adjust_u_func_t adjust_u; /* Method to adjust a selection by an offset */
H5S_sel_project_scalar project_scalar; /* Method to construct scalar dataspace projection */
H5S_sel_project_simple project_simple; /* Method to construct simple dataspace projection */
@@ -217,9 +309,11 @@ struct H5S_t {
/* Selection iteration methods */
/* Method to retrieve the current coordinates of iterator for current selection */
-typedef herr_t (*H5S_sel_iter_coords_func_t)(const H5S_sel_iter_t *iter, hsize_t *coords);
+typedef herr_t (*H5S_sel_iter_coords_func_t)(const H5S_sel_iter_t *iter,
+ hsize_t *coords);
/* Method to retrieve the current block of iterator for current selection */
-typedef herr_t (*H5S_sel_iter_block_func_t)(const H5S_sel_iter_t *iter, hsize_t *start, hsize_t *end);
+typedef herr_t (*H5S_sel_iter_block_func_t)(const H5S_sel_iter_t *iter,
+ hsize_t *start, hsize_t *end);
/* Method to determine number of elements left in iterator for current selection */
typedef hsize_t (*H5S_sel_iter_nelmts_func_t)(const H5S_sel_iter_t *iter);
/* Method to determine if there are more blocks left in the current selection */
@@ -228,6 +322,10 @@ typedef htri_t (*H5S_sel_iter_has_next_block_func_t)(const H5S_sel_iter_t *iter)
typedef herr_t (*H5S_sel_iter_next_func_t)(H5S_sel_iter_t *iter, size_t nelem);
/* Method to move selection iterator to the next block in the selection */
typedef herr_t (*H5S_sel_iter_next_block_func_t)(H5S_sel_iter_t *iter);
+/* Method to retrieve a list of offset/length sequences for selection iterator */
+typedef herr_t (*H5S_sel_iter_get_seq_list_func_t)(H5S_sel_iter_t *iter,
+ size_t maxseq, size_t maxbytes, size_t *nseq, size_t *nbytes, hsize_t *off,
+ size_t *len);
/* Method to release iterator for current selection */
typedef herr_t (*H5S_sel_iter_release_func_t)(H5S_sel_iter_t *iter);
@@ -242,6 +340,7 @@ typedef struct H5S_sel_iter_class_t {
H5S_sel_iter_has_next_block_func_t iter_has_next_block; /* Method to query if there is another block left in the selection */
H5S_sel_iter_next_func_t iter_next; /* Method to move selection iterator to the next element in the selection */
H5S_sel_iter_next_block_func_t iter_next_block; /* Method to move selection iterator to the next block in the selection */
+ H5S_sel_iter_get_seq_list_func_t iter_get_seq_list; /* Method to retrieve a list of offset/length sequences for selection iterator */
H5S_sel_iter_release_func_t iter_release; /* Method to release iterator for current selection */
} H5S_sel_iter_class_t;
@@ -269,20 +368,24 @@ H5_DLLVAR const H5S_select_class_t H5S_sel_point[1];
H5_DLLVAR const unsigned H5O_sdspace_ver_bounds[H5F_LIBVER_NBOUNDS];
/* Extent functions */
-H5_DLL herr_t H5S_extent_release(H5S_extent_t *extent);
-H5_DLL herr_t H5S_extent_copy_real(H5S_extent_t *dst, const H5S_extent_t *src,
+H5_DLL herr_t H5S__extent_release(H5S_extent_t *extent);
+H5_DLL herr_t H5S__extent_copy_real(H5S_extent_t *dst, const H5S_extent_t *src,
hbool_t copy_max);
-/* Operations on selections */
+/* Operations on hyperslab selections */
+H5_DLL uint64_t H5S__hyper_get_op_gen(void);
+H5_DLL void H5S__hyper_rebuild(H5S_t *space);
+H5_DLL herr_t H5S__modify_select(H5S_t *space1, H5S_seloper_t op, H5S_t *space2);
H5_DLL herr_t H5S__hyper_project_intersection(const H5S_t *src_space,
- const H5S_t *dst_space, const H5S_t *src_intersect_space,
- H5S_t *proj_space);
-H5_DLL herr_t H5S__hyper_subtract(H5S_t *space, H5S_t *subtract_space);
+ const H5S_t *dst_space, const H5S_t *src_intersect_space, H5S_t *proj_space);
/* Testing functions */
#ifdef H5S_TESTING
-H5_DLL htri_t H5S_select_shape_same_test(hid_t sid1, hid_t sid2);
-H5_DLL htri_t H5S_get_rebuild_status_test(hid_t space_id);
+H5_DLL herr_t H5S__get_rebuild_status_test(hid_t space_id,
+ H5S_diminfo_valid_t *status1, H5S_diminfo_valid_t *status2);
+H5_DLL herr_t H5S__get_diminfo_status_test(hid_t space_id,
+ H5S_diminfo_valid_t *status);
+H5_DLL htri_t H5S__internal_consistency_test(hid_t space_id);
#endif /* H5S_TESTING */
#endif /*_H5Spkg_H*/
diff --git a/src/H5Spoint.c b/src/H5Spoint.c
index 9924920..ea6c9c5 100644
--- a/src/H5Spoint.c
+++ b/src/H5Spoint.c
@@ -15,185 +15,259 @@
* Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
* Tuesday, June 16, 1998
*
- * Purpose: Point selection dataspace I/O functions.
+ * Purpose: Point selection dataspace I/O functions.
*/
+/****************/
+/* Module Setup */
+/****************/
+
#include "H5Smodule.h" /* This source code file is part of the H5S module */
-#include "H5private.h" /* Generic Functions */
-#include "H5Eprivate.h" /* Error handling */
-#include "H5FLprivate.h" /* Free Lists */
-#include "H5Iprivate.h" /* ID Functions */
-#include "H5MMprivate.h" /* Memory Management functions */
-#include "H5Spkg.h" /* Dataspace functions */
-#include "H5VMprivate.h" /* Vector functions */
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5CXprivate.h" /* API Contexts */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5FLprivate.h" /* Free Lists */
+#include "H5Iprivate.h" /* ID Functions */
+#include "H5MMprivate.h" /* Memory management */
+#include "H5Spkg.h" /* Dataspace functions */
+#include "H5VMprivate.h" /* Vector functions */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
-/* Static function prototypes */
+/* Define alias for hsize_t, for allocating H5S_pnt_node_t + point objects */
+/* (Makes it easier to understand the alloc / free calls) */
+typedef hsize_t hcoords_t;
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+static herr_t H5S__point_add(H5S_t *space, H5S_seloper_t op, size_t num_elem,
+ const hsize_t *coord);
+static H5S_pnt_list_t *H5S__copy_pnt_list(const H5S_pnt_list_t *src,
+ unsigned rank);
+static void H5S__free_pnt_list(H5S_pnt_list_t *pnt_lst);
/* Selection callbacks */
-static herr_t H5S_point_copy(H5S_t *dst, const H5S_t *src, hbool_t share_selection);
-static herr_t H5S_point_get_seq_list(const H5S_t *space, unsigned flags,
- H5S_sel_iter_t *iter, size_t maxseq, size_t maxbytes,
- size_t *nseq, size_t *nbytes, hsize_t *off, size_t *len);
-static herr_t H5S_point_release(H5S_t *space);
-static htri_t H5S_point_is_valid(const H5S_t *space);
-static hssize_t H5S_point_serial_size(const H5S_t *space);
-static herr_t H5S_point_serialize(const H5S_t *space, uint8_t **p);
-static herr_t H5S_point_deserialize(H5S_t *space, uint32_t version, uint8_t flags,
- const uint8_t **p);
-static herr_t H5S_point_bounds(const H5S_t *space, hsize_t *start, hsize_t *end);
-static herr_t H5S_point_offset(const H5S_t *space, hsize_t *off);
+static herr_t H5S__point_copy(H5S_t *dst, const H5S_t *src, hbool_t share_selection);
+static herr_t H5S__point_release(H5S_t *space);
+static htri_t H5S__point_is_valid(const H5S_t *space);
+static hssize_t H5S__point_serial_size(const H5S_t *space);
+static herr_t H5S__point_serialize(const H5S_t *space, uint8_t **p);
+static herr_t H5S__point_deserialize(H5S_t **space, const uint8_t **p);
+static herr_t H5S__point_bounds(const H5S_t *space, hsize_t *start, hsize_t *end);
+static herr_t H5S__point_offset(const H5S_t *space, hsize_t *off);
static int H5S__point_unlim_dim(const H5S_t *space);
-static htri_t H5S_point_is_contiguous(const H5S_t *space);
-static htri_t H5S_point_is_single(const H5S_t *space);
-static htri_t H5S_point_is_regular(const H5S_t *space);
-static herr_t H5S_point_adjust_u(H5S_t *space, const hsize_t *offset);
-static herr_t H5S_point_project_scalar(const H5S_t *space, hsize_t *offset);
-static herr_t H5S_point_project_simple(const H5S_t *space, H5S_t *new_space, hsize_t *offset);
-static herr_t H5S_point_iter_init(H5S_sel_iter_t *iter, const H5S_t *space);
+static htri_t H5S__point_is_contiguous(const H5S_t *space);
+static htri_t H5S__point_is_single(const H5S_t *space);
+static htri_t H5S__point_is_regular(const H5S_t *space);
+static htri_t H5S__point_shape_same(const H5S_t *space1, const H5S_t *space2);
+static htri_t H5S__point_intersect_block(const H5S_t *space, const hsize_t *start,
+ const hsize_t *end);
+static herr_t H5S__point_adjust_u(H5S_t *space, const hsize_t *offset);
+static herr_t H5S__point_project_scalar(const H5S_t *space, hsize_t *offset);
+static herr_t H5S__point_project_simple(const H5S_t *space, H5S_t *new_space,
+ hsize_t *offset);
+static herr_t H5S__point_iter_init(const H5S_t *space, H5S_sel_iter_t *iter);
+static herr_t H5S__point_get_version_enc_size(const H5S_t *space,
+ uint32_t *version, uint8_t *enc_size);
/* Selection iteration callbacks */
-static herr_t H5S_point_iter_coords(const H5S_sel_iter_t *iter, hsize_t *coords);
-static herr_t H5S_point_iter_block(const H5S_sel_iter_t *iter, hsize_t *start, hsize_t *end);
-static hsize_t H5S_point_iter_nelmts(const H5S_sel_iter_t *iter);
-static htri_t H5S_point_iter_has_next_block(const H5S_sel_iter_t *iter);
-static herr_t H5S_point_iter_next(H5S_sel_iter_t *sel_iter, size_t nelem);
-static herr_t H5S_point_iter_next_block(H5S_sel_iter_t *sel_iter);
-static herr_t H5S_point_iter_release(H5S_sel_iter_t *sel_iter);
+static herr_t H5S__point_iter_coords(const H5S_sel_iter_t *iter, hsize_t *coords);
+static herr_t H5S__point_iter_block(const H5S_sel_iter_t *iter, hsize_t *start,
+ hsize_t *end);
+static hsize_t H5S__point_iter_nelmts(const H5S_sel_iter_t *iter);
+static htri_t H5S__point_iter_has_next_block(const H5S_sel_iter_t *iter);
+static herr_t H5S__point_iter_next(H5S_sel_iter_t *sel_iter, size_t nelem);
+static herr_t H5S__point_iter_next_block(H5S_sel_iter_t *sel_iter);
+static herr_t H5S__point_iter_get_seq_list(H5S_sel_iter_t *iter, size_t maxseq,
+ size_t maxbytes, size_t *nseq, size_t *nbytes, hsize_t *off, size_t *len);
+static herr_t H5S__point_iter_release(H5S_sel_iter_t *sel_iter);
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
/* Selection properties for point selections */
const H5S_select_class_t H5S_sel_point[1] = {{
H5S_SEL_POINTS,
/* Methods on selection */
- H5S_point_copy,
- H5S_point_get_seq_list,
- H5S_point_release,
- H5S_point_is_valid,
- H5S_point_serial_size,
- H5S_point_serialize,
- H5S_point_deserialize,
- H5S_point_bounds,
- H5S_point_offset,
+ H5S__point_copy,
+ H5S__point_release,
+ H5S__point_is_valid,
+ H5S__point_serial_size,
+ H5S__point_serialize,
+ H5S__point_deserialize,
+ H5S__point_bounds,
+ H5S__point_offset,
H5S__point_unlim_dim,
NULL,
- H5S_point_is_contiguous,
- H5S_point_is_single,
- H5S_point_is_regular,
- H5S_point_adjust_u,
- H5S_point_project_scalar,
- H5S_point_project_simple,
- H5S_point_iter_init,
+ H5S__point_is_contiguous,
+ H5S__point_is_single,
+ H5S__point_is_regular,
+ H5S__point_shape_same,
+ H5S__point_intersect_block,
+ H5S__point_adjust_u,
+ H5S__point_project_scalar,
+ H5S__point_project_simple,
+ H5S__point_iter_init,
}};
+/* Format version bounds for dataspace hyperslab selection */
+const unsigned H5O_sds_point_ver_bounds[] = {
+ H5S_POINT_VERSION_1, /* H5F_LIBVER_EARLIEST */
+ H5S_POINT_VERSION_1, /* H5F_LIBVER_V18 */
+ H5S_POINT_VERSION_1, /* H5F_LIBVER_V110 */
+ H5S_POINT_VERSION_2, /* H5F_LIBVER_V112 */
+ H5S_POINT_VERSION_2 /* H5F_LIBVER_LATEST */
+};
+
+/*******************/
+/* Local Variables */
+/*******************/
+
/* Iteration properties for point selections */
static const H5S_sel_iter_class_t H5S_sel_iter_point[1] = {{
H5S_SEL_POINTS,
/* Methods on selection iterator */
- H5S_point_iter_coords,
- H5S_point_iter_block,
- H5S_point_iter_nelmts,
- H5S_point_iter_has_next_block,
- H5S_point_iter_next,
- H5S_point_iter_next_block,
- H5S_point_iter_release,
+ H5S__point_iter_coords,
+ H5S__point_iter_block,
+ H5S__point_iter_nelmts,
+ H5S__point_iter_has_next_block,
+ H5S__point_iter_next,
+ H5S__point_iter_next_block,
+ H5S__point_iter_get_seq_list,
+ H5S__point_iter_release,
}};
-/* Declare a free list to manage the H5S_pnt_node_t struct */
-H5FL_DEFINE_STATIC(H5S_pnt_node_t);
+/* Declare a free list to manage the H5S_pnt_node_t + hcoords_t array struct */
+H5FL_BARR_DEFINE_STATIC(H5S_pnt_node_t, hcoords_t, H5S_MAX_RANK);
/* Declare a free list to manage the H5S_pnt_list_t struct */
H5FL_DEFINE_STATIC(H5S_pnt_list_t);
-
+
+
/*-------------------------------------------------------------------------
- * Function: H5S_point_iter_init
+ * Function: H5S__point_iter_init
*
- * Purpose: Initializes iteration information for point selection.
+ * Purpose: Initializes iteration information for point selection.
*
- * Return: non-negative on success, negative on failure.
+ * Return: Non-negative on success, negative on failure.
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* Tuesday, June 16, 1998
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
static herr_t
-H5S_point_iter_init(H5S_sel_iter_t *iter, const H5S_t *space)
+H5S__point_iter_init(const H5S_t *space, H5S_sel_iter_t *iter)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
/* Check args */
- HDassert(space && H5S_SEL_POINTS==H5S_GET_SELECT_TYPE(space));
+ HDassert(space && H5S_SEL_POINTS == H5S_GET_SELECT_TYPE(space));
HDassert(iter);
- /* Initialize the number of points to iterate over */
- iter->elmt_left=space->select.num_elem;
+ /* If this iterator is created from an API call, by default we clone the
+ * selection now, as the dataspace could be modified or go out of scope.
+ *
+ * However, if the H5S_SEL_ITER_SHARE_WITH_DATASPACE flag is given,
+ * the selection is shared between the selection iterator and the
+ * dataspace. In this case, the application _must_not_ modify or
+ * close the dataspace that the iterator is operating on, or undefined
+ * behavior will occur.
+ */
+ if((iter->flags & H5S_SEL_ITER_API_CALL) &&
+ !(iter->flags & H5S_SEL_ITER_SHARE_WITH_DATASPACE)) {
+ /* Copy the point list */
+ if(NULL == (iter->u.pnt.pnt_lst = H5S__copy_pnt_list(space->select.sel_info.pnt_lst, space->extent.rank)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy point list")
+ } /* end if */
+ else
+ /* OK to share point list for internal iterations */
+ iter->u.pnt.pnt_lst = space->select.sel_info.pnt_lst;
/* Start at the head of the list of points */
- iter->u.pnt.curr=space->select.sel_info.pnt_lst->head;
+ iter->u.pnt.curr = iter->u.pnt.pnt_lst->head;
/* Initialize type of selection iterator */
- iter->type=H5S_sel_iter_point;
+ iter->type = H5S_sel_iter_point;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S__point_iter_init() */
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5S_point_iter_init() */
-
/*-------------------------------------------------------------------------
- * Function: H5S_point_iter_coords
+ * Function: H5S__point_iter_coords
*
- * Purpose: Retrieve the current coordinates of iterator for current
+ * Purpose: Retrieve the current coordinates of iterator for current
* selection
*
- * Return: non-negative on success, negative on failure
+ * Return: Non-negative on success, negative on failure
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* Tuesday, April 22, 2003
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
static herr_t
-H5S_point_iter_coords (const H5S_sel_iter_t *iter, hsize_t *coords)
+H5S__point_iter_coords(const H5S_sel_iter_t *iter, hsize_t *coords)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
/* Check args */
HDassert(iter);
HDassert(coords);
/* Copy the offset of the current point */
- HDmemcpy(coords,iter->u.pnt.curr->pnt,sizeof(hsize_t)*iter->rank);
+ H5MM_memcpy(coords, iter->u.pnt.curr->pnt, sizeof(hsize_t) * iter->rank);
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5S_point_iter_coords() */
+} /* end H5S__point_iter_coords() */
+
-
/*-------------------------------------------------------------------------
- * Function: H5S_point_iter_block
+ * Function: H5S__point_iter_block
*
- * Purpose: Retrieve the current block of iterator for current
+ * Purpose: Retrieve the current block of iterator for current
* selection
*
- * Return: non-negative on success, negative on failure
+ * Return: Non-negative on success, negative on failure
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* Monday, June 2, 2003
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
static herr_t
-H5S_point_iter_block (const H5S_sel_iter_t *iter, hsize_t *start, hsize_t *end)
+H5S__point_iter_block(const H5S_sel_iter_t *iter, hsize_t *start, hsize_t *end)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
/* Check args */
HDassert(iter);
@@ -201,46 +275,44 @@ H5S_point_iter_block (const H5S_sel_iter_t *iter, hsize_t *start, hsize_t *end)
HDassert(end);
/* Copy the current point as a block */
- HDmemcpy(start,iter->u.pnt.curr->pnt,sizeof(hsize_t)*iter->rank);
- HDmemcpy(end,iter->u.pnt.curr->pnt,sizeof(hsize_t)*iter->rank);
+ H5MM_memcpy(start, iter->u.pnt.curr->pnt, sizeof(hsize_t) * iter->rank);
+ H5MM_memcpy(end, iter->u.pnt.curr->pnt, sizeof(hsize_t) * iter->rank);
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5S_point_iter_block() */
+} /* end H5S__point_iter_block() */
+
-
/*-------------------------------------------------------------------------
- * Function: H5S_point_iter_nelmts
+ * Function: H5S__point_iter_nelmts
*
- * Purpose: Return number of elements left to process in iterator
+ * Purpose: Return number of elements left to process in iterator
*
- * Return: non-negative number of elements on success, zero on failure
+ * Return: Non-negative number of elements on success, zero on failure
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* Tuesday, June 16, 1998
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
static hsize_t
-H5S_point_iter_nelmts (const H5S_sel_iter_t *iter)
+H5S__point_iter_nelmts(const H5S_sel_iter_t *iter)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
/* Check args */
HDassert(iter);
FUNC_LEAVE_NOAPI(iter->elmt_left)
-} /* H5S_point_iter_nelmts() */
+} /* end H5S__point_iter_nelmts() */
+
-
/*--------------------------------------------------------------------------
NAME
- H5S_point_iter_has_next_block
+ H5S__point_iter_has_next_block
PURPOSE
Check if there is another block left in the current iterator
USAGE
- htri_t H5S_point_iter_has_next_block(iter)
+ htri_t H5S__point_iter_has_next_block(iter)
const H5S_sel_iter_t *iter; IN: Pointer to selection iterator
RETURNS
Non-negative (TRUE/FALSE) on success/Negative on failure
@@ -252,31 +324,31 @@ H5S_point_iter_nelmts (const H5S_sel_iter_t *iter)
REVISION LOG
--------------------------------------------------------------------------*/
static htri_t
-H5S_point_iter_has_next_block(const H5S_sel_iter_t *iter)
+H5S__point_iter_has_next_block(const H5S_sel_iter_t *iter)
{
- htri_t ret_value=TRUE; /* Return value */
+ htri_t ret_value = TRUE; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
/* Check args */
HDassert(iter);
/* Check if there is another point in the list */
- if(iter->u.pnt.curr->next==NULL)
+ if(iter->u.pnt.curr->next == NULL)
HGOTO_DONE(FALSE);
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_point_iter_has_next_block() */
+} /* end H5S__point_iter_has_next_block() */
+
-
/*--------------------------------------------------------------------------
NAME
- H5S_point_iter_next
+ H5S__point_iter_next
PURPOSE
Increment selection iterator
USAGE
- herr_t H5S_point_iter_next(iter, nelem)
+ herr_t H5S__point_iter_next(iter, nelem)
H5S_sel_iter_t *iter; IN: Pointer to selection iterator
size_t nelem; IN: Number of elements to advance by
RETURNS
@@ -289,31 +361,31 @@ done:
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S_point_iter_next(H5S_sel_iter_t *iter, size_t nelem)
+H5S__point_iter_next(H5S_sel_iter_t *iter, size_t nelem)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
/* Check args */
HDassert(iter);
- HDassert(nelem>0);
+ HDassert(nelem > 0);
/* Increment the iterator */
- while(nelem>0) {
- iter->u.pnt.curr=iter->u.pnt.curr->next;
+ while(nelem > 0) {
+ iter->u.pnt.curr = iter->u.pnt.curr->next;
nelem--;
} /* end while */
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5S_point_iter_next() */
+} /* end H5S__point_iter_next() */
+
-
/*--------------------------------------------------------------------------
NAME
- H5S_point_iter_next_block
+ H5S__point_iter_next_block
PURPOSE
Increment selection iterator to next block
USAGE
- herr_t H5S_point_iter_next_block(iter)
+ herr_t H5S__point_iter_next_block(iter)
H5S_sel_iter_t *iter; IN: Pointer to selection iterator
RETURNS
Non-negative on success/Negative on failure
@@ -325,27 +397,158 @@ H5S_point_iter_next(H5S_sel_iter_t *iter, size_t nelem)
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S_point_iter_next_block(H5S_sel_iter_t *iter)
+H5S__point_iter_next_block(H5S_sel_iter_t *iter)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
/* Check args */
HDassert(iter);
/* Increment the iterator */
- iter->u.pnt.curr=iter->u.pnt.curr->next;
+ iter->u.pnt.curr = iter->u.pnt.curr->next;
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5S_point_iter_next_block() */
+} /* end H5S__point_iter_next_block() */
+
-
/*--------------------------------------------------------------------------
NAME
- H5S_point_iter_release
+ H5S__point_iter_get_seq_list
+ PURPOSE
+ Create a list of offsets & lengths for a selection
+ USAGE
+ herr_t H5S__point_iter_get_seq_list(iter,maxseq,maxelem,nseq,nelem,off,len)
+ H5S_sel_iter_t *iter; IN/OUT: Selection iterator describing last
+ position of interest in selection.
+ size_t maxseq; IN: Maximum number of sequences to generate
+ size_t maxelem; IN: Maximum number of elements to include in the
+ generated sequences
+ size_t *nseq; OUT: Actual number of sequences generated
+ size_t *nelem; OUT: Actual number of elements in sequences generated
+ hsize_t *off; OUT: Array of offsets (in bytes)
+ size_t *len; OUT: Array of lengths (in bytes)
+ RETURNS
+ Non-negative on success/Negative on failure.
+ DESCRIPTION
+ Use the selection in the dataspace to generate a list of byte offsets and
+ lengths for the region(s) selected. Start/Restart from the position in the
+ ITER parameter. The number of sequences generated is limited by the MAXSEQ
+ parameter and the number of sequences actually generated is stored in the
+ NSEQ parameter.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static herr_t
+H5S__point_iter_get_seq_list(H5S_sel_iter_t *iter, size_t maxseq, size_t maxelem,
+ size_t *nseq, size_t *nelem, hsize_t *off, size_t *len)
+{
+ size_t io_left; /* The number of bytes left in the selection */
+ size_t start_io_left; /* The initial number of bytes left in the selection */
+ H5S_pnt_node_t *node; /* Point node */
+ unsigned ndims; /* Dimensionality of dataspace*/
+ hsize_t acc; /* Coordinate accumulator */
+ hsize_t loc; /* Coordinate offset */
+ size_t curr_seq; /* Current sequence being operated on */
+ int i; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* return value */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Check args */
+ HDassert(iter);
+ HDassert(maxseq > 0);
+ HDassert(maxelem > 0);
+ HDassert(nseq);
+ HDassert(nelem);
+ HDassert(off);
+ HDassert(len);
+
+ /* Choose the minimum number of bytes to sequence through */
+ H5_CHECK_OVERFLOW(iter->elmt_left, hsize_t, size_t);
+ start_io_left = io_left = (size_t)MIN(iter->elmt_left, maxelem);
+
+ /* Get the dataspace's rank */
+ ndims = iter->rank;
+
+ /* Walk through the points in the selection, starting at the current */
+ /* location in the iterator */
+ node = iter->u.pnt.curr;
+ curr_seq = 0;
+ while(NULL != node) {
+ /* Compute the offset of each selected point in the buffer */
+ for(i = (int)(ndims - 1), acc = iter->elmt_size, loc = 0; i >= 0; i--) {
+ loc += (hsize_t)((hssize_t)node->pnt[i] + iter->sel_off[i]) * acc;
+ acc *= iter->dims[i];
+ } /* end for */
+
+ /* Check if this is a later point in the selection */
+ if(curr_seq > 0) {
+ /* If a sorted sequence is requested, make certain we don't go backwards in the offset */
+ if((iter->flags & H5S_SEL_ITER_GET_SEQ_LIST_SORTED) && loc < off[curr_seq - 1])
+ break;
+
+ /* Check if this point extends the previous sequence */
+ /* (Unlikely, but possible) */
+ if(loc == (off[curr_seq - 1] + len[curr_seq - 1])) {
+ /* Extend the previous sequence */
+ len[curr_seq - 1] += iter->elmt_size;
+ } /* end if */
+ else {
+ /* Add a new sequence */
+ off[curr_seq] = loc;
+ len[curr_seq] = iter->elmt_size;
+
+ /* Increment sequence count */
+ curr_seq++;
+ } /* end else */
+ } /* end if */
+ else {
+ /* Add a new sequence */
+ off[curr_seq] = loc;
+ len[curr_seq] = iter->elmt_size;
+
+ /* Increment sequence count */
+ curr_seq++;
+ } /* end else */
+
+ /* Decrement number of elements left to process */
+ io_left--;
+
+ /* Move the iterator */
+ iter->u.pnt.curr = node->next;
+ iter->elmt_left--;
+
+ /* Check if we're finished with all sequences */
+ if(curr_seq == maxseq)
+ break;
+
+ /* Check if we're finished with all the elements available */
+ if(io_left == 0)
+ break;
+
+ /* Advance to the next point */
+ node = node->next;
+ } /* end while */
+
+ /* Set the number of sequences generated */
+ *nseq = curr_seq;
+
+ /* Set the number of elements used */
+ *nelem = start_io_left - io_left;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S__point_iter_get_seq_list() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S__point_iter_release
PURPOSE
Release point selection iterator information for a dataspace
USAGE
- herr_t H5S_point_iter_release(iter)
+ herr_t H5S__point_iter_release(iter)
H5S_sel_iter_t *iter; IN: Pointer to selection iterator
RETURNS
Non-negative on success/Negative on failure
@@ -357,24 +560,29 @@ H5S_point_iter_next_block(H5S_sel_iter_t *iter)
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S_point_iter_release (H5S_sel_iter_t H5_ATTR_UNUSED * iter)
+H5S__point_iter_release(H5S_sel_iter_t * iter)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
/* Check args */
HDassert(iter);
+ /* If this iterator copied the point list, we must free it */
+ if((iter->flags & H5S_SEL_ITER_API_CALL) &&
+ !(iter->flags & H5S_SEL_ITER_SHARE_WITH_DATASPACE))
+ H5S__free_pnt_list(iter->u.pnt.pnt_lst);
+
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5S_point_iter_release() */
+} /* end H5S__point_iter_release() */
+
-
/*--------------------------------------------------------------------------
NAME
- H5S_point_add
+ H5S__point_add
PURPOSE
Add a series of elements to a point selection
USAGE
- herr_t H5S_point_add(space, num_elem, coord)
+ herr_t H5S__point_add(space, num_elem, coord)
H5S_t *space; IN: Dataspace of selection to modify
size_t num_elem; IN: Number of elements in COORD array.
const hsize_t *coord[]; IN: The location of each element selected
@@ -388,31 +596,32 @@ H5S_point_iter_release (H5S_sel_iter_t H5_ATTR_UNUSED * iter)
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S_point_add(H5S_t *space, H5S_seloper_t op, size_t num_elem, const hsize_t *coord)
+H5S__point_add(H5S_t *space, H5S_seloper_t op, size_t num_elem, const hsize_t *coord)
{
H5S_pnt_node_t *top = NULL, *curr = NULL, *new_node = NULL; /* Point selection nodes */
unsigned u; /* Counter */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
+ /* Sanity checks */
HDassert(space);
HDassert(num_elem > 0);
HDassert(coord);
HDassert(op == H5S_SELECT_SET || op == H5S_SELECT_APPEND || op == H5S_SELECT_PREPEND);
for(u = 0; u < num_elem; u++) {
+ unsigned dim; /* Counter for dimensions */
+
/* Allocate space for the new node */
- if(NULL == (new_node = H5FL_MALLOC(H5S_pnt_node_t)))
+ if(NULL == (new_node = (H5S_pnt_node_t *)H5FL_ARR_MALLOC(hcoords_t, space->extent.rank)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate point node")
/* Initialize fields in node */
new_node->next = NULL;
- if(NULL == (new_node->pnt = (hsize_t *)H5MM_malloc(space->extent.rank * sizeof(hsize_t))))
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate coordinate information")
/* Copy over the coordinates */
- HDmemcpy(new_node->pnt, coord + (u * space->extent.rank), (space->extent.rank * sizeof(hsize_t)));
+ H5MM_memcpy(new_node->pnt, coord + (u * space->extent.rank), (space->extent.rank * sizeof(hsize_t)));
/* Link into list */
if(top == NULL)
@@ -420,6 +629,17 @@ H5S_point_add(H5S_t *space, H5S_seloper_t op, size_t num_elem, const hsize_t *co
else
curr->next = new_node;
curr = new_node;
+
+ /* Update bound box */
+ /* (Note: when op is H5S_SELECT_SET, the bound box has been reset
+ * inside H5S_select_elements, the only caller of this function.
+ * So the following bound box update procedure works correctly
+ * for the SET operation)
+ */
+ for(dim = 0; dim < space->extent.rank; dim++) {
+ space->select.sel_info.pnt_lst->low_bounds[dim] = MIN(space->select.sel_info.pnt_lst->low_bounds[dim], curr->pnt[dim]);
+ space->select.sel_info.pnt_lst->high_bounds[dim] = MAX(space->select.sel_info.pnt_lst->high_bounds[dim], curr->pnt[dim]);
+ } /* end for */
} /* end for */
new_node = NULL;
@@ -431,20 +651,22 @@ H5S_point_add(H5S_t *space, H5S_seloper_t op, size_t num_elem, const hsize_t *co
/* Put new list in point selection */
space->select.sel_info.pnt_lst->head = top;
+
+ /* Change the tail pointer if tail has not been set */
+ if(NULL == space->select.sel_info.pnt_lst->tail)
+ space->select.sel_info.pnt_lst->tail = curr;
} /* end if */
else { /* op==H5S_SELECT_APPEND */
H5S_pnt_node_t *tmp_node; /* Temporary point selection node */
tmp_node = space->select.sel_info.pnt_lst->head;
if(tmp_node != NULL) {
- while(tmp_node->next != NULL)
- tmp_node = tmp_node->next;
-
- /* Append new list to point selection */
- tmp_node->next = top;
+ HDassert(space->select.sel_info.pnt_lst->tail);
+ space->select.sel_info.pnt_lst->tail->next = top;
} /* end if */
else
space->select.sel_info.pnt_lst->head = top;
+ space->select.sel_info.pnt_lst->tail = curr;
} /* end else */
/* Set the number of elements in the new selection */
@@ -457,28 +679,27 @@ done:
if(ret_value < 0) {
/* Release possibly partially initialized new node */
if(new_node)
- new_node = H5FL_FREE(H5S_pnt_node_t, new_node);
+ new_node = (H5S_pnt_node_t *)H5FL_ARR_FREE(hcoords_t, new_node);
/* Release possible linked list of nodes */
while(top) {
- curr = top->next;
- H5MM_xfree(top->pnt);
- top = H5FL_FREE(H5S_pnt_node_t, top);
+ curr = top->next;
+ top = (H5S_pnt_node_t *)H5FL_ARR_FREE(hcoords_t, top);
top = curr;
} /* end while */
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_point_add() */
+} /* end H5S__point_add() */
+
-
/*--------------------------------------------------------------------------
NAME
- H5S_point_release
+ H5S__point_release
PURPOSE
Release point selection information for a dataspace
USAGE
- herr_t H5S_point_release(space)
+ herr_t H5S__point_release(space)
H5S_t *space; IN: Pointer to dataspace
RETURNS
Non-negative on success/Negative on failure
@@ -490,34 +711,26 @@ done:
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S_point_release (H5S_t *space)
+H5S__point_release(H5S_t *space)
{
- H5S_pnt_node_t *curr, *next; /* Point selection nodes */
-
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
/* Check args */
HDassert(space);
- /* Delete all the nodes from the list */
- curr = space->select.sel_info.pnt_lst->head;
- while(curr != NULL) {
- next = curr->next;
- H5MM_xfree(curr->pnt);
- curr = H5FL_FREE(H5S_pnt_node_t, curr);
- curr = next;
- } /* end while */
+ /* Free the point list */
+ H5S__free_pnt_list(space->select.sel_info.pnt_lst);
- /* Free & reset the point list header */
- space->select.sel_info.pnt_lst = H5FL_FREE(H5S_pnt_list_t, space->select.sel_info.pnt_lst);
+ /* Reset the point list header */
+ space->select.sel_info.pnt_lst = NULL;
/* Reset the number of elements in the selection */
space->select.num_elem = 0;
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5S_point_release() */
+} /* end H5S__point_release() */
+
-
/*--------------------------------------------------------------------------
NAME
H5S_select_elements
@@ -539,10 +752,7 @@ H5S_point_release (H5S_t *space)
array elements are iterated through when I/O is performed. Duplicate
coordinates are not checked for. The selection operator, OP, determines
how the new selection is to be combined with the existing selection for
- the dataspace. Currently, only H5S_SELECT_SET is supported, which replaces
- the existing selection with the one defined in this call. When operators
- other than H5S_SELECT_SET are used to combine a new selection with an
- existing selection, the selection ordering is reset to 'C' array ordering.
+ the dataspace.
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
EXAMPLES
@@ -552,9 +762,9 @@ herr_t
H5S_select_elements(H5S_t *space, H5S_seloper_t op, size_t num_elem,
const hsize_t *coord)
{
- herr_t ret_value = SUCCEED; /* return value */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_NOAPI(FAIL)
/* Check args */
HDassert(space);
@@ -568,12 +778,19 @@ H5S_select_elements(H5S_t *space, H5S_seloper_t op, size_t num_elem,
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release point selection")
/* Allocate space for the point selection information if necessary */
- if(H5S_GET_SELECT_TYPE(space) != H5S_SEL_POINTS || space->select.sel_info.pnt_lst == NULL)
+ if(H5S_GET_SELECT_TYPE(space) != H5S_SEL_POINTS || space->select.sel_info.pnt_lst == NULL) {
+ hsize_t tmp = HSIZET_MAX;
+
if(NULL == (space->select.sel_info.pnt_lst = H5FL_CALLOC(H5S_pnt_list_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate element information")
+ /* Set the bound box to the default value */
+ H5VM_array_fill(space->select.sel_info.pnt_lst->low_bounds, &tmp, sizeof(hsize_t), space->extent.rank);
+ HDmemset(space->select.sel_info.pnt_lst->high_bounds, 0, sizeof(hsize_t) * space->extent.rank);
+ } /* end if */
+
/* Add points to selection */
- if(H5S_point_add(space, op, num_elem, coord) < 0)
+ if(H5S__point_add(space, op, num_elem, coord) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert elements")
/* Set selection type */
@@ -581,61 +798,61 @@ H5S_select_elements(H5S_t *space, H5S_seloper_t op, size_t num_elem,
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_select_elements() */
+} /* end H5S_select_elements() */
+
-
/*--------------------------------------------------------------------------
NAME
- H5S_point_copy
+ H5S__copy_pnt_list
PURPOSE
- Copy a selection from one dataspace to another
+ Copy a point selection list
USAGE
- herr_t H5S_point_copy(dst, src)
- H5S_t *dst; OUT: Pointer to the destination dataspace
- H5S_t *src; IN: Pointer to the source dataspace
+ H5S_pnt_list_t *H5S__copy_pnt_list(src)
+ const H5S_pnt_list_t *src; IN: Pointer to the source point list
+ unsigned rank; IN: # of dimensions for points
RETURNS
- Non-negative on success/Negative on failure
+ Non-NULL pointer to new point list on success / NULL on failure
DESCRIPTION
- Copies all the point selection information from the source
- dataspace to the destination dataspace.
+ Copies point selection information from the source point list to newly
+ created point list.
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-static herr_t
-H5S_point_copy(H5S_t *dst, const H5S_t *src, hbool_t H5_ATTR_UNUSED share_selection)
+static H5S_pnt_list_t *
+H5S__copy_pnt_list(const H5S_pnt_list_t *src, unsigned rank)
{
- H5S_pnt_node_t *curr, *new_node, *new_tail; /* Point information nodes */
- herr_t ret_value = SUCCEED; /* Return value */
+ H5S_pnt_list_t *dst = NULL; /* New point list */
+ H5S_pnt_node_t *curr, *new_tail; /* Point information nodes */
+ H5S_pnt_list_t *ret_value = NULL; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
+ /* Sanity checks */
HDassert(src);
- HDassert(dst);
+ HDassert(rank > 0);
/* Allocate room for the head of the point list */
- if(NULL == (dst->select.sel_info.pnt_lst = H5FL_MALLOC(H5S_pnt_list_t)))
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate point list node")
+ if(NULL == (dst = H5FL_MALLOC(H5S_pnt_list_t)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, NULL, "can't allocate point list node")
- curr = src->select.sel_info.pnt_lst->head;
+ curr = src->head;
new_tail = NULL;
while(curr) {
+ H5S_pnt_node_t *new_node; /* New point information node */
+
/* Create new point */
- if(NULL == (new_node = H5FL_MALLOC(H5S_pnt_node_t)))
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate point node")
+ if(NULL == (new_node = (H5S_pnt_node_t *)H5FL_ARR_MALLOC(hcoords_t, rank)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, NULL, "can't allocate point node")
new_node->next = NULL;
- if(NULL == (new_node->pnt = (hsize_t *)H5MM_malloc(src->extent.rank * sizeof(hsize_t)))) {
- new_node = H5FL_FREE(H5S_pnt_node_t, new_node);
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate coordinate information")
- } /* end if */
/* Copy over the point's coordinates */
- HDmemcpy(new_node->pnt, curr->pnt, (src->extent.rank * sizeof(hsize_t)));
+ H5MM_memcpy(new_node->pnt, curr->pnt, (rank * sizeof(hsize_t)));
/* Keep the order the same when copying */
if(NULL == new_tail)
- new_tail = dst->select.sel_info.pnt_lst->head = new_node;
+ new_tail = dst->head = new_node;
else {
new_tail->next = new_node;
new_tail = new_node;
@@ -643,35 +860,114 @@ H5S_point_copy(H5S_t *dst, const H5S_t *src, hbool_t H5_ATTR_UNUSED share_select
curr = curr->next;
} /* end while */
+ dst->tail = new_tail;
+
+ /* Copy the selection bounds */
+ H5MM_memcpy(dst->high_bounds, src->high_bounds, (rank * sizeof(hsize_t)));
+ H5MM_memcpy(dst->low_bounds, src->low_bounds, (rank * sizeof(hsize_t)));
+
+ /* Set return value */
+ ret_value = dst;
done:
- if(ret_value < 0 && dst->select.sel_info.pnt_lst) {
- /* Traverse the (incomplete?) dst list, freeing all memory */
- curr = dst->select.sel_info.pnt_lst->head;
- while(curr) {
- H5S_pnt_node_t *tmp_node = curr;
-
- curr->pnt = (hsize_t *)H5MM_xfree(curr->pnt);
- curr = curr->next;
- tmp_node = H5FL_FREE(H5S_pnt_node_t, tmp_node);
- } /* end while */
+ if(NULL == ret_value && dst)
+ H5S__free_pnt_list(dst);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S__copy_pnt_list() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S__free_pnt_list
+ PURPOSE
+ Free a point selection list
+ USAGE
+ void H5S__free_pnt_list(pnt_lst)
+ H5S_pnt_list_t *pnt_lst; IN: Pointer to the point list to free
+ RETURNS
+ None
+ DESCRIPTION
+ Frees point selection information from the point list
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static void
+H5S__free_pnt_list(H5S_pnt_list_t *pnt_lst)
+{
+ H5S_pnt_node_t *curr; /* Point information nodes */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Sanity checks */
+ HDassert(pnt_lst);
+
+ /* Traverse the list, freeing all memory */
+ curr = pnt_lst->head;
+ while(curr) {
+ H5S_pnt_node_t *tmp_node = curr;
+
+ curr = curr->next;
+ tmp_node = (H5S_pnt_node_t *)H5FL_ARR_FREE(hcoords_t, tmp_node);
+ } /* end while */
+
+ H5FL_FREE(H5S_pnt_list_t, pnt_lst);
+
+ FUNC_LEAVE_NOAPI_VOID
+} /* end H5S__free_pnt_list() */
- dst->select.sel_info.pnt_lst = H5FL_FREE(H5S_pnt_list_t, dst->select.sel_info.pnt_lst);
- } /* end if */
+/*--------------------------------------------------------------------------
+ NAME
+ H5S__point_copy
+ PURPOSE
+ Copy a selection from one dataspace to another
+ USAGE
+ herr_t H5S__point_copy(dst, src, share_selection)
+ H5S_t *dst; OUT: Pointer to the destination dataspace
+ H5S_t *src; IN: Pointer to the source dataspace
+ hbool_t share_selection; IN: Whether to share the selection between the dataspaces
+ RETURNS
+ Non-negative on success/Negative on failure
+ DESCRIPTION
+ Copies all the point selection information from the source
+ dataspace to the destination dataspace.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static herr_t
+H5S__point_copy(H5S_t *dst, const H5S_t *src, hbool_t H5_ATTR_UNUSED share_selection)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity check */
+ HDassert(src);
+ HDassert(dst);
+
+ /* Allocate room for the head of the point list */
+ if(NULL == (dst->select.sel_info.pnt_lst = H5S__copy_pnt_list(src->select.sel_info.pnt_lst, src->extent.rank)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy point list")
+
+done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5S_point_copy() */
+} /* end H5S__point_copy() */
+
-
/*--------------------------------------------------------------------------
NAME
- H5S_point_is_valid
+ H5S__point_is_valid
PURPOSE
Check whether the selection fits within the extent, with the current
offset defined.
USAGE
- htri_t H5S_point_is_valid(space);
- H5S_t *space; IN: Dataspace pointer to query
+ htri_t H5S__point_is_valid(space);
+ const H5S_t *space; IN: Dataspace pointer to query
RETURNS
TRUE if the selection fits within the extent, FALSE if it does not and
Negative on an error.
@@ -684,36 +980,29 @@ done:
REVISION LOG
--------------------------------------------------------------------------*/
static htri_t
-H5S_point_is_valid (const H5S_t *space)
+H5S__point_is_valid(const H5S_t *space)
{
- H5S_pnt_node_t *curr; /* Point information nodes */
unsigned u; /* Counter */
htri_t ret_value = TRUE; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
HDassert(space);
- /* Check each point to determine whether selection+offset is within extent */
- curr = space->select.sel_info.pnt_lst->head;
- while(curr != NULL) {
- /* Check each dimension */
- for(u = 0; u < space->extent.rank; u++) {
- /* Check if an offset has been defined */
- /* Bounds check the selected point + offset against the extent */
- if(((curr->pnt[u] + (hsize_t)space->select.offset[u]) > space->extent.size[u])
- || (((hssize_t)curr->pnt[u] + space->select.offset[u]) < 0))
- HGOTO_DONE(FALSE)
- } /* end for */
-
- curr = curr->next;
- } /* end while */
+ /* Check each dimension */
+ for(u = 0; u < space->extent.rank; u++) {
+ /* Bounds check the selected point + offset against the extent */
+ if((space->select.sel_info.pnt_lst->high_bounds[u] + (hsize_t)space->select.offset[u]) > space->extent.size[u])
+ HGOTO_DONE(FALSE)
+ if(((hssize_t)space->select.sel_info.pnt_lst->low_bounds[u] + space->select.offset[u]) < 0)
+ HGOTO_DONE(FALSE)
+ } /* end for */
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5S_point_is_valid() */
+} /* end H5S__point_is_valid() */
+
-
/*--------------------------------------------------------------------------
NAME
H5Sget_select_elem_npoints
@@ -750,18 +1039,136 @@ H5Sget_select_elem_npoints(hid_t spaceid)
done:
FUNC_LEAVE_API(ret_value)
-} /* H5Sget_select_elem_npoints() */
+} /* end H5Sget_select_elem_npoints() */
+
-
/*--------------------------------------------------------------------------
NAME
- H5S_point_serial_size
+ H5S__point_get_version_enc_size
+ PURPOSE
+ Determine the version and the size (2, 4 or 8 bytes) to encode point selection info
+ USAGE
+ hssize_t H5S__point_set_enc_size(space, version, enc_size)
+ const H5S_t *space: IN: Dataspace ID of selection to query
+ uint32_t *version: OUT: The version to use for encoding
+ uint8_t *enc_size: OUT: The size to use for encoding
+ RETURNS
+ The version and the size to encode point selection info
+ DESCRIPTION
+ Determine the version to use for encoding points selection info based
+ on the following:
+ (1) the low/high bounds setting in fapl
+ (2) whether the number of points or selection high bounds exceeds H5S_UINT32_MAX or not
+
+ Determine the encoded size based on version:
+ --For version 2, the encoded size of point selection info is determined
+ by the maximum size for:
+ (a) storing the number of points
+ (b) storing the selection high bounds
+
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static herr_t
+H5S__point_get_version_enc_size(const H5S_t *space, uint32_t *version, uint8_t *enc_size)
+{
+ hbool_t count_up_version = FALSE; /* Whether number of points exceed H5S_UINT32_MAX */
+ hbool_t bound_up_version = FALSE; /* Whether high bounds exceed H5S_UINT32_MAX */
+ H5F_libver_t low_bound; /* The 'low' bound of library format versions */
+ H5F_libver_t high_bound; /* The 'high' bound of library format versions */
+ uint32_t tmp_version; /* Local temporary version */
+ hsize_t bounds_start[H5S_MAX_RANK]; /* Starting coordinate of bounding box */
+ hsize_t bounds_end[H5S_MAX_RANK]; /* Opposite coordinate of bounding box */
+ hsize_t max_size = 0; /* Maximum selection size */
+ unsigned u; /* Local index veriable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Get bounding box for the selection */
+ HDmemset(bounds_end, 0, sizeof(bounds_end));
+ if(H5S__point_bounds(space, bounds_start, bounds_end) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get selection bounds")
+
+ /* Determine whether number of points or high bounds exceeds (2^32 - 1) */
+ if(space->select.num_elem > H5S_UINT32_MAX)
+ count_up_version = TRUE;
+ else
+ for(u = 0; u < space->extent.rank; u++)
+ if(bounds_end[u] > H5S_UINT32_MAX) {
+ bound_up_version = TRUE;
+ break;
+ } /* end if */
+
+ /* If exceed (2^32 -1) */
+ if(count_up_version || bound_up_version)
+ tmp_version = H5S_POINT_VERSION_2;
+ else
+ tmp_version = H5S_POINT_VERSION_1;
+
+ /* Get the file's low/high bounds */
+ if(H5CX_get_libver_bounds(&low_bound, &high_bound) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get low/high bounds from API context")
+
+ /* Upgrade to the version indicated by the file's low bound if higher */
+ tmp_version = MAX(tmp_version, H5O_sds_point_ver_bounds[low_bound]);
+
+ /* Version bounds check */
+ if(tmp_version > H5O_sds_point_ver_bounds[high_bound]) {
+ if(count_up_version)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "The number of points in point selection exceeds 2^32")
+ else if(bound_up_version)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "The end of bounding box in point selection exceeds 2^32")
+ else
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "Dataspace point selection version out of bounds")
+ } /* end if */
+
+ /* Set the version to return */
+ *version = tmp_version;
+
+ /* Get the encoded size use based on version */
+ switch(tmp_version) {
+ case H5S_POINT_VERSION_1:
+ *enc_size = H5S_SELECT_INFO_ENC_SIZE_4;
+ break;
+
+ case H5S_POINT_VERSION_2:
+ /* Find max for num_elem and bounds_end[] */
+ max_size = space->select.num_elem;
+ for(u = 0; u < space->extent.rank; u++)
+ if(bounds_end[u] > max_size)
+ max_size = bounds_end[u];
+
+ /* Determine the encoding size */
+ if(max_size > H5S_UINT32_MAX)
+ *enc_size = H5S_SELECT_INFO_ENC_SIZE_8;
+ else if(max_size > H5S_UINT16_MAX)
+ *enc_size = H5S_SELECT_INFO_ENC_SIZE_4;
+ else
+ *enc_size = H5S_SELECT_INFO_ENC_SIZE_2;
+ break;
+
+ default:
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unknown point info size")
+ break;
+ } /* end switch */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5S__point_get_version_enc_size() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S__point_serial_size
PURPOSE
Determine the number of bytes needed to store the serialized point selection
information.
USAGE
- hssize_t H5S_point_serial_size(space)
- H5S_t *space; IN: Dataspace pointer to query
+ hssize_t H5S__point_serial_size(space)
+ const H5S_t *space; IN: Dataspace pointer to query
RETURNS
The number of bytes required on success, negative on an error.
DESCRIPTION
@@ -773,40 +1180,52 @@ done:
REVISION LOG
--------------------------------------------------------------------------*/
static hssize_t
-H5S_point_serial_size (const H5S_t *space)
+H5S__point_serial_size(const H5S_t *space)
{
- H5S_pnt_node_t *curr; /* Point information nodes */
+ uint32_t version; /* Version number */
+ uint8_t enc_size; /* Encoded size of point selection info */
hssize_t ret_value = -1; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC
HDassert(space);
- /* Basic number of bytes required to serialize point selection:
- * <type (4 bytes)> + <version (4 bytes)> + <padding (4 bytes)> +
- * <length (4 bytes)> + <rank (4 bytes)> + <# of points (4 bytes)> = 24 bytes
- */
- ret_value = 24;
+ /* Determine the version and encoded size for point selection */
+ if(H5S__point_get_version_enc_size(space, &version, &enc_size) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't determine hyper version")
+
+ /* Basic number of bytes required to serialize point selection: */
+ if(version >= H5S_POINT_VERSION_2)
+ /*
+ * <type (4 bytes)> + <version (4 bytes)> +
+ * <size of point info (1 byte)> + rank (4 bytes)>
+ */
+ ret_value=13;
+ else
+ /*
+ * <type (4 bytes)> + <version (4 bytes)> + <padding (4 bytes)> +
+ * <length (4 bytes)> + <rank (4 bytes)>
+ */
+ ret_value = 20;
+
+ /* <num points (depend on enc_size)> */
+ ret_value += enc_size;
/* Count points in selection */
- curr=space->select.sel_info.pnt_lst->head;
- while(curr!=NULL) {
- /* Add 4 bytes times the rank for each element selected */
- ret_value+=4*space->extent.rank;
- curr=curr->next;
- } /* end while */
+ ret_value += (hssize_t) (enc_size * space->extent.rank * space->select.num_elem);
+done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5S_point_serial_size() */
+} /* end H5S__point_serial_size() */
+
-
/*--------------------------------------------------------------------------
NAME
- H5S_point_serialize
+ H5S__point_serialize
PURPOSE
Serialize the current selection into a user-provided buffer.
USAGE
- herr_t H5S_point_serialize(space, p)
+ herr_t H5S__point_serialize(space, p)
const H5S_t *space; IN: Dataspace with selection to serialize
uint8_t **p; OUT: Pointer to buffer to put serialized
selection. Will be advanced to end of
@@ -822,70 +1241,126 @@ H5S_point_serial_size (const H5S_t *space)
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S_point_serialize (const H5S_t *space, uint8_t **p)
+H5S__point_serialize(const H5S_t *space, uint8_t **p)
{
H5S_pnt_node_t *curr; /* Point information nodes */
- uint8_t *pp = (*p); /* Local pointer for decoding */
- uint8_t *lenp; /* pointer to length location for later storage */
+ uint8_t *pp; /* Local pointer for decoding */
+ uint8_t *lenp = NULL; /* pointer to length location for later storage */
uint32_t len=0; /* number of bytes used */
unsigned u; /* local counting variable */
+ uint32_t version; /* Version number */
+ uint8_t enc_size; /* Encoded size of point selection info */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC
/* Check args */
HDassert(space);
HDassert(p);
+ pp = (*p);
HDassert(pp);
+ /* Determine the version and encoded size for point selection info */
+ if(H5S__point_get_version_enc_size(space, &version, &enc_size) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't determine hyper version")
+
/* Store the preamble information */
UINT32ENCODE(pp, (uint32_t)H5S_GET_SELECT_TYPE(space)); /* Store the type of selection */
- UINT32ENCODE(pp, (uint32_t)1); /* Store the version number */
- UINT32ENCODE(pp, (uint32_t)0); /* Store the un-used padding */
- lenp = pp; /* Keep the pointer to the length location for later */
- pp += 4; /* Skip over space for length */
+
+ UINT32ENCODE(pp, version); /* Store the version number */
+ if(version >= 2) {
+ *(pp)++ = enc_size; /* Store size of point info */
+ } else {
+ HDassert(version == H5S_POINT_VERSION_1);
+ UINT32ENCODE(pp, (uint32_t)0); /* Store the un-used padding */
+ lenp = pp; /* Keep the pointer to the length location for later */
+ pp += 4; /* Skip over space for length */
+ len += 8; /* Add in advance # of bytes for num of dimensions and num elements */
+ }
/* Encode number of dimensions */
UINT32ENCODE(pp, (uint32_t)space->extent.rank);
- len+=4;
- /* Encode number of elements */
- UINT32ENCODE(pp, (uint32_t)space->select.num_elem);
- len+=4;
+ switch(enc_size) {
+ case H5S_SELECT_INFO_ENC_SIZE_2:
+ HDassert(version == H5S_POINT_VERSION_2);
+
+ /* Encode number of elements */
+ UINT16ENCODE(pp, (uint16_t)space->select.num_elem);
+
+ /* Encode each point in selection */
+ curr=space->select.sel_info.pnt_lst->head;
+ while(curr!=NULL) {
+ /* Encode each point */
+ for(u=0; u<space->extent.rank; u++)
+ UINT16ENCODE(pp, (uint16_t)curr->pnt[u]);
+ curr=curr->next;
+ } /* end while */
+ break;
- /* Encode each point in selection */
- curr=space->select.sel_info.pnt_lst->head;
- while(curr!=NULL) {
- /* Add 4 bytes times the rank for each element selected */
- len+=4*space->extent.rank;
+ case H5S_SELECT_INFO_ENC_SIZE_4:
+ HDassert(version == H5S_POINT_VERSION_1 || version == H5S_POINT_VERSION_2);
- /* Encode each point */
- for(u=0; u<space->extent.rank; u++)
- UINT32ENCODE(pp, (uint32_t)curr->pnt[u]);
+ /* Encode number of elements */
+ UINT32ENCODE(pp, (uint32_t)space->select.num_elem);
- curr=curr->next;
- } /* end while */
+ /* Encode each point in selection */
+ curr=space->select.sel_info.pnt_lst->head;
+ while(curr!=NULL) {
+ /* Encode each point */
+ for(u=0; u<space->extent.rank; u++)
+ UINT32ENCODE(pp, (uint32_t)curr->pnt[u]);
+ curr=curr->next;
+ } /* end while */
- /* Encode length */
- UINT32ENCODE(lenp, (uint32_t)len); /* Store the length of the extra information */
+ /* Add 4 bytes times the rank for each element selected */
+ if(version == H5S_POINT_VERSION_1)
+ len += (uint32_t)space->select.num_elem * 4 * space->extent.rank;
+ break;
+
+ case H5S_SELECT_INFO_ENC_SIZE_8:
+ HDassert(version == H5S_POINT_VERSION_2);
+
+ /* Encode number of elements */
+ UINT64ENCODE(pp, space->select.num_elem);
+
+ /* Encode each point in selection */
+ curr=space->select.sel_info.pnt_lst->head;
+ while(curr!=NULL) {
+ /* Encode each point */
+ for(u=0; u<space->extent.rank; u++)
+ UINT64ENCODE(pp, curr->pnt[u]);
+ curr=curr->next;
+ } /* end while */
+ break;
+
+ default:
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unknown point info size")
+ break;
+
+ } /* end switch */
+
+ if(version == H5S_POINT_VERSION_1)
+ UINT32ENCODE(lenp, (uint32_t)len); /* Store the length of the extra information */
/* Update encoding pointer */
*p = pp;
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5S_point_serialize() */
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5S__point_serialize() */
+
+
-
/*--------------------------------------------------------------------------
NAME
- H5S_point_deserialize
+ H5S__point_deserialize
PURPOSE
Deserialize the current selection from a user-provided buffer.
USAGE
- herr_t H5S_point_deserialize(space, p)
- H5S_t *space; IN/OUT: Dataspace pointer to place
+ herr_t H5S__point_deserialize(space, p)
+ H5S_t **space; IN/OUT: Dataspace pointer to place
selection into
- uint32_t version IN: Selection version
- uint8_t flags IN: Selection flags
uint8 **p; OUT: Pointer to buffer holding serialized
selection. Will be advanced to end of
serialized selection.
@@ -900,28 +1375,85 @@ H5S_point_serialize (const H5S_t *space, uint8_t **p)
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S_point_deserialize(H5S_t *space, uint32_t H5_ATTR_UNUSED version, uint8_t H5_ATTR_UNUSED flags,
- const uint8_t **p)
+H5S__point_deserialize(H5S_t **space, const uint8_t **p)
{
- H5S_seloper_t op = H5S_SELECT_SET; /* Selection operation */
+ H5S_t *tmp_space = NULL; /* Pointer to actual dataspace to use,
+ either *space or a newly allocated one */
+ hsize_t dims[H5S_MAX_RANK]; /* Dimension sizes */
+ uint32_t version; /* Version number */
+ uint8_t enc_size = 0; /* Encoded size of selection info */
hsize_t *coord = NULL, *tcoord; /* Pointer to array of elements */
- const uint8_t *pp = (*p); /* Local pointer for decoding */
- size_t num_elem = 0; /* Number of elements in selection */
+ const uint8_t *pp; /* Local pointer for decoding */
+ uint64_t num_elem = 0; /* Number of elements in selection */
unsigned rank; /* Rank of points */
unsigned i, j; /* local counting variables */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
/* Check args */
- HDassert(space);
HDassert(p);
+ pp = (*p);
HDassert(pp);
- /* Deserialize points to select */
- /* (The header and rank have already beed decoded) */
- rank = space->extent.rank; /* Retrieve rank from space */
- UINT32DECODE(pp, num_elem); /* decode the number of points */
+ /* As part of the efforts to push all selection-type specific coding
+ to the callbacks, the coding for the allocation of a null dataspace
+ is moved from H5S_select_deserialize() in H5Sselect.c to here.
+ This is needed for decoding virtual layout in H5O__layout_decode() */
+ /* Allocate space if not provided */
+ if(!*space) {
+ if(NULL == (tmp_space = H5S_create(H5S_SIMPLE)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't create dataspace")
+ } /* end if */
+ else
+ tmp_space = *space;
+
+ /* Decode version */
+ UINT32DECODE(pp, version);
+
+ if(version >= (uint32_t)H5S_POINT_VERSION_2)
+ /* Decode size of point info */
+ enc_size = *(pp)++;
+ else {
+ /* Skip over the remainder of the header */
+ pp += 8;
+ enc_size = H5S_SELECT_INFO_ENC_SIZE_4;
+ }
+
+ /* Check encoded size */
+ if(enc_size & ~H5S_SELECT_INFO_ENC_SIZE_BITS)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTLOAD, FAIL, "unknown size of point/offset info for selection")
+
+ /* Decode the rank of the point selection */
+ UINT32DECODE(pp,rank);
+
+ if(!*space) {
+ /* Patch the rank of the allocated dataspace */
+ (void)HDmemset(dims, 0, (size_t)rank * sizeof(dims[0]));
+ if(H5S_set_extent_simple(tmp_space, rank, dims, NULL) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't set dimensions")
+ } /* end if */
+ else
+ /* Verify the rank of the provided dataspace */
+ if(rank != tmp_space->extent.rank)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "rank of serialized selection does not match dataspace")
+
+ /* decode the number of points */
+ switch(enc_size) {
+ case H5S_SELECT_INFO_ENC_SIZE_2:
+ UINT16DECODE(pp, num_elem);
+ break;
+ case H5S_SELECT_INFO_ENC_SIZE_4:
+ UINT32DECODE(pp, num_elem);
+ break;
+ case H5S_SELECT_INFO_ENC_SIZE_8:
+ UINT64DECODE(pp, num_elem);
+ break;
+ default:
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unknown point info size")
+ break;
+ } /* end switch */
+
/* Allocate space for the coordinates */
if(NULL == (coord = (hsize_t *)H5MM_malloc(num_elem * rank * sizeof(hsize_t))))
@@ -930,32 +1462,56 @@ H5S_point_deserialize(H5S_t *space, uint32_t H5_ATTR_UNUSED version, uint8_t H5_
/* Retrieve the coordinates from the buffer */
for(tcoord = coord, i = 0; i < num_elem; i++)
for(j = 0; j < (unsigned)rank; j++, tcoord++)
- UINT32DECODE(pp, *tcoord);
+ switch(enc_size) {
+ case H5S_SELECT_INFO_ENC_SIZE_2:
+ UINT16DECODE(pp, *tcoord);
+ break;
+
+ case H5S_SELECT_INFO_ENC_SIZE_4:
+ UINT32DECODE(pp, *tcoord);
+ break;
+
+ case H5S_SELECT_INFO_ENC_SIZE_8:
+ UINT64DECODE(pp, *tcoord);
+ break;
+ default:
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unknown point info size")
+ break;
+ } /* end switch */
/* Select points */
- if(H5S_select_elements(space, op, num_elem, (const hsize_t *)coord) < 0)
+ if(H5S_select_elements(tmp_space, H5S_SELECT_SET, num_elem, (const hsize_t *)coord) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection")
/* Update decoding pointer */
*p = pp;
+ /* Return space to the caller if allocated */
+ if(!*space)
+ *space = tmp_space;
+
done:
+ /* Free temporary space if not passed to caller (only happens on error) */
+ if(!*space && tmp_space)
+ if(H5S_close(tmp_space) < 0)
+ HDONE_ERROR(H5E_DATASPACE, H5E_CANTFREE, FAIL, "can't close dataspace")
+
/* Free the coordinate array if necessary */
if(coord != NULL)
H5MM_xfree(coord);
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_point_deserialize() */
+} /* end H5S__point_deserialize() */
+
-
/*--------------------------------------------------------------------------
NAME
- H5S_get_select_elem_pointlist
+ H5S__get_select_elem_pointlist
PURPOSE
Get the list of element points currently selected
USAGE
- herr_t H5S_get_select_elem_pointlist(space, hsize_t *buf)
- H5S_t *space; IN: Dataspace pointer of selection to query
+ herr_t H5S__get_select_elem_pointlist(space, hsize_t *buf)
+ const H5S_t *space; IN: Dataspace pointer of selection to query
hsize_t startpoint; IN: Element point to start with
hsize_t numpoints; IN: Number of element points to get
hsize_t *buf; OUT: List of element points selected
@@ -978,12 +1534,13 @@ done:
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S_get_select_elem_pointlist(H5S_t *space, hsize_t startpoint, hsize_t numpoints, hsize_t *buf)
+H5S__get_select_elem_pointlist(const H5S_t *space, hsize_t startpoint,
+ hsize_t numpoints, hsize_t *buf)
{
H5S_pnt_node_t *node; /* Point node */
unsigned rank; /* Dataspace rank */
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
HDassert(space);
HDassert(buf);
@@ -1002,16 +1559,16 @@ H5S_get_select_elem_pointlist(H5S_t *space, hsize_t startpoint, hsize_t numpoint
/* Iterate through the node, copying each point's information */
while(node != NULL && numpoints > 0) {
- HDmemcpy(buf, node->pnt, sizeof(hsize_t) * rank);
+ H5MM_memcpy(buf, node->pnt, sizeof(hsize_t) * rank);
buf += rank;
numpoints--;
node = node->next;
} /* end while */
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5S_get_select_elem_pointlist() */
+} /* end H5S__get_select_elem_pointlist() */
+
-
/*--------------------------------------------------------------------------
NAME
H5Sget_select_elem_pointlist
@@ -1059,20 +1616,20 @@ H5Sget_select_elem_pointlist(hid_t spaceid, hsize_t startpoint,
if(H5S_GET_SELECT_TYPE(space) != H5S_SEL_POINTS)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a point selection")
- ret_value = H5S_get_select_elem_pointlist(space, startpoint, numpoints, buf);
+ ret_value = H5S__get_select_elem_pointlist(space, startpoint, numpoints, buf);
done:
FUNC_LEAVE_API(ret_value)
-} /* H5Sget_select_elem_pointlist() */
+} /* end H5Sget_select_elem_pointlist() */
+
-
/*--------------------------------------------------------------------------
NAME
- H5S_point_bounds
+ H5S__point_bounds
PURPOSE
Gets the bounding box containing the selection.
USAGE
- herr_t H5S_point_bounds(space, start, end)
+ herr_t H5S__point_bounds(space, start, end)
H5S_t *space; IN: Dataspace pointer of selection to query
hsize_t *start; OUT: Starting coordinate of bounding box
hsize_t *end; OUT: Opposite coordinate of bounding box
@@ -1093,57 +1650,44 @@ done:
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S_point_bounds(const H5S_t *space, hsize_t *start, hsize_t *end)
+H5S__point_bounds(const H5S_t *space, hsize_t *start, hsize_t *end)
{
- H5S_pnt_node_t *node; /* Point node */
- unsigned rank; /* Dataspace rank */
unsigned u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
/* Sanity check */
HDassert(space);
HDassert(start);
HDassert(end);
- /* Get the dataspace extent rank */
- rank = space->extent.rank;
-
- /* Set the start and end arrays up */
- for(u = 0; u < rank; u++) {
- start[u] = HSIZET_MAX;
- end[u] = 0;
- } /* end for */
+ /* Loop over dimensions */
+ for(u = 0; u < space->extent.rank; u++) {
+ /* Sanity check */
+ HDassert(space->select.sel_info.pnt_lst->low_bounds[u] <= space->select.sel_info.pnt_lst->high_bounds[u]);
- /* Iterate through the node, checking the bounds on each element */
- node = space->select.sel_info.pnt_lst->head;
- while(node != NULL) {
- for(u = 0; u < rank; u++) {
- /* Check for offset moving selection negative */
- if(((hssize_t)node->pnt[u] + space->select.offset[u]) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "offset moves selection out of bounds")
+ /* Check for offset moving selection negative */
+ if(((hssize_t)space->select.sel_info.pnt_lst->low_bounds[u] + space->select.offset[u]) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "offset moves selection out of bounds")
- if(start[u] > (hsize_t)((hssize_t)node->pnt[u] + space->select.offset[u]))
- start[u] = (hsize_t)((hssize_t)node->pnt[u] + space->select.offset[u]);
- if(end[u] < (hsize_t)((hssize_t)node->pnt[u] + space->select.offset[u]))
- end[u] = (hsize_t)((hssize_t)node->pnt[u] + space->select.offset[u]);
- } /* end for */
- node = node->next;
- } /* end while */
+ /* Set the low & high bounds in this dimension */
+ start[u] = (hsize_t)((hssize_t)space->select.sel_info.pnt_lst->low_bounds[u] + space->select.offset[u]);
+ end[u] = (hsize_t)((hssize_t)space->select.sel_info.pnt_lst->high_bounds[u] + space->select.offset[u]);
+ } /* end for */
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_point_bounds() */
+} /* end H5S__point_bounds() */
+
-
/*--------------------------------------------------------------------------
NAME
- H5S_point_offset
+ H5S__point_offset
PURPOSE
Gets the linear offset of the first element for the selection.
USAGE
- herr_t H5S_point_offset(space, offset)
+ herr_t H5S__point_offset(space, offset)
const H5S_t *space; IN: Dataspace pointer of selection to query
hsize_t *offset; OUT: Linear offset of first element in selection
RETURNS
@@ -1158,7 +1702,7 @@ done:
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S_point_offset(const H5S_t *space, hsize_t *offset)
+H5S__point_offset(const H5S_t *space, hsize_t *offset)
{
const hsize_t *pnt; /* Pointer to a selected point's coordinates */
const hssize_t *sel_offset; /* Pointer to the selection's offset */
@@ -1167,7 +1711,7 @@ H5S_point_offset(const H5S_t *space, hsize_t *offset)
int i; /* index variable */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(FAIL)
+ FUNC_ENTER_STATIC
HDassert(space);
HDassert(offset);
@@ -1198,9 +1742,9 @@ H5S_point_offset(const H5S_t *space, hsize_t *offset)
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_point_offset() */
+} /* end H5S__point_offset() */
+
-
/*--------------------------------------------------------------------------
NAME
H5S__point_unlim_dim
@@ -1229,14 +1773,14 @@ H5S__point_unlim_dim(const H5S_t H5_ATTR_UNUSED *space)
FUNC_LEAVE_NOAPI(-1)
} /* end H5S__point_unlim_dim() */
-
+
/*--------------------------------------------------------------------------
NAME
- H5S_point_is_contiguous
+ H5S__point_is_contiguous
PURPOSE
Check if a point selection is contiguous within the dataspace extent.
USAGE
- htri_t H5S_point_is_contiguous(space)
+ htri_t H5S__point_is_contiguous(space)
H5S_t *space; IN: Dataspace pointer to check
RETURNS
TRUE/FALSE/FAIL
@@ -1252,31 +1796,31 @@ H5S__point_unlim_dim(const H5S_t H5_ATTR_UNUSED *space)
REVISION LOG
--------------------------------------------------------------------------*/
static htri_t
-H5S_point_is_contiguous(const H5S_t *space)
+H5S__point_is_contiguous(const H5S_t *space)
{
htri_t ret_value = FAIL; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
HDassert(space);
/* One point is definitely contiguous */
- if(space->select.num_elem==1)
- ret_value=TRUE;
- else /* More than one point might be contiguous, but it's complex to check and we don't need it right now */
- ret_value=FALSE;
+ if(space->select.num_elem == 1)
+ ret_value = TRUE;
+ else /* More than one point might be contiguous, but it's complex to check and we don't need it right now */
+ ret_value = FALSE;
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_point_is_contiguous() */
+} /* end H5S__point_is_contiguous() */
+
-
/*--------------------------------------------------------------------------
NAME
- H5S_point_is_single
+ H5S__point_is_single
PURPOSE
Check if a point selection is single within the dataspace extent.
USAGE
- htri_t H5S_point_is_single(space)
+ htri_t H5S__point_is_single(space)
H5S_t *space; IN: Dataspace pointer to check
RETURNS
TRUE/FALSE/FAIL
@@ -1289,31 +1833,31 @@ H5S_point_is_contiguous(const H5S_t *space)
REVISION LOG
--------------------------------------------------------------------------*/
static htri_t
-H5S_point_is_single(const H5S_t *space)
+H5S__point_is_single(const H5S_t *space)
{
htri_t ret_value = FAIL; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
HDassert(space);
/* One point is definitely 'single' :-) */
- if(space->select.num_elem==1)
- ret_value=TRUE;
+ if(space->select.num_elem == 1)
+ ret_value = TRUE;
else
- ret_value=FALSE;
+ ret_value = FALSE;
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_point_is_single() */
+} /* end H5S__point_is_single() */
+
-
/*--------------------------------------------------------------------------
NAME
- H5S_point_is_regular
+ H5S__point_is_regular
PURPOSE
Check if a point selection is "regular"
USAGE
- htri_t H5S_point_is_regular(space)
+ htri_t H5S__point_is_regular(space)
const H5S_t *space; IN: Dataspace pointer to check
RETURNS
TRUE/FALSE/FAIL
@@ -1329,32 +1873,197 @@ H5S_point_is_single(const H5S_t *space)
REVISION LOG
--------------------------------------------------------------------------*/
static htri_t
-H5S_point_is_regular(const H5S_t *space)
+H5S__point_is_regular(const H5S_t *space)
{
htri_t ret_value = FAIL; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
/* Check args */
HDassert(space);
/* Only simple check for regular points for now... */
- if(space->select.num_elem==1)
- ret_value=TRUE;
+ if(space->select.num_elem == 1)
+ ret_value = TRUE;
else
- ret_value=FALSE;
+ ret_value = FALSE;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S__point_is_regular() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S__point_shape_same
+ PURPOSE
+ Check if a two "point" selections are the same shape
+ USAGE
+ htri_t H5S__point_shape_same(space1, space2)
+ const H5S_t *space1; IN: First dataspace to check
+ const H5S_t *space2; IN: Second dataspace to check
+ RETURNS
+ TRUE / FALSE / FAIL
+ DESCRIPTION
+ Checks to see if the current selection in each dataspace are the same
+ shape.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static htri_t
+H5S__point_shape_same(const H5S_t *space1, const H5S_t *space2)
+{
+ H5S_pnt_node_t *pnt1, *pnt2; /* Point information nodes */
+ hssize_t offset[H5S_MAX_RANK]; /* Offset between the selections */
+ unsigned space1_rank; /* Number of dimensions of first dataspace */
+ unsigned space2_rank; /* Number of dimensions of second dataspace */
+ int space1_dim; /* Current dimension in first dataspace */
+ int space2_dim; /* Current dimension in second dataspace */
+ htri_t ret_value = TRUE; /* Return value */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Check args */
+ HDassert(space1);
+ HDassert(space2);
+
+ /* Get dataspace ranks */
+ space1_rank = space1->extent.rank;
+ space2_rank = space2->extent.rank;
+
+ /* Sanity check */
+ HDassert(space1_rank >= space2_rank);
+ HDassert(space2_rank > 0);
+
+ /* Initialize dimensions */
+ space1_dim = (int)space1_rank - 1;
+ space2_dim = (int)space2_rank - 1;
+
+ /* Look at first point in each selection to compute the offset for common
+ * dimensions.
+ */
+ pnt1 = space1->select.sel_info.pnt_lst->head;
+ pnt2 = space2->select.sel_info.pnt_lst->head;
+ while(space2_dim >= 0) {
+ /* Set the relative locations of the selections */
+ offset[space1_dim] = (hssize_t)pnt2->pnt[space2_dim] - (hssize_t)pnt1->pnt[space1_dim];
+
+ space1_dim--;
+ space2_dim--;
+ } /* end while */
+
+ /* For dimensions that appear only in space1: */
+ while(space1_dim >= 0) {
+ /* Set the absolute offset of the remaining dimensions */
+ offset[space1_dim] = (hssize_t)pnt1->pnt[space1_dim];
+
+ space1_dim--;
+ } /* end while */
+
+ /* Advance to next point */
+ pnt1 = pnt1->next;
+ pnt2 = pnt2->next;
+
+ /* Loop over remaining points */
+ while(pnt1 && pnt2) {
+ /* Initialize dimensions */
+ space1_dim = (int)space1_rank - 1;
+ space2_dim = (int)space2_rank - 1;
+
+ /* Compare locations in common dimensions, including relative offset */
+ while(space2_dim >= 0) {
+ if((hsize_t)((hssize_t)pnt1->pnt[space1_dim] + offset[space1_dim]) != pnt2->pnt[space2_dim])
+ HGOTO_DONE(FALSE)
+
+ space1_dim--;
+ space2_dim--;
+ } /* end while */
+
+ /* For dimensions that appear only in space1: */
+ while(space1_dim >= 0) {
+ /* Compare the absolute offset in the remaining dimensions */
+ if((hssize_t)pnt1->pnt[space1_dim] != offset[space1_dim])
+ HGOTO_DONE(FALSE)
+
+ space1_dim--;
+ } /* end while */
+
+
+ /* Advance to next point */
+ pnt1 = pnt1->next;
+ pnt2 = pnt2->next;
+ } /* end while */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S__point_shape_same() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S__point_intersect_block
+ PURPOSE
+ Detect intersections of selection with block
+ USAGE
+ htri_t H5S__point_intersect_block(space, start, end)
+ const H5S_t *space; IN: Dataspace with selection to use
+ const hsize_t *start; IN: Starting coordinate for block
+ const hsize_t *end; IN: Ending coordinate for block
+ RETURNS
+ Non-negative TRUE / FALSE on success, negative on failure
+ DESCRIPTION
+ Quickly detect intersections with a block
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+htri_t
+H5S__point_intersect_block(const H5S_t *space, const hsize_t *start,
+ const hsize_t *end)
+{
+ H5S_pnt_node_t *pnt; /* Point information node */
+ htri_t ret_value = FALSE; /* Return value */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Sanity check */
+ HDassert(space);
+ HDassert(H5S_SEL_POINTS == H5S_GET_SELECT_TYPE(space));
+ HDassert(start);
+ HDassert(end);
+
+ /* Loop over points */
+ pnt = space->select.sel_info.pnt_lst->head;
+ while(pnt) {
+ unsigned u; /* Local index variable */
+ /* Verify that the point is within the block */
+ for(u = 0; u < space->extent.rank; u++)
+ if(pnt->pnt[u] < start[u] || pnt->pnt[u] > end[u])
+ break;
+
+ /* Check if point was within block for all dimensions */
+ if(u == space->extent.rank)
+ HGOTO_DONE(TRUE)
+
+ /* Advance to next point */
+ pnt = pnt->next;
+ } /* end while */
+
+done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_point_is_regular() */
+} /* end H5S__point_intersect_block() */
+
-
/*--------------------------------------------------------------------------
NAME
- H5S_point_adjust_u
+ H5S__point_adjust_u
PURPOSE
Adjust a "point" selection by subtracting an offset
USAGE
- herr_t H5S_point_adjust_u(space, offset)
+ herr_t H5S__point_adjust_u(space, offset)
H5S_t *space; IN/OUT: Pointer to dataspace to adjust
const hsize_t *offset; IN: Offset to subtract
RETURNS
@@ -1367,12 +2076,13 @@ H5S_point_is_regular(const H5S_t *space)
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S_point_adjust_u(H5S_t *space, const hsize_t *offset)
+H5S__point_adjust_u(H5S_t *space, const hsize_t *offset)
{
H5S_pnt_node_t *node; /* Point node */
unsigned rank; /* Dataspace rank */
+ unsigned u; /* Local index variable */
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
HDassert(space);
HDassert(offset);
@@ -1381,8 +2091,6 @@ H5S_point_adjust_u(H5S_t *space, const hsize_t *offset)
node = space->select.sel_info.pnt_lst->head;
rank = space->extent.rank;
while(node) {
- unsigned u; /* Local index variable */
-
/* Adjust each coordinate for point node */
for(u = 0; u < rank; u++) {
/* Check for offset moving selection negative */
@@ -1396,30 +2104,36 @@ H5S_point_adjust_u(H5S_t *space, const hsize_t *offset)
node = node->next;
} /* end while */
+ /* update the bound box of the selection */
+ for(u = 0; u < rank; u++) {
+ space->select.sel_info.pnt_lst->low_bounds[u] -= offset[u];
+ space->select.sel_info.pnt_lst->high_bounds[u] -= offset[u];
+ } /* end for */
+
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5S_point_adjust_u() */
+} /* end H5S__point_adjust_u() */
+
-
/*-------------------------------------------------------------------------
- * Function: H5S_point_project_scalar
+ * Function: H5S__point_project_scalar
*
- * Purpose: Projects a single element point selection into a scalar
+ * Purpose: Projects a single element point selection into a scalar
* dataspace
*
- * Return: non-negative on success, negative on failure.
+ * Return: Non-negative on success, negative on failure.
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* Sunday, July 18, 2010
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5S_point_project_scalar(const H5S_t *space, hsize_t *offset)
+H5S__point_project_scalar(const H5S_t *space, hsize_t *offset)
{
const H5S_pnt_node_t *node; /* Point node */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
/* Check args */
HDassert(space && H5S_SEL_POINTS == H5S_GET_SELECT_TYPE(space));
@@ -1433,36 +2147,37 @@ H5S_point_project_scalar(const H5S_t *space, hsize_t *offset)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "point selection of one element has more than one node!")
/* Calculate offset of selection in projected buffer */
- *offset = H5VM_array_offset(space->extent.rank, space->extent.size, node->pnt);
+ *offset = H5VM_array_offset(space->extent.rank, space->extent.size, node->pnt);
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_point_project_scalar() */
+} /* end H5S__point_project_scalar() */
+
-
/*-------------------------------------------------------------------------
- * Function: H5S_point_project_simple
+ * Function: H5S__point_project_simple
*
- * Purpose: Projects a point selection onto/into a simple dataspace
+ * Purpose: Projects a point selection onto/into a simple dataspace
* of a different rank
*
- * Return: non-negative on success, negative on failure.
+ * Return: Non-negative on success, negative on failure.
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* Sunday, July 18, 2010
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5S_point_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *offset)
+H5S__point_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *offset)
{
const H5S_pnt_node_t *base_node; /* Point node in base space */
H5S_pnt_node_t *new_node; /* Point node in new space */
H5S_pnt_node_t *prev_node; /* Previous point node in new space */
unsigned rank_diff; /* Difference in ranks between spaces */
+ unsigned u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
/* Check args */
HDassert(base_space && H5S_SEL_POINTS == H5S_GET_SELECT_TYPE(base_space));
@@ -1486,24 +2201,20 @@ H5S_point_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *off
/* Calculate offset of selection in projected buffer */
HDmemset(block, 0, sizeof(block));
- HDmemcpy(block, base_space->select.sel_info.pnt_lst->head->pnt, sizeof(hsize_t) * rank_diff);
- *offset = H5VM_array_offset(base_space->extent.rank, base_space->extent.size, block);
+ H5MM_memcpy(block, base_space->select.sel_info.pnt_lst->head->pnt, sizeof(hsize_t) * rank_diff);
+ *offset = H5VM_array_offset(base_space->extent.rank, base_space->extent.size, block);
/* Iterate through base space's point nodes, copying the point information */
base_node = base_space->select.sel_info.pnt_lst->head;
prev_node = NULL;
while(base_node) {
/* Create new point */
- if(NULL == (new_node = H5FL_MALLOC(H5S_pnt_node_t)))
+ if(NULL == (new_node = (H5S_pnt_node_t *)H5FL_ARR_MALLOC(hcoords_t, new_space->extent.rank)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate point node")
new_node->next = NULL;
- if(NULL == (new_node->pnt = (hsize_t *)H5MM_malloc(new_space->extent.rank * sizeof(hsize_t)))) {
- new_node = H5FL_FREE(H5S_pnt_node_t, new_node);
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate coordinate information")
- } /* end if */
/* Copy over the point's coordinates */
- HDmemcpy(new_node->pnt, &base_node->pnt[rank_diff], (new_space->extent.rank * sizeof(hsize_t)));
+ H5MM_memcpy(new_node->pnt, &base_node->pnt[rank_diff], (new_space->extent.rank * sizeof(hsize_t)));
/* Keep the order the same when copying */
if(NULL == prev_node)
@@ -1516,6 +2227,12 @@ H5S_point_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *off
/* Advance to next node */
base_node = base_node->next;
} /* end while */
+
+ /* Update the bounding box */
+ for(u = 0; u < new_space->extent.rank; u++) {
+ new_space->select.sel_info.pnt_lst->low_bounds[u] = base_space->select.sel_info.pnt_lst->low_bounds[u + rank_diff];
+ new_space->select.sel_info.pnt_lst->high_bounds[u] = base_space->select.sel_info.pnt_lst->high_bounds[u + rank_diff];
+ } /* end for */
} /* end if */
else {
HDassert(new_space->extent.rank > base_space->extent.rank);
@@ -1531,17 +2248,13 @@ H5S_point_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *off
prev_node = NULL;
while(base_node) {
/* Create new point */
- if(NULL == (new_node = H5FL_MALLOC(H5S_pnt_node_t)))
+ if(NULL == (new_node = (H5S_pnt_node_t *)H5FL_ARR_MALLOC(hcoords_t, new_space->extent.rank)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate point node")
new_node->next = NULL;
- if(NULL == (new_node->pnt = (hsize_t *)H5MM_malloc(new_space->extent.rank * sizeof(hsize_t)))) {
- new_node = H5FL_FREE(H5S_pnt_node_t, new_node);
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate coordinate information")
- } /* end if */
/* Copy over the point's coordinates */
HDmemset(new_node->pnt, 0, sizeof(hsize_t) * rank_diff);
- HDmemcpy(&new_node->pnt[rank_diff], base_node->pnt, (new_space->extent.rank * sizeof(hsize_t)));
+ H5MM_memcpy(&new_node->pnt[rank_diff], base_node->pnt, (new_space->extent.rank * sizeof(hsize_t)));
/* Keep the order the same when copying */
if(NULL == prev_node)
@@ -1554,6 +2267,16 @@ H5S_point_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *off
/* Advance to next node */
base_node = base_node->next;
} /* end while */
+
+ /* Update the bounding box */
+ for(u = 0; u < rank_diff; u++) {
+ new_space->select.sel_info.pnt_lst->low_bounds[u] = 0;
+ new_space->select.sel_info.pnt_lst->high_bounds[u] = 0;
+ } /* end for */
+ for(; u < new_space->extent.rank; u++) {
+ new_space->select.sel_info.pnt_lst->low_bounds[u] = base_space->select.sel_info.pnt_lst->low_bounds[u - rank_diff];
+ new_space->select.sel_info.pnt_lst->high_bounds[u] = base_space->select.sel_info.pnt_lst->high_bounds[u - rank_diff];
+ } /* end for */
} /* end else */
/* Number of elements selected will be the same */
@@ -1564,9 +2287,9 @@ H5S_point_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *off
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_point_project_simple() */
+} /* end H5S__point_project_simple() */
+
-
/*--------------------------------------------------------------------------
NAME
H5Sselect_elements
@@ -1625,143 +2348,5 @@ H5Sselect_elements(hid_t spaceid, H5S_seloper_t op, size_t num_elem,
done:
FUNC_LEAVE_API(ret_value)
-} /* H5Sselect_elements() */
-
-
-/*--------------------------------------------------------------------------
- NAME
- H5S_point_get_seq_list
- PURPOSE
- Create a list of offsets & lengths for a selection
- USAGE
- herr_t H5S_point_get_seq_list(space,flags,iter,maxseq,maxelem,nseq,nelem,off,len)
- H5S_t *space; IN: Dataspace containing selection to use.
- unsigned flags; IN: Flags for extra information about operation
- H5S_sel_iter_t *iter; IN/OUT: Selection iterator describing last
- position of interest in selection.
- size_t maxseq; IN: Maximum number of sequences to generate
- size_t maxelem; IN: Maximum number of elements to include in the
- generated sequences
- size_t *nseq; OUT: Actual number of sequences generated
- size_t *nelem; OUT: Actual number of elements in sequences generated
- hsize_t *off; OUT: Array of offsets
- size_t *len; OUT: Array of lengths
- RETURNS
- Non-negative on success/Negative on failure.
- DESCRIPTION
- Use the selection in the dataspace to generate a list of byte offsets and
- lengths for the region(s) selected. Start/Restart from the position in the
- ITER parameter. The number of sequences generated is limited by the MAXSEQ
- parameter and the number of sequences actually generated is stored in the
- NSEQ parameter.
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
-static herr_t
-H5S_point_get_seq_list(const H5S_t *space, unsigned flags, H5S_sel_iter_t *iter,
- size_t maxseq, size_t maxelem, size_t *nseq, size_t *nelem,
- hsize_t *off, size_t *len)
-{
- size_t io_left; /* The number of bytes left in the selection */
- size_t start_io_left; /* The initial number of bytes left in the selection */
- H5S_pnt_node_t *node; /* Point node */
- hsize_t dims[H5O_LAYOUT_NDIMS]; /* Total size of memory buf */
- int ndims; /* Dimensionality of space*/
- hsize_t acc; /* Coordinate accumulator */
- hsize_t loc; /* Coordinate offset */
- size_t curr_seq; /* Current sequence being operated on */
- int i; /* Local index variable */
- herr_t ret_value=SUCCEED; /* return value */
-
- FUNC_ENTER_NOAPI_NOINIT
-
- /* Check args */
- HDassert(space);
- HDassert(iter);
- HDassert(maxseq > 0);
- HDassert(maxelem > 0);
- HDassert(nseq);
- HDassert(nelem);
- HDassert(off);
- HDassert(len);
-
- /* Choose the minimum number of bytes to sequence through */
- H5_CHECK_OVERFLOW(iter->elmt_left, hsize_t, size_t);
- start_io_left = io_left = (size_t)MIN(iter->elmt_left, maxelem);
-
- /* Get the dataspace dimensions */
- if((ndims = H5S_get_simple_extent_dims (space, dims, NULL)) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to retrieve dataspace dimensions")
-
- /* Walk through the points in the selection, starting at the current */
- /* location in the iterator */
- node = iter->u.pnt.curr;
- curr_seq = 0;
- while(NULL != node) {
- /* Compute the offset of each selected point in the buffer */
- for(i = ndims - 1, acc = iter->elmt_size, loc = 0; i >= 0; i--) {
- loc += (hsize_t)((hssize_t)node->pnt[i] + space->select.offset[i]) * acc;
- acc *= dims[i];
- } /* end for */
-
- /* Check if this is a later point in the selection */
- if(curr_seq>0) {
- /* If a sorted sequence is requested, make certain we don't go backwards in the offset */
- if((flags&H5S_GET_SEQ_LIST_SORTED) && loc<off[curr_seq-1])
- break;
-
- /* Check if this point extends the previous sequence */
- /* (Unlikely, but possible) */
- if(loc==(off[curr_seq-1]+len[curr_seq-1])) {
- /* Extend the previous sequence */
- len[curr_seq-1]+=iter->elmt_size;
- } /* end if */
- else {
- /* Add a new sequence */
- off[curr_seq]=loc;
- len[curr_seq]=iter->elmt_size;
-
- /* Increment sequence count */
- curr_seq++;
- } /* end else */
- } /* end if */
- else {
- /* Add a new sequence */
- off[curr_seq]=loc;
- len[curr_seq]=iter->elmt_size;
-
- /* Increment sequence count */
- curr_seq++;
- } /* end else */
-
- /* Decrement number of elements left to process */
- io_left--;
-
- /* Move the iterator */
- iter->u.pnt.curr=node->next;
- iter->elmt_left--;
-
- /* Check if we're finished with all sequences */
- if(curr_seq==maxseq)
- break;
-
- /* Check if we're finished with all the elements available */
- if(io_left==0)
- break;
-
- /* Advance to the next point */
- node=node->next;
- } /* end while */
-
- /* Set the number of sequences generated */
- *nseq=curr_seq;
-
- /* Set the number of elements used */
- *nelem=start_io_left-io_left;
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5S_point_get_seq_list() */
+} /* end H5Sselect_elements() */
diff --git a/src/H5Sprivate.h b/src/H5Sprivate.h
index 32ac51a..3d68de0 100644
--- a/src/H5Sprivate.h
+++ b/src/H5Sprivate.h
@@ -17,9 +17,6 @@
#ifndef _H5Sprivate_H
#define _H5Sprivate_H
-/* Early typedefs to avoid circular dependencies */
-typedef struct H5S_t H5S_t;
-
/* Include package's public header */
#include "H5Spublic.h"
@@ -30,25 +27,13 @@ typedef struct H5S_t H5S_t;
#include "H5private.h" /* Generic Functions */
#include "H5Fprivate.h" /* Files */
#include "H5Gprivate.h" /* Groups */
-#include "H5Oprivate.h" /* Object headers */
#include "H5Pprivate.h" /* Property lists */
#include "H5Tprivate.h" /* Datatypes */
-/* Flags for H5S_find */
-#define H5S_CONV_PAR_IO_POSSIBLE 0x0001
-/* The storage options are mutually exclusive */
-/* (2-bits reserved for storage type currently) */
-#define H5S_CONV_STORAGE_COMPACT 0x0000 /* i.e. '0' */
-#define H5S_CONV_STORAGE_CONTIGUOUS 0x0002 /* i.e. '1' */
-#define H5S_CONV_STORAGE_CHUNKED 0x0004 /* i.e. '2' */
-#define H5S_CONV_STORAGE_MASK 0x0006
-
-/* Flags for "get_seq_list" methods */
-#define H5S_GET_SEQ_LIST_SORTED 0x0001
-
/* Forward references of package typedefs */
typedef struct H5S_extent_t H5S_extent_t;
typedef struct H5S_pnt_node_t H5S_pnt_node_t;
+typedef struct H5S_pnt_list_t H5S_pnt_list_t;
typedef struct H5S_hyper_span_t H5S_hyper_span_t;
typedef struct H5S_hyper_span_info_t H5S_hyper_span_info_t;
@@ -62,20 +47,22 @@ typedef struct H5S_hyper_dim_t {
/* Point selection iteration container */
typedef struct {
- H5S_pnt_node_t *curr; /* Pointer to next node to output */
+ H5S_pnt_list_t *pnt_lst; /* Pointer to point list */
+ H5S_pnt_node_t *curr; /* Pointer to next node to output */
} H5S_point_iter_t;
/* Hyperslab selection iteration container */
typedef struct {
/* Common fields for all hyperslab selections */
- hsize_t off[H5S_MAX_RANK]; /* Offset in span node (used as position for regular hyperslabs) */
+ hsize_t off[H5S_MAX_RANK]; /* Offset in span node (used as position for regular hyperslabs) */
+ hsize_t slab[H5S_MAX_RANK]; /* Cumulative size of each dimension in bytes */
unsigned iter_rank; /* Rank of iterator information */
/* (This should always be the same as the dataspace
- * rank, except for regular hyperslab selections in
- * which there are contiguous regions in the lower
- * dimensions which have been "flattened" out
+ * rank, except for regular hyperslab selections in
+ * which there are contiguous regions in the lower
+ * dimensions that have been "flattened")
*/
- hbool_t diminfo_valid; /* Whether the dimension information is valid */
+ hbool_t diminfo_valid; /* Whether the dimension information is valid */
/* "Flattened" regular hyperslab selection fields */
H5S_hyper_dim_t diminfo[H5S_MAX_RANK]; /* "Flattened" regular selection information */
@@ -84,6 +71,7 @@ typedef struct {
hbool_t flattened[H5S_MAX_RANK]; /* Whether this dimension has been flattened */
/* Irregular hyperslab selection fields */
+ hsize_t loc_off[H5S_MAX_RANK]; /* Byte offset in buffer, for each dimension's current offset */
H5S_hyper_span_info_t *spans; /* Pointer to copy of the span tree */
H5S_hyper_span_t *span[H5S_MAX_RANK];/* Array of pointers to span nodes */
} H5S_hyper_iter_t;
@@ -104,9 +92,11 @@ typedef struct H5S_sel_iter_t {
/* Information common to all iterators */
unsigned rank; /* Rank of dataspace the selection iterator is operating on */
- hsize_t *dims; /* Dimensions of dataspace the selection is operating on */
+ hsize_t dims[H5S_MAX_RANK]; /* Dimensions of dataspace the selection is operating on */
+ hssize_t sel_off[H5S_MAX_RANK]; /* Selection offset in dataspace */
hsize_t elmt_left; /* Number of elements left to iterate over */
size_t elmt_size; /* Size of elements to iterate over */
+ unsigned flags; /* Flags controlling iterator behavior */
/* Information specific to each type of iterator */
union {
@@ -146,7 +136,6 @@ typedef struct H5S_sel_iter_op_t {
#define H5S_GET_EXTENT_NPOINTS(S) ((S)->extent.nelem)
#define H5S_GET_SELECT_NPOINTS(S) ((S)->select.num_elem)
#define H5S_GET_SELECT_TYPE(S) ((S)->select.type->type)
-#define H5S_SELECT_GET_SEQ_LIST(S,FLAGS,ITER,MAXSEQ,MAXBYTES,NSEQ,NBYTES,OFF,LEN) ((*(S)->select.type->get_seq_list)(S,FLAGS,ITER,MAXSEQ,MAXBYTES,NSEQ,NBYTES,OFF,LEN))
#define H5S_SELECT_VALID(S) ((*(S)->select.type->is_valid)(S))
#define H5S_SELECT_SERIAL_SIZE(S) ((*(S)->select.type->serial_size)(S))
#define H5S_SELECT_SERIALIZE(S,BUF) ((*(S)->select.type->serialize)(S,BUF))
@@ -164,6 +153,7 @@ typedef struct H5S_sel_iter_op_t {
#define H5S_SELECT_ITER_HAS_NEXT_BLOCK(ITER) ((*(ITER)->type->iter_has_next_block)(ITER))
#define H5S_SELECT_ITER_NEXT(ITER,NELEM)((*(ITER)->type->iter_next)(ITER,NELEM))
#define H5S_SELECT_ITER_NEXT_BLOCK(ITER) ((*(ITER)->type->iter_next_block)(ITER))
+#define H5S_SELECT_ITER_GET_SEQ_LIST(ITER,MAXSEQ,MAXBYTES,NSEQ,NBYTES,OFF,LEN) ((*(ITER)->type->iter_get_seq_list)(ITER,MAXSEQ,MAXBYTES,NSEQ,NBYTES,OFF,LEN))
#define H5S_SELECT_ITER_RELEASE(ITER) ((*(ITER)->type->iter_release)(ITER))
#else /* H5S_MODULE */
#define H5S_GET_EXTENT_TYPE(S) (H5S_get_simple_extent_type(S))
@@ -171,7 +161,6 @@ typedef struct H5S_sel_iter_op_t {
#define H5S_GET_EXTENT_NPOINTS(S) (H5S_get_simple_extent_npoints(S))
#define H5S_GET_SELECT_NPOINTS(S) (H5S_get_select_npoints(S))
#define H5S_GET_SELECT_TYPE(S) (H5S_get_select_type(S))
-#define H5S_SELECT_GET_SEQ_LIST(S,FLAGS,ITER,MAXSEQ,MAXBYTES,NSEQ,NBYTES,OFF,LEN) (H5S_select_get_seq_list(S,FLAGS,ITER,MAXSEQ,MAXBYTES,NSEQ,NBYTES,OFF,LEN))
#define H5S_SELECT_VALID(S) (H5S_select_valid(S))
#define H5S_SELECT_SERIAL_SIZE(S) (H5S_select_serial_size(S))
#define H5S_SELECT_SERIALIZE(S,BUF) (H5S_select_serialize(S,BUF))
@@ -189,13 +178,22 @@ typedef struct H5S_sel_iter_op_t {
#define H5S_SELECT_ITER_HAS_NEXT_BLOCK(ITER) (H5S_select_iter_has_next_block(ITER))
#define H5S_SELECT_ITER_NEXT(ITER,NELEM)(H5S_select_iter_next(ITER,NELEM))
#define H5S_SELECT_ITER_NEXT_BLOCK(ITER) (H5S_select_iter_next_block(ITER))
+#define H5S_SELECT_ITER_GET_SEQ_LIST(ITER,MAXSEQ,MAXBYTES,NSEQ,NBYTES,OFF,LEN) (H5S_select_iter_get_seq_list(ITER,MAXSEQ,MAXBYTES,NSEQ,NBYTES,OFF,LEN))
#define H5S_SELECT_ITER_RELEASE(ITER) (H5S_select_iter_release(ITER))
#endif /* H5S_MODULE */
/* Handle these callbacks in a special way, since they have prologs that need to be executed */
#define H5S_SELECT_COPY(DST,SRC,SHARE) (H5S_select_copy(DST,SRC,SHARE))
+#define H5S_SELECT_SHAPE_SAME(S1,S2) (H5S_select_shape_same(S1,S2))
+#define H5S_SELECT_INTERSECT_BLOCK(S,START,END) (H5S_select_intersect_block(S,START,END))
#define H5S_SELECT_RELEASE(S) (H5S_select_release(S))
#define H5S_SELECT_DESERIALIZE(S,BUF) (H5S_select_deserialize(S,BUF))
+/* Forward declaration of structs used below */
+struct H5O_t;
+struct H5O_loc_t;
+
+/* Early typedef to avoid circular dependencies */
+typedef struct H5S_t H5S_t;
/* Operations on dataspaces */
H5_DLL H5S_t *H5S_copy(const H5S_t *src, hbool_t share_selection, hbool_t copy_max);
@@ -207,7 +205,7 @@ H5_DLL hbool_t H5S_has_extent(const H5S_t *ds);
H5_DLL int H5S_get_simple_extent_ndims(const H5S_t *ds);
H5_DLL int H5S_get_simple_extent_dims(const H5S_t *ds, hsize_t dims[]/*out*/,
hsize_t max_dims[]/*out*/);
-H5_DLL herr_t H5S_write(H5F_t *f, H5O_t *oh, unsigned update_flags, H5S_t *ds);
+H5_DLL herr_t H5S_write(H5F_t *f, struct H5O_t *oh, unsigned update_flags, H5S_t *ds);
H5_DLL herr_t H5S_append(H5F_t *f, struct H5O_t *oh, H5S_t *ds);
H5_DLL H5S_t *H5S_read(const struct H5O_loc_t *loc);
H5_DLL htri_t H5S_set_extent(H5S_t *space, const hsize_t *size);
@@ -247,13 +245,12 @@ H5_DLL herr_t H5S_get_select_num_elem_non_unlim(const H5S_t *space,
H5_DLL herr_t H5S_select_offset(H5S_t *space, const hssize_t *offset);
H5_DLL herr_t H5S_select_copy(H5S_t *dst, const H5S_t *src, hbool_t share_selection);
H5_DLL htri_t H5S_select_shape_same(const H5S_t *space1, const H5S_t *space2);
+H5_DLL htri_t H5S_select_intersect_block(const H5S_t *space, const hsize_t *start,
+ const hsize_t *end);
H5_DLL herr_t H5S_select_construct_projection(const H5S_t *base_space,
H5S_t **new_space_ptr, unsigned new_space_rank, const void *buf,
void const **adj_buf_ptr, hsize_t element_size);
H5_DLL herr_t H5S_select_release(H5S_t *ds);
-H5_DLL herr_t H5S_select_get_seq_list(const H5S_t *space, unsigned flags,
- H5S_sel_iter_t *iter, size_t maxseq, size_t maxbytes,
- size_t *nseq, size_t *nbytes, hsize_t *off, size_t *len);
H5_DLL hssize_t H5S_select_serial_size(const H5S_t *space);
H5_DLL herr_t H5S_select_serialize(const H5S_t *space, uint8_t **p);
H5_DLL htri_t H5S_select_is_contiguous(const H5S_t *space);
@@ -280,14 +277,11 @@ H5_DLL herr_t H5S_select_elements(H5S_t *space, H5S_seloper_t op,
/* Operations on hyperslab selections */
H5_DLL herr_t H5S_select_hyperslab(H5S_t *space, H5S_seloper_t op, const hsize_t start[],
const hsize_t *stride, const hsize_t count[], const hsize_t *block);
+H5_DLL herr_t H5S_combine_hyperslab(H5S_t *old_space, H5S_seloper_t op,
+ const hsize_t start[], const hsize_t *stride, const hsize_t count[],
+ const hsize_t *block, H5S_t **new_space);
H5_DLL herr_t H5S_hyper_add_span_element(H5S_t *space, unsigned rank,
const hsize_t *coords);
-H5_DLL herr_t H5S_hyper_reset_scratch(H5S_t *space);
-H5_DLL herr_t H5S_hyper_convert(H5S_t *space);
-#ifdef LATER
-H5_DLL htri_t H5S_hyper_intersect (H5S_t *space1, H5S_t *space2);
-#endif /* LATER */
-H5_DLL htri_t H5S_hyper_intersect_block(H5S_t *space, const hsize_t *start, const hsize_t *end);
H5_DLL herr_t H5S_hyper_adjust_s(H5S_t *space, const hssize_t *offset);
H5_DLL htri_t H5S_hyper_normalize_offset(H5S_t *space, hssize_t *old_offset);
H5_DLL herr_t H5S_hyper_denormalize_offset(H5S_t *space, const hssize_t *old_offset);
@@ -302,19 +296,22 @@ H5_DLL hsize_t H5S_hyper_get_first_inc_block(const H5S_t *space,
hsize_t clip_size, hbool_t *partial);
/* Operations on selection iterators */
-H5_DLL herr_t H5S_select_iter_init(H5S_sel_iter_t *iter, const H5S_t *space, size_t elmt_size);
+H5_DLL herr_t H5S_select_iter_init(H5S_sel_iter_t *iter, const H5S_t *space,
+ size_t elmt_size, unsigned flags);
H5_DLL herr_t H5S_select_iter_coords(const H5S_sel_iter_t *sel_iter, hsize_t *coords);
H5_DLL hsize_t H5S_select_iter_nelmts(const H5S_sel_iter_t *sel_iter);
H5_DLL herr_t H5S_select_iter_next(H5S_sel_iter_t *sel_iter, size_t nelem);
+H5_DLL herr_t H5S_select_iter_get_seq_list(H5S_sel_iter_t *iter, size_t maxseq,
+ size_t maxbytes, size_t *nseq, size_t *nbytes, hsize_t *off, size_t *len);
H5_DLL herr_t H5S_select_iter_release(H5S_sel_iter_t *sel_iter);
+H5_DLL herr_t H5S_sel_iter_close(H5S_sel_iter_t *sel_iter);
#ifdef H5_HAVE_PARALLEL
-H5_DLL hsize_t H5S_mpio_set_bigio_count(hsize_t new_count);
H5_DLL herr_t H5S_mpio_space_type(const H5S_t *space, size_t elmt_size,
/* out: */ MPI_Datatype *new_type,
int *count,
hbool_t *is_derived_type,
- hbool_t do_permute,
+ hbool_t do_permute,
hsize_t **permute_map,
hbool_t * is_permuted);
#endif /* H5_HAVE_PARALLEL */
diff --git a/src/H5Spublic.h b/src/H5Spublic.h
index 09b474a..a04f3c1 100644
--- a/src/H5Spublic.h
+++ b/src/H5Spublic.h
@@ -28,6 +28,35 @@
/* Define user-level maximum number of dimensions */
#define H5S_MAX_RANK 32
+/* Flags for selection iterators */
+#define H5S_SEL_ITER_GET_SEQ_LIST_SORTED 0x0001 /* Retrieve elements from iterator
+ * in increasing offset order, for
+ * each call to retrieve sequences.
+ * Currently, this only applies to
+ * point selections, as hyperslab
+ * selections are always returned
+ * in increasing offset order.
+ *
+ * Note that the order is only
+ * increasing for each call to
+ * get_seq_list, the next set of
+ * sequences could start with an
+ * earlier offset than the previous
+ * one.
+ */
+#define H5S_SEL_ITER_SHARE_WITH_DATASPACE 0x0002 /* Don't copy the dataspace
+ * selection when creating the
+ * selection iterator.
+ *
+ * This can improve performance
+ * of creating the iterator, but
+ * the dataspace _MUST_NOT_ be
+ * modified or closed until the
+ * selection iterator is closed
+ * or the iterator's behavior
+ * will be undefined.
+ */
+
/* Different types of dataspaces */
typedef enum H5S_class_t {
H5S_NO_CLASS = -1, /*error */
@@ -79,74 +108,86 @@ typedef enum H5S_seloper_t {
typedef enum {
H5S_SEL_ERROR = -1, /* Error */
H5S_SEL_NONE = 0, /* Nothing selected */
- H5S_SEL_POINTS = 1, /* Sequence of points selected */
- H5S_SEL_HYPERSLABS = 2, /* "New-style" hyperslab selection defined */
+ H5S_SEL_POINTS = 1, /* Points / elements selected */
+ H5S_SEL_HYPERSLABS = 2, /* Hyperslab selected */
H5S_SEL_ALL = 3, /* Entire extent selected */
H5S_SEL_N /*THIS MUST BE LAST */
-}H5S_sel_type;
+} H5S_sel_type;
#ifdef __cplusplus
extern "C" {
#endif
-/* Functions in H5S.c */
+/* Operations on dataspaces */
H5_DLL hid_t H5Screate(H5S_class_t type);
H5_DLL hid_t H5Screate_simple(int rank, const hsize_t dims[],
- const hsize_t maxdims[]);
+ const hsize_t maxdims[]);
H5_DLL herr_t H5Sset_extent_simple(hid_t space_id, int rank,
- const hsize_t dims[],
- const hsize_t max[]);
+ const hsize_t dims[], const hsize_t max[]);
H5_DLL hid_t H5Scopy(hid_t space_id);
H5_DLL herr_t H5Sclose(hid_t space_id);
-H5_DLL herr_t H5Sencode(hid_t obj_id, void *buf, size_t *nalloc);
+H5_DLL herr_t H5Sencode2(hid_t obj_id, void *buf, size_t *nalloc, hid_t fapl);
H5_DLL hid_t H5Sdecode(const void *buf);
H5_DLL hssize_t H5Sget_simple_extent_npoints(hid_t space_id);
H5_DLL int H5Sget_simple_extent_ndims(hid_t space_id);
H5_DLL int H5Sget_simple_extent_dims(hid_t space_id, hsize_t dims[],
- hsize_t maxdims[]);
+ hsize_t maxdims[]);
H5_DLL htri_t H5Sis_simple(hid_t space_id);
-H5_DLL hssize_t H5Sget_select_npoints(hid_t spaceid);
-H5_DLL herr_t H5Sselect_hyperslab(hid_t space_id, H5S_seloper_t op,
- const hsize_t start[],
- const hsize_t _stride[],
- const hsize_t count[],
- const hsize_t _block[]);
-/* #define NEW_HYPERSLAB_API */
-/* Note that these haven't been working for a while and were never
- * publicly released - QAK */
-#ifdef NEW_HYPERSLAB_API
-H5_DLL hid_t H5Scombine_hyperslab(hid_t space_id, H5S_seloper_t op,
- const hsize_t start[],
- const hsize_t _stride[],
- const hsize_t count[],
- const hsize_t _block[]);
-H5_DLL herr_t H5Sselect_select(hid_t space1_id, H5S_seloper_t op,
- hid_t space2_id);
-H5_DLL hid_t H5Scombine_select(hid_t space1_id, H5S_seloper_t op,
- hid_t space2_id);
-#endif /* NEW_HYPERSLAB_API */
-H5_DLL herr_t H5Sselect_elements(hid_t space_id, H5S_seloper_t op,
- size_t num_elem, const hsize_t *coord);
H5_DLL H5S_class_t H5Sget_simple_extent_type(hid_t space_id);
H5_DLL herr_t H5Sset_extent_none(hid_t space_id);
H5_DLL herr_t H5Sextent_copy(hid_t dst_id,hid_t src_id);
H5_DLL htri_t H5Sextent_equal(hid_t sid1, hid_t sid2);
+
+/* Operations on dataspace selections */
+H5_DLL H5S_sel_type H5Sget_select_type(hid_t spaceid);
+H5_DLL hssize_t H5Sget_select_npoints(hid_t spaceid);
+H5_DLL herr_t H5Sselect_copy(hid_t dst_id, hid_t src_id);
+H5_DLL htri_t H5Sselect_valid(hid_t spaceid);
+H5_DLL herr_t H5Sselect_adjust_u(hid_t spaceid, const hsize_t *offset);
+H5_DLL herr_t H5Sget_select_bounds(hid_t spaceid, hsize_t start[],
+ hsize_t end[]);
+H5_DLL htri_t H5Sselect_shape_same(hid_t space1_id, hid_t space2_id);
+H5_DLL htri_t H5Sselect_intersect_block(hid_t space_id, const hsize_t *start,
+ const hsize_t *end);
+H5_DLL herr_t H5Soffset_simple(hid_t space_id, const hssize_t *offset);
H5_DLL herr_t H5Sselect_all(hid_t spaceid);
H5_DLL herr_t H5Sselect_none(hid_t spaceid);
-H5_DLL herr_t H5Soffset_simple(hid_t space_id, const hssize_t *offset);
-H5_DLL htri_t H5Sselect_valid(hid_t spaceid);
+H5_DLL herr_t H5Sselect_elements(hid_t space_id, H5S_seloper_t op,
+ size_t num_elem, const hsize_t *coord);
+H5_DLL hssize_t H5Sget_select_elem_npoints(hid_t spaceid);
+H5_DLL herr_t H5Sget_select_elem_pointlist(hid_t spaceid, hsize_t startpoint,
+ hsize_t numpoints, hsize_t buf[/*numpoints*/]);
+H5_DLL herr_t H5Sselect_hyperslab(hid_t space_id, H5S_seloper_t op,
+ const hsize_t start[], const hsize_t _stride[], const hsize_t count[],
+ const hsize_t _block[]);
+H5_DLL hid_t H5Scombine_hyperslab(hid_t space_id, H5S_seloper_t op,
+ const hsize_t start[], const hsize_t _stride[], const hsize_t count[],
+ const hsize_t _block[]);
+H5_DLL herr_t H5Smodify_select(hid_t space1_id, H5S_seloper_t op, hid_t space2_id);
+H5_DLL hid_t H5Scombine_select(hid_t space1_id, H5S_seloper_t op, hid_t space2_id);
H5_DLL htri_t H5Sis_regular_hyperslab(hid_t spaceid);
H5_DLL htri_t H5Sget_regular_hyperslab(hid_t spaceid, hsize_t start[],
hsize_t stride[], hsize_t count[], hsize_t block[]);
H5_DLL hssize_t H5Sget_select_hyper_nblocks(hid_t spaceid);
-H5_DLL hssize_t H5Sget_select_elem_npoints(hid_t spaceid);
H5_DLL herr_t H5Sget_select_hyper_blocklist(hid_t spaceid, hsize_t startblock,
hsize_t numblocks, hsize_t buf[/*numblocks*/]);
-H5_DLL herr_t H5Sget_select_elem_pointlist(hid_t spaceid, hsize_t startpoint,
- hsize_t numpoints, hsize_t buf[/*numpoints*/]);
-H5_DLL herr_t H5Sget_select_bounds(hid_t spaceid, hsize_t start[],
- hsize_t end[]);
-H5_DLL H5S_sel_type H5Sget_select_type(hid_t spaceid);
+H5_DLL herr_t H5Shyper_adjust_s(hid_t space_id, const hssize_t *offset);
+
+/* Operations on dataspace selection iterators */
+H5_DLL hid_t H5Ssel_iter_create(hid_t spaceid, size_t elmt_size, unsigned flags);
+H5_DLL herr_t H5Ssel_iter_get_seq_list(hid_t sel_iter_id, size_t maxseq,
+ size_t maxbytes, size_t *nseq, size_t *nbytes, hsize_t *off, size_t *len);
+H5_DLL herr_t H5Ssel_iter_close(hid_t sel_iter_id);
+
+/* Symbols defined for compatibility with previous versions of the HDF5 API.
+ *
+ * Use of these symbols is deprecated.
+ */
+#ifndef H5_NO_DEPRECATED_SYMBOLS
+/* Function prototypes */
+H5_DLL herr_t H5Sencode1(hid_t obj_id, void *buf, size_t *nalloc);
+
+#endif /* H5_NO_DEPRECATED_SYMBOLS */
#ifdef __cplusplus
}
diff --git a/src/H5Sselect.c b/src/H5Sselect.c
index 2ce3f10..1a13f2c 100644
--- a/src/H5Sselect.c
+++ b/src/H5Sselect.c
@@ -17,26 +17,59 @@
* Purpose: Dataspace selection functions.
*/
+/****************/
+/* Module Setup */
+/****************/
+
#include "H5Smodule.h" /* This source code file is part of the H5S module */
+/***********/
+/* Headers */
+/***********/
#include "H5private.h" /* Generic Functions */
#include "H5Dprivate.h" /* Datasets */
#include "H5Eprivate.h" /* Error handling */
#include "H5FLprivate.h" /* Free Lists */
#include "H5Iprivate.h" /* IDs */
-#include "H5MMprivate.h" /* Memory management */
#include "H5Spkg.h" /* Dataspaces */
-#include "H5VMprivate.h" /* Vector and array functions */
-#include "H5WBprivate.h" /* Wrapped Buffers */
+#include "H5VMprivate.h" /* Vector and array functions */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+/* All the valid public flags to H5Ssel_iter_create() */
+#define H5S_SEL_ITER_ALL_PUBLIC_FLAGS (H5S_SEL_ITER_GET_SEQ_LIST_SORTED | \
+ H5S_SEL_ITER_SHARE_WITH_DATASPACE)
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
-/* Local functions */
#ifdef LATER
static herr_t H5S_select_iter_block(const H5S_sel_iter_t *iter, hsize_t *start, hsize_t *end);
static htri_t H5S_select_iter_has_next_block(const H5S_sel_iter_t *iter);
static herr_t H5S_select_iter_next_block(H5S_sel_iter_t *iter);
#endif /* LATER */
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
/* Declare a free list to manage the H5S_sel_iter_t struct */
H5FL_DEFINE(H5S_sel_iter_t);
@@ -47,6 +80,11 @@ H5FL_SEQ_EXTERN(size_t);
H5FL_SEQ_EXTERN(hsize_t);
+/*******************/
+/* Local Variables */
+/*******************/
+
+
/*--------------------------------------------------------------------------
NAME
@@ -78,13 +116,102 @@ H5S_select_offset(H5S_t *space, const hssize_t *offset)
HDassert(offset);
/* Copy the offset over */
- HDmemcpy(space->select.offset, offset, sizeof(hssize_t)*space->extent.rank);
+ H5MM_memcpy(space->select.offset, offset, sizeof(hssize_t) * space->extent.rank);
/* Indicate that the offset was changed */
space->select.offset_changed = TRUE;
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5S_select_offset() */
+} /* end H5S_select_offset() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Soffset_simple
+ PURPOSE
+ Changes the offset of a selection within a simple dataspace extent
+ USAGE
+ herr_t H5Soffset_simple(space_id, offset)
+ hid_t space_id; IN: Dataspace object to reset
+ const hssize_t *offset; IN: Offset to position the selection at
+ RETURNS
+ Non-negative on success/Negative on failure
+ DESCRIPTION
+ This function creates an offset for the selection within an extent, allowing
+ the same shaped selection to be moved to different locations within a
+ dataspace without requiring it to be re-defined.
+--------------------------------------------------------------------------*/
+herr_t
+H5Soffset_simple(hid_t space_id, const hssize_t *offset)
+{
+ H5S_t *space; /* Dataspace to query */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE2("e", "i*Hs", space_id, offset);
+
+ /* Check args */
+ if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "not a dataspace")
+ if(space->extent.rank == 0 || (H5S_GET_EXTENT_TYPE(space) == H5S_SCALAR
+ || H5S_GET_EXTENT_TYPE(space) == H5S_NULL))
+ HGOTO_ERROR(H5E_ATOM, H5E_UNSUPPORTED, FAIL, "can't set offset on scalar or null dataspace")
+ if(offset == NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no offset specified")
+
+ /* Set the selection offset */
+ if(H5S_select_offset(space, offset) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't set offset")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Soffset_simple() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Sselect_copy
+ PURPOSE
+ Copy a selection from one dataspace to another
+ USAGE
+ herr_t H5Sselect_copy(dst, src)
+ hid_t dst; OUT: ID of the destination dataspace
+ hid_t src; IN: ID of the source dataspace
+
+ RETURNS
+ Non-negative on success/Negative on failure
+ DESCRIPTION
+ Copies all the selection information (including offset) from the source
+ dataspace to the destination dataspace.
+
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5Sselect_copy(hid_t dst_id, hid_t src_id)
+{
+ H5S_t *src;
+ H5S_t *dst;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE2("e", "ii", dst_id, src_id);
+
+ /* Check args */
+ if(NULL == (src = (H5S_t *)H5I_object_verify(src_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
+ if(NULL == (dst = (H5S_t *)H5I_object_verify(dst_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
+
+ /* Copy */
+ if(H5S_select_copy(dst, src, FALSE) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy selection")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Sselect_copy() */
/*--------------------------------------------------------------------------
@@ -93,9 +220,10 @@ H5S_select_offset(H5S_t *space, const hssize_t *offset)
PURPOSE
Copy a selection from one dataspace to another
USAGE
- herr_t H5S_select_copy(dst, src)
+ herr_t H5S_select_copy(dst, src, share_selection)
H5S_t *dst; OUT: Pointer to the destination dataspace
H5S_t *src; IN: Pointer to the source dataspace
+ hbool_t; IN: Whether to share the selection between the dataspaces
RETURNS
Non-negative on success/Negative on failure
DESCRIPTION
@@ -122,16 +250,20 @@ H5S_select_copy(H5S_t *dst, const H5S_t *src, hbool_t share_selection)
HDassert(dst);
HDassert(src);
+ /* Release the current selection */
+ if(H5S_SELECT_RELEASE(dst) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection")
+
/* Copy regular fields */
dst->select = src->select;
/* Perform correct type of copy based on the type of selection */
- if((ret_value = (*src->select.type->copy)(dst,src,share_selection)) < 0)
+ if((ret_value = (*src->select.type->copy)(dst, src, share_selection)) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy selection specific information")
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_select_copy() */
+} /* end H5S_select_copy() */
/*-------------------------------------------------------------------------
@@ -153,7 +285,7 @@ done:
herr_t
H5S_select_release(H5S_t *ds)
{
- herr_t ret_value = FAIL; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
@@ -165,44 +297,7 @@ H5S_select_release(H5S_t *ds)
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5S_select_release() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5S_select_get_seq_list
- *
- * Purpose: Retrieves the next sequence of offset/length pairs for an
- * iterator on a dataspace
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * Tuesday, May 18, 2004
- *
- * Note: This routine participates in the "Inlining C function pointers"
- * pattern, don't call it directly, use the appropriate macro
- * defined in H5Sprivate.h.
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5S_select_get_seq_list(const H5S_t *space, unsigned flags,
- H5S_sel_iter_t *iter, size_t maxseq, size_t maxbytes,
- size_t *nseq, size_t *nbytes, hsize_t *off, size_t *len)
-{
- herr_t ret_value = FAIL; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT
-
- HDassert(space);
-
- /* Call the selection type's get_seq_list function */
- if((ret_value = (*space->select.type->get_seq_list)(space, flags, iter, maxseq, maxbytes, nseq, nbytes, off, len)) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get selection sequence list")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5S_select_get_seq_list() */
+} /* end H5S_select_release() */
/*-------------------------------------------------------------------------
@@ -232,10 +327,10 @@ H5S_select_serial_size(const H5S_t *space)
HDassert(space);
/* Call the selection type's serial_size function */
- ret_value=(*space->select.type->serial_size)(space);
+ ret_value = (*space->select.type->serial_size)(space);
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5S_select_serial_size() */
+} /* end H5S_select_serial_size() */
/*--------------------------------------------------------------------------
@@ -265,7 +360,7 @@ H5S_select_serial_size(const H5S_t *space)
herr_t
H5S_select_serialize(const H5S_t *space, uint8_t **p)
{
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT_NOERR
@@ -273,10 +368,10 @@ H5S_select_serialize(const H5S_t *space, uint8_t **p)
HDassert(p);
/* Call the selection type's serialize function */
- ret_value=(*space->select.type->serialize)(space,p);
+ ret_value = (*space->select.type->serialize)(space, p);
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5S_select_serialize() */
+} /* end H5S_select_serialize() */
/*--------------------------------------------------------------------------
@@ -313,7 +408,7 @@ H5Sget_select_npoints(hid_t spaceid)
done:
FUNC_LEAVE_API(ret_value)
-} /* H5Sget_select_npoints() */
+} /* H5Sget_select_npoints() */
/*--------------------------------------------------------------------------
@@ -336,7 +431,7 @@ done:
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-hssize_t
+H5_ATTR_PURE hssize_t
H5S_get_select_npoints(const H5S_t *space)
{
FUNC_ENTER_NOAPI_NOINIT_NOERR
@@ -345,7 +440,7 @@ H5S_get_select_npoints(const H5S_t *space)
HDassert(space);
FUNC_LEAVE_NOAPI((hssize_t)space->select.num_elem)
-} /* H5S_get_select_npoints() */
+} /* end H5S_get_select_npoints() */
/*--------------------------------------------------------------------------
@@ -367,8 +462,6 @@ H5S_get_select_npoints(const H5S_t *space)
COMMENTS, BUGS, ASSUMPTIONS
EXAMPLES
REVISION LOG
- Christian Chilan 01/17/2007
- Changed the error return value from 0 to FAIL.
--------------------------------------------------------------------------*/
htri_t
H5Sselect_valid(hid_t spaceid)
@@ -387,7 +480,7 @@ H5Sselect_valid(hid_t spaceid)
done:
FUNC_LEAVE_API(ret_value)
-} /* H5Sselect_valid() */
+} /* end H5Sselect_valid() */
/*--------------------------------------------------------------------------
@@ -425,7 +518,7 @@ H5S_select_valid(const H5S_t *space)
ret_value = (*space->select.type->is_valid)(space);
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_select_valid() */
+} /* end H5S_select_valid() */
/*--------------------------------------------------------------------------
@@ -457,103 +550,46 @@ H5S_select_valid(const H5S_t *space)
herr_t
H5S_select_deserialize(H5S_t **space, const uint8_t **p)
{
- H5S_t *tmp_space = NULL; /* Pointer to actual dataspace to use, either
- *space or a newly allocated one */
uint32_t sel_type; /* Pointer to the selection type */
- uint32_t version; /* Version number */
- uint8_t flags = 0; /* Flags */
herr_t ret_value = FAIL; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
HDassert(space);
- /* Allocate space if not provided */
- if(!*space) {
- if(NULL == (tmp_space = H5S_create(H5S_SIMPLE)))
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't create dataspace")
- } /* end if */
- else
- tmp_space = *space;
+ /* Selection-type specific coding is moved to the callbacks. */
/* Decode selection type */
UINT32DECODE(*p, sel_type);
- /* Decode version */
- UINT32DECODE(*p, version);
-
- if(version >= (uint32_t)2) {
- /* Decode flags */
- flags = *(*p)++;
-
- /* Check for unknown flags */
- if(flags & ~H5S_SELECT_FLAG_BITS)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTLOAD, FAIL, "unknown flag for selection")
-
- /* Skip over the remainder of the header */
- *p += 4;
- } /* end if */
- else
- /* Skip over the remainder of the header */
- *p += 8;
-
- /* Decode and check or patch rank for point and hyperslab selections */
- if((sel_type == H5S_SEL_POINTS) || (sel_type == H5S_SEL_HYPERSLABS)) {
- uint32_t rank; /* Rank of dataspace */
-
- /* Decode the rank of the point selection */
- UINT32DECODE(*p,rank);
-
- if(!*space) {
- hsize_t dims[H5S_MAX_RANK];
-
- /* Patch the rank of the allocated dataspace */
- (void)HDmemset(dims, 0, (size_t)rank * sizeof(dims[0]));
- if(H5S_set_extent_simple(tmp_space, rank, dims, NULL) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't set dimensions")
- } /* end if */
- else
- /* Verify the rank of the provided dataspace */
- if(rank != tmp_space->extent.rank)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "rank of serialized selection does not match dataspace")
- } /* end if */
-
/* Make routine for selection type */
switch(sel_type) {
case H5S_SEL_POINTS: /* Sequence of points selected */
- ret_value = (*H5S_sel_point->deserialize)(tmp_space, version, flags, p);
+ ret_value = (*H5S_sel_point->deserialize)(space, p);
break;
case H5S_SEL_HYPERSLABS: /* Hyperslab selection defined */
- ret_value = (*H5S_sel_hyper->deserialize)(tmp_space, version, flags, p);
+ ret_value = (*H5S_sel_hyper->deserialize)(space, p);
break;
case H5S_SEL_ALL: /* Entire extent selected */
- ret_value = (*H5S_sel_all->deserialize)(tmp_space, version, flags, p);
+ ret_value = (*H5S_sel_all->deserialize)(space, p);
break;
case H5S_SEL_NONE: /* Nothing selected */
- ret_value = (*H5S_sel_none->deserialize)(tmp_space, version, flags, p);
+ ret_value = (*H5S_sel_none->deserialize)(space, p);
break;
default:
break;
- }
+ } /* end switch */
+
if(ret_value < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTLOAD, FAIL, "can't deserialize selection")
- /* Return space to the caller if allocated */
- if(!*space)
- *space = tmp_space;
-
done:
- /* Free temporary space if not passed to caller (only happens on error) */
- if(!*space && tmp_space)
- if(H5S_close(tmp_space) < 0)
- HDONE_ERROR(H5E_DATASPACE, H5E_CANTFREE, FAIL, "can't close dataspace")
-
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_select_deserialize() */
+} /* end H5S_select_deserialize() */
/*--------------------------------------------------------------------------
@@ -605,7 +641,7 @@ H5Sget_select_bounds(hid_t spaceid, hsize_t start[], hsize_t end[])
done:
FUNC_LEAVE_API(ret_value)
-} /* H5Sget_select_bounds() */
+} /* end H5Sget_select_bounds() */
/*--------------------------------------------------------------------------
@@ -647,10 +683,10 @@ H5S_get_select_bounds(const H5S_t *space, hsize_t *start, hsize_t *end)
HDassert(start);
HDassert(end);
- ret_value = (*space->select.type->bounds)(space,start,end);
+ ret_value = (*space->select.type->bounds)(space, start, end);
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_get_select_bounds() */
+} /* end H5S_get_select_bounds() */
/*--------------------------------------------------------------------------
@@ -690,7 +726,7 @@ H5S_get_select_offset(const H5S_t *space, hsize_t *offset)
ret_value = (*space->select.type->offset)(space, offset);
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_get_select_offset() */
+} /* end H5S_get_select_offset() */
/*--------------------------------------------------------------------------
@@ -728,7 +764,7 @@ H5S_get_select_unlim_dim(const H5S_t *space)
ret_value = (*space->select.type->unlim_dim)(space);
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_get_select_unlim_dim() */
+} /* end H5S_get_select_unlim_dim() */
/*--------------------------------------------------------------------------
@@ -773,7 +809,7 @@ H5S_get_select_num_elem_non_unlim(const H5S_t *space,
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_get_select_unlim_dim() */
+} /* end H5S_get_select_unlim_dim() */
/*--------------------------------------------------------------------------
@@ -810,7 +846,7 @@ H5S_select_is_contiguous(const H5S_t *space)
ret_value = (*space->select.type->is_contiguous)(space);
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_select_is_contiguous() */
+} /* end H5S_select_is_contiguous() */
/*--------------------------------------------------------------------------
@@ -847,7 +883,7 @@ H5S_select_is_single(const H5S_t *space)
ret_value = (*space->select.type->is_single)(space);
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_select_is_single() */
+} /* end H5S_select_is_single() */
/*--------------------------------------------------------------------------
@@ -884,7 +920,7 @@ H5S_select_is_regular(const H5S_t *space)
ret_value = (*space->select.type->is_regular)(space);
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_select_is_regular() */
+} /* end H5S_select_is_regular() */
/*--------------------------------------------------------------------------
@@ -911,7 +947,9 @@ H5S_select_is_regular(const H5S_t *space)
herr_t
H5S_select_adjust_u(H5S_t *space, const hsize_t *offset)
{
- herr_t ret_value = FAIL; /* Return value */
+ hbool_t non_zero_offset = FALSE; /* Whether any offset is non-zero */
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT_NOERR
@@ -919,10 +957,58 @@ H5S_select_adjust_u(H5S_t *space, const hsize_t *offset)
HDassert(space);
HDassert(offset);
- ret_value = (*space->select.type->adjust_u)(space, offset);
+ /* Check for an all-zero offset vector */
+ for(u = 0; u < space->extent.rank; u++)
+ if(0 != offset[u]) {
+ non_zero_offset = TRUE;
+ break;
+ } /* end if */
+
+ /* Only perform operation if the offset is non-zero */
+ if(non_zero_offset)
+ ret_value = (*space->select.type->adjust_u)(space, offset);
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_select_adjust_u() */
+} /* end H5S_select_adjust_u() */
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Sselect_adjust_u
+ PURPOSE
+ Adjust a selection by subtracting an offset
+ USAGE
+ herr_t H5Sselect_adjust_u(space_id, offset)
+ hid_t space_id; IN: ID of dataspace to adjust
+ const hsize_t *offset; IN: Offset to subtract
+ RETURNS
+ Non-negative on success, negative on failure
+ DESCRIPTION
+ Moves a selection by subtracting an offset from it.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5Sselect_adjust_u(hid_t space_id, const hsize_t *offset)
+{
+ H5S_t *space;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE2("e", "i*h", space_id, offset);
+
+ if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "not a dataspace")
+ if(NULL == offset)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "NULL offset pointer")
+
+ if(H5S_select_adjust_u(space, offset) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't adjust selection");
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Sselect_adjust_u() */
/*--------------------------------------------------------------------------
@@ -961,7 +1047,7 @@ H5S_select_project_scalar(const H5S_t *space, hsize_t *offset)
ret_value = (*space->select.type->project_scalar)(space, offset);
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_select_project_scalar() */
+} /* end H5S_select_project_scalar() */
/*--------------------------------------------------------------------------
@@ -1002,7 +1088,7 @@ H5S_select_project_simple(const H5S_t *space, H5S_t *new_space, hsize_t *offset)
ret_value = (*space->select.type->project_simple)(space, new_space, offset);
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_select_project_simple() */
+} /* end H5S_select_project_simple() */
/*--------------------------------------------------------------------------
@@ -1011,11 +1097,12 @@ H5S_select_project_simple(const H5S_t *space, H5S_t *new_space, hsize_t *offset)
PURPOSE
Initializes iteration information for a selection.
USAGE
- herr_t H5S_select_iter_init(sel_iter, space, elmt_size)
+ herr_t H5S_select_iter_init(sel_iter, space, elmt_size, flags)
H5S_sel_iter_t *sel_iter; OUT: Selection iterator to initialize.
H5S_t *space; IN: Dataspace object containing selection to
iterate over
size_t elmt_size; IN: Size of elements in the selection
+ unsigned flags; IN: Flags to control iteration behavior
RETURNS
Non-negative on success, negative on failure.
DESCRIPTION
@@ -1023,7 +1110,8 @@ H5S_select_project_simple(const H5S_t *space, H5S_t *new_space, hsize_t *offset)
in the dataspace's selection.
--------------------------------------------------------------------------*/
herr_t
-H5S_select_iter_init(H5S_sel_iter_t *sel_iter, const H5S_t *space, size_t elmt_size)
+H5S_select_iter_init(H5S_sel_iter_t *sel_iter, const H5S_t *space,
+ size_t elmt_size, unsigned flags)
{
herr_t ret_value = FAIL; /* Return value */
@@ -1038,21 +1126,27 @@ H5S_select_iter_init(H5S_sel_iter_t *sel_iter, const H5S_t *space, size_t elmt_s
/* Save the dataspace's rank */
sel_iter->rank = space->extent.rank;
- /* Point to the dataspace dimensions, if there are any */
- if(sel_iter->rank > 0)
- sel_iter->dims = space->extent.size;
- else
- sel_iter->dims = NULL;
+ /* If dims > 0, copy the dataspace dimensions & selection offset */
+ if(sel_iter->rank > 0) {
+ H5MM_memcpy(sel_iter->dims, space->extent.size, sizeof(hsize_t) * space->extent.rank);
+ H5MM_memcpy(sel_iter->sel_off, space->select.offset, sizeof(hsize_t) * space->extent.rank);
+ } /* end if */
/* Save the element size */
sel_iter->elmt_size = elmt_size;
+ /* Initialize the number of elements to iterate over */
+ sel_iter->elmt_left = space->select.num_elem;
+
+ /* Set the flags for the iterator */
+ sel_iter->flags = flags;
+
/* Call initialization routine for selection type */
- ret_value = (*space->select.type->iter_init)(sel_iter, space);
+ ret_value = (*space->select.type->iter_init)(space, sel_iter);
HDassert(sel_iter->type);
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_select_iter_init() */
+} /* end H5S_select_iter_init() */
/*--------------------------------------------------------------------------
@@ -1089,10 +1183,10 @@ H5S_select_iter_coords(const H5S_sel_iter_t *sel_iter, hsize_t *coords)
HDassert(coords);
/* Call iter_coords routine for selection type */
- ret_value = (*sel_iter->type->iter_coords)(sel_iter,coords);
+ ret_value = (*sel_iter->type->iter_coords)(sel_iter, coords);
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_select_iter_coords() */
+} /* end H5S_select_iter_coords() */
#ifdef LATER
@@ -1124,7 +1218,7 @@ H5S_select_iter_block(const H5S_sel_iter_t *iter, hsize_t *start, hsize_t *end)
{
herr_t ret_value; /* return value */
- FUNC_ENTER_NOAPI_NOINIT_NOINIT_NOERR
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
/* Check args */
HDassert(iter);
@@ -1132,10 +1226,10 @@ H5S_select_iter_block(const H5S_sel_iter_t *iter, hsize_t *start, hsize_t *end)
HDassert(end);
/* Call iter_block routine for selection type */
- ret_value = (*iter->type->iter_block)(iter,start,end);
+ ret_value = (*iter->type->iter_block)(iter, start, end);
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_select_iter_block() */
+} /* end H5S_select_iter_block() */
#endif /* LATER */
@@ -1173,7 +1267,7 @@ H5S_select_iter_nelmts(const H5S_sel_iter_t *sel_iter)
ret_value = (*sel_iter->type->iter_nelmts)(sel_iter);
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_select_iter_nelmts() */
+} /* end H5S_select_iter_nelmts() */
#ifdef LATER
@@ -1203,7 +1297,7 @@ H5S_select_iter_has_next_block(const H5S_sel_iter_t *iter)
{
herr_t ret_value; /* return value */
- FUNC_ENTER_NOAPI_NOINIT_NOINIT_NOERR
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
/* Check args */
HDassert(iter);
@@ -1212,7 +1306,7 @@ H5S_select_iter_has_next_block(const H5S_sel_iter_t *iter)
ret_value = (*iter->type->iter_has_next_block)(iter);
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_select_iter_has_next_block() */
+} /* end H5S_select_iter_has_next_block() */
#endif /* LATER */
@@ -1250,13 +1344,13 @@ H5S_select_iter_next(H5S_sel_iter_t *iter, size_t nelem)
HDassert(nelem>0);
/* Call iter_next routine for selection type */
- ret_value = (*iter->type->iter_next)(iter,nelem);
+ ret_value = (*iter->type->iter_next)(iter, nelem);
/* Decrement the number of elements left in selection */
iter->elmt_left-=nelem;
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_select_iter_next() */
+} /* end H5S_select_iter_next() */
#ifdef LATER
@@ -1297,17 +1391,54 @@ H5S_select_iter_next_block(H5S_sel_iter_t *iter)
ret_value = (*iter->type->iter_next_block)(iter);
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_select_iter_next_block() */
+} /* end H5S_select_iter_next_block() */
#endif /* LATER */
+/*-------------------------------------------------------------------------
+ * Function: H5S_select_iter_get_seq_list
+ *
+ * Purpose: Retrieves the next sequence of offset/length pairs for an
+ * iterator on a dataspace
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, May 18, 2004
+ *
+ * Note: This routine participates in the "Inlining C function pointers"
+ * pattern, don't call it directly, use the appropriate macro
+ * defined in H5Sprivate.h.
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5S_select_iter_get_seq_list(H5S_sel_iter_t *iter, size_t maxseq, size_t maxelmts,
+ size_t *nseq, size_t *nelmts, hsize_t *off, size_t *len)
+{
+ herr_t ret_value = FAIL; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* Sanity check */
+ HDassert(iter);
+
+ /* Call the selection type's get_seq_list function */
+ if((ret_value = (*iter->type->iter_get_seq_list)(iter, maxseq, maxelmts, nseq, nelmts, off, len)) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get selection sequence list")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S_select_iter_get_seq_list() */
+
+
/*--------------------------------------------------------------------------
NAME
H5S_select_iter_release
PURPOSE
Release a selection iterator's resources.
USAGE
- hssize_t H5S_select_iter_release(sel_iter)
+ herr_t H5S_select_iter_release(sel_iter)
H5S_sel_iter_t *sel_iter; IN: Selection iterator to query
RETURNS
The number of elements in selection on success, 0 on failure
@@ -1335,7 +1466,7 @@ H5S_select_iter_release(H5S_sel_iter_t *sel_iter)
ret_value = (*sel_iter->type->iter_release)(sel_iter);
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_select_iter_release() */
+} /* end H5S_select_iter_release() */
/*--------------------------------------------------------------------------
@@ -1375,7 +1506,7 @@ H5S_select_iterate(void *buf, const H5T_t *type, const H5S_t *space,
hsize_t *off = NULL; /* Array to store sequence offsets */
size_t *len = NULL; /* Array to store sequence lengths */
hssize_t nelmts; /* Number of elements in selection */
- hsize_t space_size[H5O_LAYOUT_NDIMS]; /* Dataspace size */
+ hsize_t space_size[H5S_MAX_RANK]; /* Dataspace size */
size_t max_elem; /* Maximum number of elements allowed in sequences */
size_t elmt_size; /* Datatype size */
unsigned ndims; /* Number of dimensions in dataspace */
@@ -1399,7 +1530,7 @@ H5S_select_iterate(void *buf, const H5T_t *type, const H5S_t *space,
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate selection iterator")
/* Initialize iterator */
- if(H5S_select_iter_init(iter, space, elmt_size) < 0)
+ if(H5S_select_iter_init(iter, 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 */
@@ -1413,7 +1544,7 @@ H5S_select_iterate(void *buf, const H5T_t *type, const H5S_t *space,
if(ndims > 0) {
/* Copy the size of the space */
HDassert(space->extent.size);
- HDmemcpy(space_size, space->extent.size, ndims * sizeof(hsize_t));
+ H5MM_memcpy(space_size, space->extent.size, ndims * sizeof(hsize_t));
} /* end if */
space_size[ndims] = elmt_size;
@@ -1433,7 +1564,7 @@ H5S_select_iterate(void *buf, const H5T_t *type, const H5S_t *space,
size_t curr_seq; /* Current sequence being worked on */
/* Get the sequences of bytes */
- if(H5S_SELECT_GET_SEQ_LIST(space, 0, iter, (size_t)H5D_IO_VECTOR_SIZE, max_elem, &nseq, &nelem, off, len) < 0)
+ if(H5S_SELECT_ITER_GET_SEQ_LIST(iter, (size_t)H5D_IO_VECTOR_SIZE, max_elem, &nseq, &nelem, off, len) < 0)
HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed")
/* Loop, while sequences left to process */
@@ -1449,7 +1580,7 @@ H5S_select_iterate(void *buf, const H5T_t *type, const H5S_t *space,
/* Loop, while bytes left in sequence */
while(curr_len > 0 && user_ret == 0) {
- hsize_t coords[H5O_LAYOUT_NDIMS]; /* Coordinates of element in dataspace */
+ hsize_t coords[H5S_MAX_RANK]; /* Coordinates of element in dataspace */
hsize_t tmp_off; /* Temporary offset within sequence */
uint8_t *loc; /* Current element location in buffer */
int i; /* Local Index variable */
@@ -1469,14 +1600,20 @@ H5S_select_iterate(void *buf, const H5T_t *type, const H5S_t *space,
/* Make the application callback */
user_ret = (op->u.app_op.op)(loc, op->u.app_op.type_id, ndims, coords, op_data);
break;
+
case H5S_SEL_ITER_OP_LIB:
/* Call the library's callback */
user_ret = (op->u.lib_op)(loc, type, ndims, coords, op_data);
break;
+
default:
HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unsupported op type")
} /* end switch */
+ /* Check for error return from iterator */
+ if(user_ret < 0)
+ HERROR(H5E_DATASPACE, H5E_CANTNEXT, "iteration operator failed");
+
/* Increment offset in dataspace */
curr_off += elmt_size;
@@ -1506,7 +1643,7 @@ done:
iter = H5FL_FREE(H5S_sel_iter_t, iter);
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5S_select_iterate() */
+} /* end H5S_select_iterate() */
/*--------------------------------------------------------------------------
@@ -1542,7 +1679,7 @@ H5Sget_select_type(hid_t space_id)
done:
FUNC_LEAVE_API(ret_value)
-} /* end H5Sget_select_type() */
+} /* end H5Sget_select_type() */
/*--------------------------------------------------------------------------
@@ -1564,7 +1701,7 @@ done:
pattern, don't call it directly, use the appropriate macro
defined in H5Sprivate.h.
--------------------------------------------------------------------------*/
-H5S_sel_type
+H5_ATTR_PURE H5S_sel_type
H5S_get_select_type(const H5S_t *space)
{
H5S_sel_type ret_value = H5S_SEL_ERROR; /* Return value */
@@ -1575,10 +1712,10 @@ H5S_get_select_type(const H5S_t *space)
HDassert(space);
/* Set return value */
- ret_value=H5S_GET_SELECT_TYPE(space);
+ ret_value = H5S_GET_SELECT_TYPE(space);
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5S_get_select_type() */
+} /* end H5S_get_select_type() */
/*--------------------------------------------------------------------------
@@ -1595,23 +1732,23 @@ H5S_get_select_type(const H5S_t *space)
DESCRIPTION
Checks to see if the current selection in the dataspaces are the same
dimensionality and shape.
+
This is primarily used for reading the entire selection in one swoop.
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
- Assumes that there is only a single "block" for hyperslab selections.
+ This routine participates in the "Inlining C function pointers" pattern,
+ don't call it directly, use the appropriate macro defined in H5Sprivate.h.
EXAMPLES
REVISION LOG
- Modified function to view identical shapes with different dimensions
- as being the same under some circumstances.
--------------------------------------------------------------------------*/
htri_t
H5S_select_shape_same(const H5S_t *space1, const H5S_t *space2)
{
H5S_sel_iter_t *iter_a = NULL; /* Selection a iteration info */
H5S_sel_iter_t *iter_b = NULL; /* Selection b iteration info */
- hbool_t iter_a_init = FALSE; /* Selection a iteration info has been initialized */
- hbool_t iter_b_init = FALSE; /* Selection b iteration info has been initialized */
- htri_t ret_value = TRUE; /* Return value */
+ hbool_t iter_a_init = FALSE; /* Selection a iteration info has been initialized */
+ hbool_t iter_b_init = FALSE; /* Selection b iteration info has been initialized */
+ htri_t ret_value = TRUE; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
@@ -1630,128 +1767,98 @@ H5S_select_shape_same(const H5S_t *space1, const H5S_t *space2)
const H5S_t *space_b; /* Dataspace with smaller rank */
unsigned space_a_rank; /* Number of dimensions of dataspace A */
unsigned space_b_rank; /* Number of dimensions of dataspace B */
+ int space_a_dim; /* Current dimension in dataspace A */
+ int space_b_dim; /* Current dimension in dataspace B */
+ H5S_sel_type sel_a_type; /* Selection type for dataspace A */
+ H5S_sel_type sel_b_type; /* Selection type for dataspace B */
- /* need to be able to handle spaces of different rank:
+ /* Need to be able to handle spaces of different rank:
*
* To simplify logic, let space_a point to the element of the set
- * {space1, space2} with the largest rank or space1 if the ranks
+ * {space1, space2} with the largest rank or space1 if the ranks
* are identical.
*
* Similarly, let space_b point to the element of {space1, space2}
* with the smallest rank, or space2 if they are identical.
*
- * Let: space_a_rank be the rank of space_a,
+ * Let: space_a_rank be the rank of space_a,
* space_b_rank be the rank of space_b,
- * delta_rank = space_a_rank - space_b_rank.
*
- * Set all this up below.
+ * Set all this up here.
*/
if(space1->extent.rank >= space2->extent.rank) {
space_a = space1;
- space_a_rank = space_a->extent.rank;
-
space_b = space2;
- space_b_rank = space_b->extent.rank;
} /* end if */
else {
space_a = space2;
- space_a_rank = space_a->extent.rank;
-
space_b = space1;
- space_b_rank = space_b->extent.rank;
} /* end else */
+ space_a_rank = space_a->extent.rank;
+ space_b_rank = space_b->extent.rank;
HDassert(space_a_rank >= space_b_rank);
HDassert(space_b_rank > 0);
- /* Check for different number of elements selected */
- if(H5S_GET_SELECT_NPOINTS(space_a) != H5S_GET_SELECT_NPOINTS(space_b))
- HGOTO_DONE(FALSE)
+ /* Get selection type for both dataspaces */
+ sel_a_type = H5S_GET_SELECT_TYPE(space_a);
+ sel_b_type = H5S_GET_SELECT_TYPE(space_b);
- /* Check for "easy" cases before getting into generalized block iteration code */
- if((H5S_GET_SELECT_TYPE(space_a) == H5S_SEL_ALL) && (H5S_GET_SELECT_TYPE(space_b) == H5S_SEL_ALL)) {
- hsize_t dims1[H5O_LAYOUT_NDIMS]; /* End point of selection block in dataspace #1 */
- hsize_t dims2[H5O_LAYOUT_NDIMS]; /* End point of selection block in dataspace #2 */
- int space_a_dim; /* Current dimension in dataspace A */
- int space_b_dim; /* Current dimension in dataspace B */
+ /* If selections aren't "none", compare their bounds */
+ if(sel_a_type != H5S_SEL_NONE && sel_b_type != H5S_SEL_NONE) {
+ hsize_t low_a[H5S_MAX_RANK]; /* Low bound of selection in dataspace a */
+ hsize_t low_b[H5S_MAX_RANK]; /* Low bound of selection in dataspace b */
+ hsize_t high_a[H5S_MAX_RANK]; /* High bound of selection in dataspace a */
+ hsize_t high_b[H5S_MAX_RANK]; /* High bound of selection in dataspace b */
- if(H5S_get_simple_extent_dims(space_a, dims1, NULL) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimensionality")
- if(H5S_get_simple_extent_dims(space_b, dims2, NULL) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimensionality")
+ /* Get low & high bounds for both dataspaces */
+ if(H5S_SELECT_BOUNDS(space_a, low_a, high_a) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get selection bounds for first dataspace")
+ if(H5S_SELECT_BOUNDS(space_b, low_b, high_b) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get selection bounds for second dataspace")
+ /* Check that the range between the low & high bounds are the same */
space_a_dim = (int)space_a_rank - 1;
space_b_dim = (int)space_b_rank - 1;
-
- /* recall that space_a_rank >= space_b_rank.
- *
- * In the following while loop, we test to see if space_a and space_b
- * have identical size in all dimensions they have in common.
- */
while(space_b_dim >= 0) {
- if(dims1[space_a_dim] != dims2[space_b_dim])
- HGOTO_DONE(FALSE)
+ /* Sanity check */
+ HDassert(low_a[space_a_dim] <= high_a[space_a_dim]);
+ HDassert(low_a[space_b_dim] <= high_a[space_b_dim]);
- space_a_dim--;
- space_b_dim--;
- } /* end while */
-
- /* Since we are selecting the entire space, we must also verify that space_a
- * has size 1 in all dimensions that it does not share with space_b.
- */
- while(space_a_dim >= 0) {
- if(dims1[space_a_dim] != 1)
- HGOTO_DONE(FALSE)
-
- space_a_dim--;
- } /* end while */
- } /* end if */
- else if((H5S_GET_SELECT_TYPE(space1) == H5S_SEL_NONE) || (H5S_GET_SELECT_TYPE(space2) == H5S_SEL_NONE)) {
- /* (Both must be, at this point, if one is) */
- HGOTO_DONE(TRUE)
- } /* end if */
- else if((H5S_GET_SELECT_TYPE(space_a) == H5S_SEL_HYPERSLABS && space_a->select.sel_info.hslab->diminfo_valid)
- && (H5S_GET_SELECT_TYPE(space_b) == H5S_SEL_HYPERSLABS && space_b->select.sel_info.hslab->diminfo_valid)) {
- int space_a_dim; /* Current dimension in dataspace A */
- int space_b_dim; /* Current dimension in dataspace B */
-
- space_a_dim = (int)space_a_rank - 1;
- space_b_dim = (int)space_b_rank - 1;
-
- /* check that the shapes are the same in the common dimensions, and that
- * block == 1 in all dimensions that appear only in space_a.
- */
- while(space_b_dim >= 0) {
- if(space_a->select.sel_info.hslab->opt_diminfo[space_a_dim].stride !=
- space_b->select.sel_info.hslab->opt_diminfo[space_b_dim].stride)
- HGOTO_DONE(FALSE)
-
- if(space_a->select.sel_info.hslab->opt_diminfo[space_a_dim].count !=
- space_b->select.sel_info.hslab->opt_diminfo[space_b_dim].count)
- HGOTO_DONE(FALSE)
-
- if(space_a->select.sel_info.hslab->opt_diminfo[space_a_dim].block !=
- space_b->select.sel_info.hslab->opt_diminfo[space_b_dim].block)
+ /* Verify that the ranges are the same */
+ if((high_a[space_a_dim] - low_a[space_a_dim])
+ != (high_b[space_b_dim] - low_b[space_b_dim]))
HGOTO_DONE(FALSE)
+ /* Go to next dimension */
space_a_dim--;
space_b_dim--;
} /* end while */
+ /* Check that the rest of the ranges in space a are "flat" */
while(space_a_dim >= 0) {
- if(space_a->select.sel_info.hslab->opt_diminfo[space_a_dim].block != 1)
+ /* Sanity check */
+ HDassert(low_a[space_a_dim] <= high_a[space_a_dim]);
+
+ /* This range should be flat to be the same in a lower dimension */
+ if(low_a[space_a_dim] != high_a[space_a_dim])
HGOTO_DONE(FALSE)
space_a_dim--;
} /* end while */
} /* end if */
- /* Iterate through all the blocks in the selection */
+
+ /* If the dataspaces have the same selection type, use the selection's
+ * shape_same operator.
+ */
+ if(sel_a_type == sel_b_type)
+ ret_value = (*space_a->select.type->shape_same)(space_a, space_b);
+ /* Otherwise, iterate through all the blocks in the selection */
else {
hsize_t start_a[H5S_MAX_RANK]; /* Start point of selection block in dataspace a */
hsize_t start_b[H5S_MAX_RANK]; /* Start point of selection block in dataspace b */
hsize_t end_a[H5S_MAX_RANK]; /* End point of selection block in dataspace a */
hsize_t end_b[H5S_MAX_RANK]; /* End point of selection block in dataspace b */
- hsize_t off_a[H5S_MAX_RANK]; /* Offset of selection a blocks */
- hsize_t off_b[H5S_MAX_RANK]; /* Offset of selection b blocks */
+ hssize_t offset[H5S_MAX_RANK]; /* Offset of selection b blocks relative to selection a blocks */
hbool_t first_block = TRUE; /* Flag to indicate the first block */
/* Allocate the selection iterators */
@@ -1765,17 +1872,15 @@ H5S_select_shape_same(const H5S_t *space1, const H5S_t *space2)
* that the selection iterator shouldn't be "flattened", since we
* aren't actually going to be doing I/O with the iterators.
*/
- if(H5S_select_iter_init(iter_a, space_a, (size_t)0) < 0)
+ if(H5S_select_iter_init(iter_a, space_a, (size_t)0, 0) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator a")
iter_a_init = TRUE;
- if(H5S_select_iter_init(iter_b, space_b, (size_t)0) < 0)
+ if(H5S_select_iter_init(iter_b, space_b, (size_t)0, 0) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator b")
iter_b_init = TRUE;
/* Iterate over all the blocks in each selection */
while(1) {
- int space_a_dim; /* Current dimension in dataspace A */
- int space_b_dim; /* Current dimension in dataspace B */
htri_t status_a, status_b; /* Status from next block checks */
/* Get the current block for each selection iterator */
@@ -1787,11 +1892,11 @@ H5S_select_shape_same(const H5S_t *space1, const H5S_t *space2)
space_a_dim = (int)space_a_rank - 1;
space_b_dim = (int)space_b_rank - 1;
- /* The first block only compares the sizes and sets the
- * relative offsets for later blocks
+ /* The first block only compares the sizes and sets the
+ * relative offsets for later blocks
*/
if(first_block) {
- /* If the block sizes in the common dimensions from
+ /* If the block sizes in the common dimensions from
* each selection don't match, get out
*/
while(space_b_dim >= 0) {
@@ -1800,23 +1905,19 @@ H5S_select_shape_same(const H5S_t *space1, const H5S_t *space2)
HGOTO_DONE(FALSE)
/* Set the relative locations of the selections */
- off_a[space_a_dim] = start_a[space_a_dim];
- off_b[space_b_dim] = start_b[space_b_dim];
+ offset[space_a_dim] = (hssize_t)start_b[space_b_dim] - (hssize_t)start_a[space_a_dim];
space_a_dim--;
space_b_dim--;
} /* end while */
- /* similarly, if the block size in any dimension that appears only
+ /* Similarly, if the block size in any dimension that appears only
* in space_a is not equal to 1, get out.
*/
while(space_a_dim >= 0) {
- if((end_a[space_a_dim] - start_a[space_a_dim]) != 0)
+ if(start_a[space_a_dim] != end_a[space_a_dim])
HGOTO_DONE(FALSE)
- /* Set the relative locations of the selections */
- off_a[space_a_dim] = start_a[space_a_dim];
-
space_a_dim--;
} /* end while */
@@ -1825,11 +1926,10 @@ H5S_select_shape_same(const H5S_t *space1, const H5S_t *space2)
} /* end if */
/* Check over the blocks for each selection */
else {
- /* for dimensions that space_a and space_b have in common: */
+ /* For dimensions that space_a and space_b have in common: */
while(space_b_dim >= 0) {
/* Check if the blocks are in the same relative location */
- if((start_a[space_a_dim] - off_a[space_a_dim]) !=
- (start_b[space_b_dim] - off_b[space_b_dim]))
+ if((hsize_t)((hssize_t)start_a[space_a_dim] + offset[space_a_dim]) != start_b[space_b_dim])
HGOTO_DONE(FALSE)
/* If the block sizes from each selection doesn't match, get out */
@@ -1844,7 +1944,7 @@ H5S_select_shape_same(const H5S_t *space1, const H5S_t *space2)
/* For dimensions that appear only in space_a: */
while(space_a_dim >= 0) {
/* If the block size isn't 1, get out */
- if((end_a[space_a_dim] - start_a[space_a_dim]) != 0)
+ if(start_a[space_a_dim] != end_a[space_a_dim])
HGOTO_DONE(FALSE)
space_a_dim--;
@@ -1886,7 +1986,165 @@ done:
iter_b = H5FL_FREE(H5S_sel_iter_t, iter_b);
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_select_shape_same() */
+} /* end H5S_select_shape_same() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Sselect_shape_same
+ PURPOSE
+ Check if two selections are the same shape
+ USAGE
+ htri_t H5Sselect_shape_same(space1_id, space2_id)
+ hid_t space1_id; IN: ID of 1st Dataspace pointer to compare
+ hid_t space2_id; IN: ID of 2nd Dataspace pointer to compare
+ RETURNS
+ TRUE/FALSE/FAIL
+ DESCRIPTION
+ Checks to see if the current selection in the dataspaces are the same
+ dimensionality and shape.
+ This is primarily used for reading the entire selection in one swoop.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+htri_t
+H5Sselect_shape_same(hid_t space1_id, hid_t space2_id)
+{
+ H5S_t *space1, *space2; /* Dataspaces to compare */
+ htri_t ret_value; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE2("t", "ii", space1_id, space2_id);
+
+ if(NULL == (space1 = (H5S_t *)H5I_object_verify(space1_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "not a dataspace")
+ if(NULL == (space2 = (H5S_t *)H5I_object_verify(space2_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "not a dataspace")
+
+ if((ret_value = H5S_select_shape_same(space1, space2)) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOMPARE, FAIL, "can't compare selections")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Sselect_shape_same() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S_select_intersect_block
+ PURPOSE
+ Check if current selection intersects with a block
+ USAGE
+ htri_t H5S_select_intersect_block(space, start, end)
+ const H5S_t *space; IN: Dataspace to compare
+ const hsize_t *start; IN: Starting coordinate of block
+ const hsize_t *end; IN: Opposite ("ending") coordinate of block
+ RETURNS
+ TRUE / FALSE / FAIL
+ DESCRIPTION
+ Checks to see if the current selection in the dataspace intersects with
+ the block given.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ Assumes that start & end block bounds are _inclusive_, so start == end
+ value OK.
+
+ This routine participates in the "Inlining C function pointers" pattern,
+ don't call it directly, use the appropriate macro defined in H5Sprivate.h.
+--------------------------------------------------------------------------*/
+htri_t
+H5S_select_intersect_block(const H5S_t *space, const hsize_t *start,
+ const hsize_t *end)
+{
+ htri_t ret_value = TRUE; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Check args */
+ HDassert(space);
+ HDassert(start);
+ HDassert(end);
+
+ /* If selections aren't "none", compare their bounds */
+ if(H5S_SEL_NONE != H5S_GET_SELECT_TYPE(space)) {
+ hsize_t low[H5S_MAX_RANK]; /* Low bound of selection in dataspace */
+ hsize_t high[H5S_MAX_RANK]; /* High bound of selection in dataspace */
+ unsigned u; /* Local index variable */
+
+ /* Get low & high bounds for dataspace selection */
+ if(H5S_SELECT_BOUNDS(space, low, high) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get selection bounds for dataspace")
+
+ /* Loop over selection bounds and block, checking for overlap */
+ for(u = 0; u < space->extent.rank; u++)
+ /* If selection bounds & block don't overlap, can leave now */
+ if(!H5S_RANGE_OVERLAP(low[u], high[u], start[u], end[u]))
+ HGOTO_DONE(FALSE)
+ } /* end if */
+
+ /* Call selection type's intersect routine */
+ if((ret_value = (*space->select.type->intersect_block)(space, start, end)) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOMPARE, FAIL, "can't intersect block with selection")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S_select_intersect_block() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Sselect_intersect_block
+ PURPOSE
+ Check if current selection intersects with a block
+ USAGE
+ htri_t H5Sselect_intersect_block(space_id, start, end)
+ hid_t space1_id; IN: ID of dataspace pointer to compare
+ const hsize_t *start; IN: Starting coordinate of block
+ const hsize_t *end; IN: Opposite ("ending") coordinate of block
+ RETURNS
+ TRUE / FALSE / FAIL
+ DESCRIPTION
+ Checks to see if the current selection in the dataspace intersects with
+ the block given.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ Assumes that start & end block bounds are _inclusive_, so start == end
+ value OK.
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+htri_t
+H5Sselect_intersect_block(hid_t space_id, const hsize_t *start, const hsize_t *end)
+{
+ H5S_t *space; /* Dataspace to query */
+ unsigned u; /* Local index value */
+ htri_t ret_value = FAIL; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE3("t", "i*h*h", space_id, start, end);
+
+ /* Check arguments */
+ if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "not a dataspace")
+ if(NULL == start)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "block start array pointer is NULL")
+ if(NULL == end)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "block end array pointer is NULL")
+
+ /* Range check start & end values */
+ for(u = 0; u < space->extent.rank; u++)
+ if(start[u] > end[u])
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "block start[%u] (%llu) > end[%u] (%llu)", u, (unsigned long long)start[u], u, (unsigned long long)end[u])
+
+ /* Call internal routine to do comparison */
+ if((ret_value = H5S_select_intersect_block(space, start, end)) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOMPARE, FAIL, "can't compare selection and block")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Sselect_intersect_block() */
/*--------------------------------------------------------------------------
@@ -1895,24 +2153,24 @@ done:
PURPOSE
Given a dataspace a of rank n with some selection, construct a new
- dataspace b of rank m (m != n), with the selection in a being
- topologically identical to that in b (as verified by
+ dataspace b of rank m (m != n), with the selection in a being
+ topologically identical to that in b (as verified by
H5S_select_shape_same().
- This function exists, as some I/O code chokes on topologically
- identical selections with different ranks. At least to begin
+ This function exists, as some I/O code chokes on topologically
+ identical selections with different ranks. At least to begin
with, we will deal with the issue by constructing projections
- of the memory dataspace with ranks equaling those of the file
+ of the memory dataspace with ranks equaling those of the file
dataspace.
- Note that if m > n, it is possible that the starting point in the
- buffer associated with the memory dataspace will have to be
+ Note that if m > n, it is possible that the starting point in the
+ buffer associated with the memory dataspace will have to be
adjusted to match the projected dataspace. If the buf parameter
is not NULL, the function must return an adjusted buffer base
address in *adj_buf_ptr.
USAGE
- htri_t H5S_select_construct_projection(base_space,
+ htri_t H5S_select_construct_projection(base_space,
new_space_ptr,
new_space_rank,
buf,
@@ -1921,30 +2179,30 @@ done:
H5S_t ** new_space_ptr; OUT: Ptr to location in which to return
the address of the projected space
int new_space_rank; IN: Rank of the projected space.
- const void * buf; IN: Base address of the buffer
+ const void * buf; IN: Base address of the buffer
associated with the base space.
May be NULL.
void ** adj_buf_ptr; OUT: If buf != NULL, store the base
- address of the section of buf
+ address of the section of buf
that is described by *new_space_ptr
in *adj_buf_ptr.
-
+
RETURNS
Non-negative on success/Negative on failure.
DESCRIPTION
- Construct a new dataspace and associated selection which is a
- projection of the supplied dataspace and associated selection into
+ Construct a new dataspace and associated selection which is a
+ projection of the supplied dataspace and associated selection into
the specified rank. Return it in *new_space_ptr.
- If buf is supplied, computes the base address of the projected
+ If buf is supplied, computes the base address of the projected
selection in buf, and stores the base address in *adj_buf_ptr.
-
+
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
- The selection in the supplied base_space has thickness 1 in all
+ The selection in the supplied base_space has thickness 1 in all
dimensions greater than new_space_rank. Note that here we count
- dimensions from the fastest changing coordinate to the slowest
+ dimensions from the fastest changing coordinate to the slowest
changing changing coordinate.
EXAMPLES
REVISION LOG
@@ -1990,28 +2248,28 @@ H5S_select_construct_projection(const H5S_t *base_space, H5S_t **new_space_ptr,
/* Create new scalar dataspace */
if(NULL == (new_space = H5S_create(H5S_SCALAR)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "unable to create scalar dataspace")
-
+
/* No need to register the dataspace(i.e. get an ID) as
* we will just be discarding it shortly.
*/
- /* Selection for the new space will be either all or
+ /* Selection for the new space will be either all or
* none, depending on whether the base space has 0 or
* 1 elements selected.
*
- * Observe that the base space can't have more than
+ * Observe that the base space can't have more than
* one selected element, since its selection has the
- * same shape as the file dataspace, and that data
+ * same shape as the file dataspace, and that data
* space is scalar.
*/
if(1 == npoints) {
/* Assuming that the selection in the base dataspace is not
- * empty, we must compute the offset of the selected item in
+ * empty, we must compute the offset of the selected item in
* the buffer associated with the base dataspace.
*
- * Since the new space rank is zero, we know that the
- * the base space must have rank at least 1 -- and
- * hence it is a simple dataspace. However, the
+ * Since the new space rank is zero, we know that the
+ * the base space must have rank at least 1 -- and
+ * hence it is a simple dataspace. However, the
* selection, may be either point, hyperspace, or all.
*
*/
@@ -2029,25 +2287,25 @@ H5S_select_construct_projection(const H5S_t *base_space, H5S_t **new_space_ptr,
hsize_t new_space_dims[H5S_MAX_RANK]; /* Current dimensions for new dataspace */
hsize_t new_space_maxdims[H5S_MAX_RANK];/* Maximum dimensions for new dataspace */
unsigned rank_diff; /* Difference in ranks */
-
+
/* Set up the dimensions of the new, projected dataspace.
*
- * How we do this depends on whether we are projecting up into
- * increased dimensions, or down into a reduced number of
+ * How we do this depends on whether we are projecting up into
+ * increased dimensions, or down into a reduced number of
* dimensions.
*
- * If we are projecting up (the first half of the following
- * if statement), we copy the dimensions of the base data
- * space into the fastest changing dimensions of the new
+ * If we are projecting up (the first half of the following
+ * if statement), we copy the dimensions of the base data
+ * space into the fastest changing dimensions of the new
* projected dataspace, and set the remaining dimensions to
* one.
*
* If we are projecting down (the second half of the following
- * if statement), we just copy the dimensions with the most
+ * if statement), we just copy the dimensions with the most
* quickly changing dimensions into the dims for the projected
* data set.
*
- * This works, because H5S_select_shape_same() will return
+ * This works, because H5S_select_shape_same() will return
* true on selections of different rank iff:
*
* 1) the selection in the lower rank dataspace matches that
@@ -2055,37 +2313,37 @@ H5S_select_construct_projection(const H5S_t *base_space, H5S_t **new_space_ptr,
* the larger rank dataspace, and
*
* 2) the selection has thickness 1 in all ranks that appear
- * only in the higher rank dataspace (i.e. those with
+ * only in the higher rank dataspace (i.e. those with
* more slowly changing indicies).
- */
+ */
if(new_space_rank > base_space_rank) {
hsize_t tmp_dim_size = 1; /* Temporary dimension value, for filling arrays */
- /* we must copy the dimensions of the base space into
+ /* we must copy the dimensions of the base space into
* the fastest changing dimensions of the new space,
* and set the remaining dimensions to 1
*/
rank_diff = new_space_rank - base_space_rank;
H5VM_array_fill(new_space_dims, &tmp_dim_size, sizeof(tmp_dim_size), rank_diff);
H5VM_array_fill(new_space_maxdims, &tmp_dim_size, sizeof(tmp_dim_size), rank_diff);
- HDmemcpy(&new_space_dims[rank_diff], base_space_dims, sizeof(new_space_dims[0]) * base_space_rank);
- HDmemcpy(&new_space_maxdims[rank_diff], base_space_maxdims, sizeof(new_space_maxdims[0]) * base_space_rank);
+ H5MM_memcpy(&new_space_dims[rank_diff], base_space_dims, sizeof(new_space_dims[0]) * base_space_rank);
+ H5MM_memcpy(&new_space_maxdims[rank_diff], base_space_maxdims, sizeof(new_space_maxdims[0]) * base_space_rank);
} /* end if */
else { /* new_space_rank < base_space_rank */
- /* we must copy the fastest changing dimension of the
+ /* we must copy the fastest changing dimension of the
* base space into the dimensions of the new space.
*/
rank_diff = base_space_rank - new_space_rank;
- HDmemcpy(new_space_dims, &base_space_dims[rank_diff], sizeof(new_space_dims[0]) * new_space_rank);
- HDmemcpy(new_space_maxdims, &base_space_maxdims[rank_diff], sizeof(new_space_maxdims[0]) * new_space_rank);
+ H5MM_memcpy(new_space_dims, &base_space_dims[rank_diff], sizeof(new_space_dims[0]) * new_space_rank);
+ H5MM_memcpy(new_space_maxdims, &base_space_maxdims[rank_diff], sizeof(new_space_maxdims[0]) * new_space_rank);
} /* end else */
- /* now have the new space rank and dimensions set up --
+ /* now have the new space rank and dimensions set up --
* so we can create the new simple dataspace.
*/
if(NULL == (new_space = H5S_create_simple(new_space_rank, new_space_dims, new_space_maxdims)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't create simple dataspace")
-
+
/* No need to register the dataspace(i.e. get an ID) as
* we will just be discarding it shortly.
*/
@@ -2096,22 +2354,22 @@ H5S_select_construct_projection(const H5S_t *base_space, H5S_t **new_space_ptr,
*/
if(H5S_SELECT_PROJECT_SIMPLE(base_space, new_space, &projected_space_element_offset) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "unable to project simple selection")
-
+
/* If we get this far, we have created the new dataspace, and projected
* the selection in the base dataspace into the new dataspace.
*
- * If the base dataspace is simple, check to see if the
- * offset_changed flag on the base selection has been set -- if so,
- * project the offset into the new dataspace and set the
+ * If the base dataspace is simple, check to see if the
+ * offset_changed flag on the base selection has been set -- if so,
+ * project the offset into the new dataspace and set the
* offset_changed flag.
*/
if(H5S_GET_EXTENT_TYPE(base_space) == H5S_SIMPLE && base_space->select.offset_changed) {
if(new_space_rank > base_space_rank) {
HDmemset(new_space->select.offset, 0, sizeof(new_space->select.offset[0]) * rank_diff);
- HDmemcpy(&new_space->select.offset[rank_diff], base_space->select.offset, sizeof(new_space->select.offset[0]) * base_space_rank);
+ H5MM_memcpy(&new_space->select.offset[rank_diff], base_space->select.offset, sizeof(new_space->select.offset[0]) * base_space_rank);
} /* end if */
else
- HDmemcpy(new_space->select.offset, &base_space->select.offset[rank_diff], sizeof(new_space->select.offset[0]) * new_space_rank);
+ H5MM_memcpy(new_space->select.offset, &base_space->select.offset[rank_diff], sizeof(new_space->select.offset[0]) * new_space_rank);
/* Propagate the offset changed flag into the new dataspace. */
new_space->select.offset_changed = TRUE;
@@ -2134,12 +2392,12 @@ H5S_select_construct_projection(const H5S_t *base_space, H5S_t **new_space_ptr,
* Since we can't do pointer arithmetic on void pointers, we first
* cast buf to a pointer to byte -- i.e. uint8_t.
*
- * We then multiply the projected space element offset we
- * calculated earlier by the supplied element size, add this
- * value to the type cast buf pointer, cast the result back
+ * We then multiply the projected space element offset we
+ * calculated earlier by the supplied element size, add this
+ * value to the type cast buf pointer, cast the result back
* to a pointer to void, and assign the result to *adj_buf_ptr.
*/
- *adj_buf_ptr = (const void *)(((const uint8_t *)buf) +
+ *adj_buf_ptr = (const void *)(((const uint8_t *)buf) +
((size_t)(projected_space_element_offset * element_size)));
} /* end if */
else
@@ -2154,7 +2412,7 @@ done:
HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace")
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_select_construct_projection() */
+} /* end H5S_select_construct_projection() */
/*--------------------------------------------------------------------------
@@ -2185,7 +2443,7 @@ herr_t
H5S_select_fill(const void *fill, size_t fill_size, const H5S_t *space, void *_buf)
{
H5S_sel_iter_t *iter = NULL; /* Selection iteration info */
- hbool_t iter_init = 0; /* Selection iteration info has been initialized */
+ hbool_t iter_init = FALSE; /* Selection iteration info has been initialized */
hsize_t *off = NULL; /* Array to store sequence offsets */
size_t *len = NULL; /* Array to store sequence lengths */
hssize_t nelmts; /* Number of elements in selection */
@@ -2205,9 +2463,9 @@ H5S_select_fill(const void *fill, size_t fill_size, const H5S_t *space, void *_b
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate selection iterator")
/* Initialize iterator */
- if(H5S_select_iter_init(iter, space, fill_size) < 0)
+ if(H5S_select_iter_init(iter, space, fill_size, 0) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator")
- iter_init = 1; /* Selection iteration info has been initialized */
+ iter_init = TRUE; /* Selection iteration info has been initialized */
/* Get the number of elements in selection */
if((nelmts = (hssize_t)H5S_GET_SELECT_NPOINTS(space)) < 0)
@@ -2229,7 +2487,7 @@ H5S_select_fill(const void *fill, size_t fill_size, const H5S_t *space, void *_b
size_t nelem; /* Number of elements used in sequences */
/* Get the sequences of bytes */
- if(H5S_SELECT_GET_SEQ_LIST(space, 0, iter, (size_t)H5D_IO_VECTOR_SIZE, max_elem, &nseq, &nelem, off, len) < 0)
+ if(H5S_SELECT_ITER_GET_SEQ_LIST(iter, (size_t)H5D_IO_VECTOR_SIZE, max_elem, &nseq, &nelem, off, len) < 0)
HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed")
/* Loop over sequences */
@@ -2262,7 +2520,7 @@ done:
iter = H5FL_FREE(H5S_sel_iter_t, iter);
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_select_fill() */
+} /* end H5S_select_fill() */
/*--------------------------------------------------------------------------
@@ -2289,7 +2547,7 @@ done:
src_intersect_space within the selection of src_space as a selection
within the selection of dst_space. The result is placed in the
selection of new_space_ptr.
-
+
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
EXAMPLES
@@ -2313,7 +2571,7 @@ H5S_select_project_intersection(const H5S_t *src_space, const H5S_t *dst_space,
/* Create new space, using dst extent. Start with "all" selection. */
if(NULL == (new_space = H5S_create(H5S_SIMPLE)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "unable to create output dataspace")
- if(H5S_extent_copy_real(&new_space->extent, &dst_space->extent, TRUE) < 0)
+ if(H5S__extent_copy_real(&new_space->extent, &dst_space->extent, TRUE) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy destination space extent")
/* If the intersecting space is "all", the intersection must be equal to the
@@ -2323,22 +2581,25 @@ H5S_select_project_intersection(const H5S_t *src_space, const H5S_t *dst_space,
if(H5S_select_copy(new_space, dst_space, FALSE) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy destination space selection")
} /* end if */
- /* If any of the spaces are "none", the projection must also be "none" */
- else if((src_intersect_space->select.type->type == H5S_SEL_NONE)
- || (src_space->select.type->type == H5S_SEL_NONE)
- || (dst_space->select.type->type == H5S_SEL_NONE)) {
+ /* If any of the selections contain no elements, the projection must be
+ * "none" */
+ else if((H5S_GET_SELECT_NPOINTS(src_intersect_space) == 0)
+ || (H5S_GET_SELECT_NPOINTS(src_space) == 0)
+ || (H5S_GET_SELECT_NPOINTS(dst_space) == 0)) {
/* Change to "none" selection */
if(H5S_select_none(new_space) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection")
} /* end if */
- /* If any of the spaces use point selection, fall back to general algorithm
- */
+ /* If any of the spaces use point selection, fall back to general algorithm */
else if((src_intersect_space->select.type->type == H5S_SEL_POINTS)
|| (src_space->select.type->type == H5S_SEL_POINTS)
|| (dst_space->select.type->type == H5S_SEL_POINTS))
HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "point selections not currently supported")
else {
HDassert(src_intersect_space->select.type->type == H5S_SEL_HYPERSLABS);
+ HDassert(src_space->select.type->type != H5S_SEL_NONE);
+ HDassert(dst_space->select.type->type != H5S_SEL_NONE);
+
/* Intersecting space is hyperslab selection. Call the hyperslab
* routine to project to another hyperslab selection. */
if(H5S__hyper_project_intersection(src_space, dst_space, src_intersect_space, new_space) < 0)
@@ -2355,7 +2616,7 @@ done:
HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace")
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_select_project_intersection() */
+} /* end H5S_select_project_intersection() */
/*--------------------------------------------------------------------------
@@ -2377,7 +2638,7 @@ done:
Removes any and all portions of space that are also present in
subtract_space. In essence, performs an A_NOT_B operation with the
two selections.
-
+
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
EXAMPLES
@@ -2404,12 +2665,13 @@ H5S_select_subtract(H5S_t *space, H5S_t *subtract_space)
if(H5S_select_none(space) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection")
} /* end if */
+ /* If either selection is a point selection, fail currently */
+ else if((subtract_space->select.type->type == H5S_SEL_POINTS) ||
+ (space->select.type->type == H5S_SEL_POINTS)) {
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "point selections not currently supported")
+ } /* end if */
else {
- /* Check for point selection in subtract_space, convert to hyperslab */
- if(subtract_space->select.type->type == H5S_SEL_POINTS)
- HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "point selections not currently supported")
-
- /* Check for point or all selection in space, convert to hyperslab */
+ /* Check for all selection in space, convert to hyperslab */
if(space->select.type->type == H5S_SEL_ALL) {
/* Convert current "all" selection to "real" hyperslab selection */
/* Then allow operation to proceed */
@@ -2431,19 +2693,231 @@ H5S_select_subtract(H5S_t *space, H5S_t *subtract_space)
if(H5S_select_hyperslab(space, H5S_SELECT_SET, tmp_start, tmp_stride, tmp_count, tmp_block) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't convert selection")
} /* end if */
- else if(space->select.type->type == H5S_SEL_POINTS)
- HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "point selections not currently supported")
HDassert(space->select.type->type == H5S_SEL_HYPERSLABS);
HDassert(subtract_space->select.type->type == H5S_SEL_HYPERSLABS);
/* Both spaces are now hyperslabs, perform the operation */
- if(H5S__hyper_subtract(space, subtract_space) < 0)
+ if(H5S__modify_select(space, H5S_SELECT_NOTB, subtract_space) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL, "can't subtract hyperslab")
} /* end else */
} /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_select_subtract() */
+} /* end H5S_select_subtract() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Ssel_iter_create
+ PURPOSE
+ Create a dataspace selection iterator for a dataspace's selection
+ USAGE
+ hid_t H5Ssel_iter_create(space)
+ hid_t space; IN: ID of the dataspace with selection to iterate over
+ RETURNS
+ Valid dataspace selection iterator ID on success, H5I_INVALID_HID on failure
+ DESCRIPTION
+ Creates a selection iterator and initializes it to start at the first
+ element selected in the dataspace.
+ PROGRAMMER
+ Quincey Koziol - February 11, 2019
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+hid_t
+H5Ssel_iter_create(hid_t space_id, size_t elmt_size, unsigned flags)
+{
+ H5S_t *space; /* Dataspace with selection to iterate over */
+ H5S_sel_iter_t *sel_iter; /* Selection iterator created */
+ hid_t ret_value; /* Return value */
+
+ FUNC_ENTER_API(H5I_INVALID_HID)
+ H5TRACE3("i", "izIu", space_id, elmt_size, flags);
+
+ /* Check args */
+ if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, H5I_INVALID_HID, "not a dataspace")
+ if(elmt_size == 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, H5I_INVALID_HID, "element size must be greater than 0")
+ if(flags != (flags & H5S_SEL_ITER_ALL_PUBLIC_FLAGS))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, H5I_INVALID_HID, "invalid selection iterator flag")
+
+ /* Allocate the iterator */
+ if(NULL == (sel_iter = H5FL_MALLOC(H5S_sel_iter_t)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, H5I_INVALID_HID, "can't allocate selection iterator")
+
+ /* Add flag to indicate that this iterator is from an API call */
+ flags |= H5S_SEL_ITER_API_CALL;
+
+ /* Initialize the selection iterator */
+ if(H5S_select_iter_init(sel_iter, space, elmt_size, flags) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, H5I_INVALID_HID, "unable to initialize selection iterator")
+
+ /* Atomize */
+ if((ret_value = H5I_register(H5I_SPACE_SEL_ITER, sel_iter, TRUE)) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register dataspace selection iterator atom")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Ssel_iter_create() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Ssel_iter_get_seq_list
+ PURPOSE
+ Retrieve a list of offset / length sequences for the elements in an iterator
+ USAGE
+ herr_t H5Ssel_iter_get_seq_list(sel_iter_id, maxseq, maxbytes, nseq, nbytes, off, len)
+ hid_t sel_iter_id; IN: ID of the dataspace selection iterator to retrieve sequence from
+ size_t maxseq; IN: Max. # of sequences to retrieve
+ size_t maxbytes; IN: Max. # of bytes to retrieve in sequences
+ size_t *nseq; OUT: # of sequences retrieved
+ size_t *nbytes; OUT: # of bytes retrieved, in all sequences
+ hsize_t *off; OUT: Array of sequence offsets
+ size_t *len; OUT: Array of sequence lengths
+ RETURNS
+ Non-negative on success / Negative on failure
+ DESCRIPTION
+ Retrieve a list of offset / length pairs (a list of "sequences") matching
+ the selected elements for an iterator, according to the iteration order for
+ the iterator. The lengths returned are in _bytes_, not elements.
+
+ Note that the iteration order for "all" and "hyperslab" selections is
+ row-major (i.e. "C-ordered"), but the iteration order for "point"
+ selections is "in order selected", unless the H5S_SEL_ITER_GET_SEQ_LIST_SORTED
+ flag is passed to H5Sset_iter_create for a point selection.
+
+ MAXSEQ and MAXBYTES specify the most sequences or bytes possible to
+ place into the OFF and LEN arrays. *NSEQ and *NBYTES return the actual
+ number of sequences and bytes put into the arrays.
+
+ Each call to H5Ssel_iter_get_seq_list() will retrieve the next set
+ of sequences for the selection being iterated over.
+
+ The total number of bytes possible to retrieve from a selection iterator
+ is the 'elmt_size' passed to H5Ssel_iter_create multiplied by the number
+ of elements selected in the dataspace the iterator was created from
+ (which can be retrieved with H5Sget_select_npoints). When there are no
+ further sequences of elements to retrieve, calls to this routine will
+ set *NSEQ and *NBYTES to zero.
+ PROGRAMMER
+ Quincey Koziol - February 11, 2019
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5Ssel_iter_get_seq_list(hid_t sel_iter_id, size_t maxseq, size_t maxbytes,
+ size_t *nseq, size_t *nbytes, hsize_t *off, size_t *len)
+{
+ H5S_sel_iter_t *sel_iter; /* Dataspace selection iterator to operate on */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE7("e", "izz*z*z*h*z", sel_iter_id, maxseq, maxbytes, nseq, nbytes, off,
+ len);
+
+ /* Check args */
+ if(NULL == (sel_iter = (H5S_sel_iter_t *)H5I_object_verify(sel_iter_id, H5I_SPACE_SEL_ITER)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "not a dataspace selection iterator")
+ if(NULL == nseq)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "'nseq' pointer is NULL")
+ if(NULL == nbytes)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "'nbytes' pointer is NULL")
+ if(NULL == off)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "offset array pointer is NULL")
+ if(NULL == len)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "length array pointer is NULL")
+
+ /* Get the sequences of bytes */
+ if(maxseq > 0 && maxbytes > 0) {
+ if(H5S_SELECT_ITER_GET_SEQ_LIST(sel_iter, maxseq, maxbytes, nseq, nbytes, off, len) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "sequence length generation failed")
+ } /* end if */
+ else
+ *nseq = *nbytes = 0;
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Ssel_iter_get_seq_list() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5S_sel_iter_close
+ *
+ * Purpose: Releases a dataspace selection iterator and its memory.
+ *
+ * Return: Non-negative on success / Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Monday, February 11, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5S_sel_iter_close(H5S_sel_iter_t *sel_iter)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check */
+ HDassert(sel_iter);
+
+ /* Call selection type-specific release routine */
+ if(H5S_SELECT_ITER_RELEASE(sel_iter) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "problem releasing a selection iterator's type-specific info")
+
+ /* Release the structure */
+ sel_iter = H5FL_FREE(H5S_sel_iter_t, sel_iter);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S_sel_iter_close() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Ssel_iter_close
+ PURPOSE
+ Close a dataspace selection iterator
+ USAGE
+ herr_t H5Ssel_iter_close(sel_iter_id)
+ hid_t sel_iter_id; IN: ID of the dataspace selection iterator to close
+ RETURNS
+ Non-negative on success / Negative on failure
+ DESCRIPTION
+ Close a dataspace selection iterator, releasing its state.
+ PROGRAMMER
+ Quincey Koziol - February 11, 2019
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5Ssel_iter_close(hid_t sel_iter_id)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE1("e", "i", sel_iter_id);
+
+ /* Check args */
+ if(NULL == H5I_object_verify(sel_iter_id, H5I_SPACE_SEL_ITER))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "not a dataspace selection iterator")
+
+ /* When the reference count reaches zero the resources are freed */
+ if(H5I_dec_app_ref(sel_iter_id) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDEC, FAIL, "problem freeing dataspace selection iterator ID")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Ssel_iter_close() */
diff --git a/src/H5Stest.c b/src/H5Stest.c
index a7bee2b..b61b6bf 100644
--- a/src/H5Stest.c
+++ b/src/H5Stest.c
@@ -17,70 +17,118 @@
* Purpose: Dataspace selection testing functions.
*/
+/****************/
+/* Module Setup */
+/****************/
+
#include "H5Smodule.h" /* This source code file is part of the H5S module */
#define H5S_TESTING /*suppress warning about H5S testing funcs*/
+/***********/
+/* Headers */
+/***********/
#include "H5private.h" /* Generic Functions */
#include "H5Eprivate.h" /* Error handling */
#include "H5Iprivate.h" /* IDs */
#include "H5Spkg.h" /* Dataspaces */
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
/*--------------------------------------------------------------------------
NAME
- H5S_select_shape_same_test
+ H5S__get_rebuild_status_test
PURPOSE
- Determine if two dataspace selections are the same shape
+ Determine the status of the diminfo_valid field (whether we know the
+ selection information for an equivalent single hyperslab selection)
+ before and after calling H5S__hyper_rebuild.
USAGE
- htri_t H5S_select_shape_same_test(sid1, sid2)
- hid_t sid1; IN: 1st dataspace to compare
- hid_t sid2; IN: 2nd dataspace to compare
+ herr_t H5S__get_rebuild_status_test(space_id, status1, status2)
+ hid_t space_id; IN: dataspace id
+ H5S_diminfo_valid_t *status1; OUT: status before calling
+ H5S__hyper_rebuild
+ H5S_diminfo_valid_t *status2; OUT: status after calling
+ H5S__hyper_rebuild
RETURNS
- Non-negative TRUE/FALSE on success, negative on failure
+ Non-negative on success, negative on failure
DESCRIPTION
- Checks to see if the current selection in the dataspaces are the same
- dimensionality and shape.
+ Query the status of rebuilding the hyperslab
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
DO NOT USE THIS FUNCTION FOR ANYTHING EXCEPT TESTING
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-htri_t
-H5S_select_shape_same_test(hid_t sid1, hid_t sid2)
+herr_t
+H5S__get_rebuild_status_test(hid_t space_id, H5S_diminfo_valid_t *status1,
+ H5S_diminfo_valid_t *status2)
{
- H5S_t *space1; /* Pointer to 1st dataspace */
- H5S_t *space2; /* Pointer to 2nd dataspace */
- htri_t ret_value = FAIL; /* Return value */
+ H5S_t *space; /* Pointer to 1st dataspace */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(FAIL)
+ FUNC_ENTER_PACKAGE
- /* Get dataspace structures */
- if(NULL == (space1 = (H5S_t *)H5I_object_verify(sid1, H5I_DATASPACE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
- if(NULL == (space2 = (H5S_t *)H5I_object_verify(sid2, H5I_DATASPACE)))
+ HDassert(status1);
+ HDassert(status2);
+
+ /* Get dataspace structures */
+ if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
- /* Check if the dataspace selections are the same shape */
- if((ret_value = H5S_select_shape_same(space1, space2)) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOMPARE, FAIL, "unable to compare dataspace selections")
+ *status1 = space->select.sel_info.hslab->diminfo_valid;
+
+ /* Fully rebuild diminfo, if necessary */
+ if(*status1 == H5S_DIMINFO_VALID_NO)
+ H5S__hyper_rebuild(space);
+
+ *status2 = space->select.sel_info.hslab->diminfo_valid;
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_select_shape_same_test() */
+} /* H5S__get_rebuild_status_test() */
/*--------------------------------------------------------------------------
NAME
- H5S_get_rebuild_status_test
+ H5S__get_diminfo_status_test
PURPOSE
- Determine the status of hyperslab rebuild
+ Determine the status of the diminfo_valid field (whether we know the
+ selection information for an equivalent single hyperslab selection)
USAGE
- htri_t H5S_inquiry_rebuild_status(hid_t space_id)
+ herr_t H5S__get_diminfo_status_test(space_id, status)
hid_t space_id; IN: dataspace id
+ H5S_diminfo_valid_t *status; OUT: status of diminfo_valid
RETURNS
- Non-negative TRUE/FALSE on success, negative on failure
+ Non-negative on success, negative on failure
DESCRIPTION
Query the status of rebuilding the hyperslab
GLOBAL VARIABLES
@@ -89,21 +137,234 @@ done:
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
+herr_t
+H5S__get_diminfo_status_test(hid_t space_id, H5S_diminfo_valid_t *status)
+{
+ H5S_t *space; /* Pointer to 1st dataspace */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ HDassert(status);
+
+ /* Get dataspace structures */
+ if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
+
+ *status = space->select.sel_info.hslab->diminfo_valid;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5S__get_diminfo_status_test() */
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S__check_spans_tail_ptr
+ PURPOSE
+ Determine if the tail pointer of the spans are correctly set
+ USAGE
+ herr_t H5S__check_spans_tail_ptr(span_lst)
+ const H5S_hyper_span_info_t *span_lst; IN: the spans to check for taill pointers
+ RETURNS
+ SUCCEED/FAIL
+ DESCRIPTION
+ Checks to see if the current selection in the dataspaces has tail pointers of each
+ dimension correctly set.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ Only check the hyperslab selection
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static herr_t
+H5S__check_spans_tail_ptr(const H5S_hyper_span_info_t *span_lst)
+{
+ H5S_hyper_span_t *cur_elem;
+ H5S_hyper_span_t *actual_tail = NULL;
+ htri_t ret_value = TRUE; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ HDassert(span_lst);
+
+ cur_elem = span_lst->head;
+ while(cur_elem) {
+ actual_tail = cur_elem;
+
+ /* check the next dimension of lower order */
+ if(NULL != cur_elem->down)
+ if((ret_value = H5S__check_spans_tail_ptr(cur_elem->down)) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_INCONSISTENTSTATE, FAIL, "the seletion has inconsistent tail pointers")
+
+ cur_elem = cur_elem->next;
+ } /* end while */
+ if(actual_tail != span_lst->tail)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_INCONSISTENTSTATE, FAIL, "the seletion has inconsistent tail pointers")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5S__check_spans_tail_ptr */
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S__check_points_tail_ptr
+ PURPOSE
+ Determine if the tail pointer of the points list are correctly set
+ USAGE
+ herr_t H5S__check_points_tail_ptr(pnt_lst)
+ const H5S_pnt_list_t *pnt_lst; IN: the points list to check for taill pointers
+ RETURNS
+ SUCCEED/FAIL
+ DESCRIPTION
+ Checks to see if the current selection in the dataspaces has tail pointers correctly set.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ Only check the points selection
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static herr_t
+H5S__check_points_tail_ptr(const H5S_pnt_list_t *pnt_lst)
+{
+ H5S_pnt_node_t *cur_elem;
+ H5S_pnt_node_t *actual_tail = NULL;
+ htri_t ret_value = TRUE; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ HDassert(pnt_lst);
+
+ cur_elem = pnt_lst->head;
+ while(cur_elem) {
+ actual_tail = cur_elem;
+ cur_elem = cur_elem->next;
+ } /* end while */
+ if(actual_tail != pnt_lst->tail)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_INCONSISTENTSTATE, FAIL, "the seletion has inconsistent tail pointers")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5S__check_points_tail_ptr */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S__check_internal_consistency
+ PURPOSE
+ Determine if internal data structures are consistent
+ USAGE
+ herr_t H5S__check_internal_consistency(space)
+ const H5S_t *space; IN: 1st Dataspace pointer to compare
+ RETURNS
+ SUCCEED/FAIL
+ DESCRIPTION
+ Checks to see if the current selection in the dataspaces has consistent
+ state of internal data structure.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ Currently only check the hyperslab selection
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static herr_t
+H5S__check_internal_consistency(const H5S_t *space)
+{
+ hsize_t low_bounds[H5S_MAX_RANK];
+ hsize_t high_bounds[H5S_MAX_RANK];
+ unsigned u;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check args */
+ HDassert(space);
+
+ if(space->select.type->type == H5S_SEL_NONE)
+ HGOTO_DONE(ret_value);
+
+ /* Initialize the inputs */
+ for(u = 0; u < space->extent.rank; u++) {
+ low_bounds[u] = HSIZET_MAX;
+ high_bounds[u] = 0;
+ } /* end for */
+
+ /* Check the bound box */
+ if(H5S_get_select_bounds(space, low_bounds, high_bounds) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_INCONSISTENTSTATE, FAIL, "the bound box could not be retrieved")
+
+ if(space->select.type->type == H5S_SEL_HYPERSLABS) {
+ H5S_hyper_sel_t *hslab = space->select.sel_info.hslab;
+
+ if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) {
+ for(u = 0; u < space->extent.rank; u++) {
+ if((hsize_t)((hssize_t)hslab->diminfo.low_bounds[u] + space->select.offset[u]) != low_bounds[u])
+ HGOTO_ERROR(H5E_DATASPACE, H5E_INCONSISTENTSTATE, FAIL, "the lower bound box of the selection is inconsistent")
+ if((hsize_t)((hssize_t)hslab->diminfo.high_bounds[u] + space->select.offset[u]) != high_bounds[u])
+ HGOTO_ERROR(H5E_DATASPACE, H5E_INCONSISTENTSTATE, FAIL, "the higher bound box of the selection is inconsistent")
+ } /* end for */
+ } /* end if */
+ else {
+ for(u = 0; u < space->extent.rank; u++) {
+ if((hsize_t)((hssize_t)hslab->span_lst->low_bounds[u] + space->select.offset[u]) != low_bounds[u])
+ HGOTO_ERROR(H5E_DATASPACE, H5E_INCONSISTENTSTATE, FAIL, "the lower bound box of the selection is inconsistent")
+ if((hsize_t)((hssize_t)hslab->span_lst->high_bounds[u] + space->select.offset[u]) != high_bounds[u])
+ HGOTO_ERROR(H5E_DATASPACE, H5E_INCONSISTENTSTATE, FAIL, "the higher bound box of the selection is inconsistent")
+ } /* end for */
+ } /* end else */
+
+ /* check the tail pointer */
+ if((NULL != hslab) && (NULL != hslab->span_lst))
+ if(H5S__check_spans_tail_ptr(hslab->span_lst) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_INCONSISTENTSTATE, FAIL, "the seletion has inconsistent tail pointers")
+ } /* end if */
+ else if(space->select.type->type == H5S_SEL_POINTS) {
+ H5S_pnt_list_t *pnt_lst = space->select.sel_info.pnt_lst;
+
+ if(NULL != pnt_lst)
+ if(H5S__check_points_tail_ptr(pnt_lst) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_INCONSISTENTSTATE, FAIL, "the seletion has inconsistent tail pointers")
+ } /* end else-if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5S__check_internal_consistency */
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S__internal_consistency_test
+ PURPOSE
+ Determine if states of internal data structures are consistent
+ USAGE
+ htri_t H5S__internal_consistency_test(hid_t space_id)
+ hid_t space_id; IN: dataspace id
+ RETURNS
+ Non-negative TRUE/FALSE on success, negative on failure
+ DESCRIPTION
+ Check the states of internal data structures of the hyperslab, and see
+ whether they are consistent or not
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ DO NOT USE THIS FUNCTION FOR ANYTHING EXCEPT TESTING
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
htri_t
-H5S_get_rebuild_status_test(hid_t space_id)
+H5S__internal_consistency_test(hid_t space_id)
{
H5S_t *space; /* Pointer to 1st dataspace */
- htri_t ret_value = FAIL; /* Return value */
+ htri_t ret_value = TRUE; /* Return value */
- FUNC_ENTER_NOAPI(FAIL)
+ FUNC_ENTER_PACKAGE
/* Get dataspace structures */
if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
- ret_value = (htri_t)space->select.sel_info.hslab->diminfo_valid;
+ /* Check if the dataspace selections are the same shape */
+ if(FAIL == H5S__check_internal_consistency(space))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_INCONSISTENTSTATE, FAIL, "The dataspace has inconsistent internal state")
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_get_rebuild_status_test() */
+} /* H5S__internal_consistency_test() */
diff --git a/src/H5T.c b/src/H5T.c
index 62fe128..d1cc68c 100644
--- a/src/H5T.c
+++ b/src/H5T.c
@@ -41,6 +41,7 @@
#include "H5MMprivate.h" /* Memory management */
#include "H5Pprivate.h" /* Property lists */
#include "H5Tpkg.h" /* Datatypes */
+#include "H5VLprivate.h" /* Virtual Object Layer */
/****************/
@@ -225,18 +226,34 @@
#define H5T_INIT_TYPE_REF_COMMON { \
H5T_INIT_TYPE_ALLOC_COMMON(H5T_REFERENCE) \
H5T_INIT_TYPE_NUM_COMMON(H5T_ORDER_NONE) \
+ dt->shared->force_conv = TRUE; \
+ dt->shared->u.atomic.u.r.f = NULL; \
+ dt->shared->u.atomic.u.r.loc = H5T_LOC_BADLOC; \
+ dt->shared->u.atomic.u.r.cls = NULL; \
}
#define H5T_INIT_TYPE_OBJREF_CORE { \
H5T_INIT_TYPE_REF_COMMON \
- dt->shared->force_conv = TRUE; \
- dt->shared->u.atomic.u.r.rtype = H5R_OBJECT; \
- dt->shared->u.atomic.u.r.loc = H5T_LOC_MEMORY; \
+ dt->shared->u.atomic.u.r.rtype = H5R_OBJECT1; \
+ dt->shared->u.atomic.u.r.opaque = FALSE; \
+ dt->shared->u.atomic.u.r.version = 0; \
}
#define H5T_INIT_TYPE_REGREF_CORE { \
H5T_INIT_TYPE_REF_COMMON \
- dt->shared->u.atomic.u.r.rtype = H5R_DATASET_REGION; \
+ dt->shared->u.atomic.u.r.rtype = H5R_DATASET_REGION1; \
+ dt->shared->u.atomic.u.r.opaque = FALSE; \
+ dt->shared->u.atomic.u.r.version = 0; \
+}
+
+/* rtype value is only used as a placeholder to differentiate the type from
+ * other types, any opaque (i.e. "new") reference type could be used.
+ */
+#define H5T_INIT_TYPE_REF_CORE { \
+ H5T_INIT_TYPE_REF_COMMON \
+ dt->shared->u.atomic.u.r.rtype = H5R_OBJECT2; \
+ dt->shared->u.atomic.u.r.opaque = TRUE; \
+ dt->shared->u.atomic.u.r.version = H5R_ENCODE_VERSION; \
}
/* Define the code templates for the "SIZE_TMPL" in the H5T_INIT_TYPE macro */
@@ -294,6 +311,7 @@ static htri_t H5T__compiler_conv(H5T_t *src, H5T_t *dst);
static herr_t H5T__set_size(H5T_t *dt, size_t size);
static herr_t H5T__close_cb(H5T_t *dt);
static H5T_path_t *H5T__path_find_real(const H5T_t *src, const H5T_t *dst, const char *name, H5T_conv_func_t *conv);
+static hbool_t H5T__detect_vlen_ref(const H5T_t *dt);
/*****************************/
@@ -352,6 +370,7 @@ hid_t H5T_STD_B64BE_g = FAIL;
hid_t H5T_STD_B64LE_g = FAIL;
hid_t H5T_STD_REF_OBJ_g = FAIL;
hid_t H5T_STD_REF_DSETREG_g = FAIL;
+hid_t H5T_STD_REF_g = FAIL;
hid_t H5T_UNIX_D32BE_g = FAIL;
hid_t H5T_UNIX_D32LE_g = FAIL;
@@ -442,6 +461,7 @@ size_t H5T_POINTER_COMP_ALIGN_g = 0;
size_t H5T_HVL_COMP_ALIGN_g = 0;
size_t H5T_HOBJREF_COMP_ALIGN_g = 0;
size_t H5T_HDSETREGREF_COMP_ALIGN_g = 0;
+size_t H5T_REF_COMP_ALIGN_g = 0;
/*
* Alignment constraints for native types. These are initialized at run time
@@ -511,6 +531,8 @@ H5FL_DEFINE(H5T_shared_t);
const unsigned H5O_dtype_ver_bounds[] = {
H5O_DTYPE_VERSION_1, /* H5F_LIBVER_EARLIEST */
H5O_DTYPE_VERSION_3, /* H5F_LIBVER_V18 */
+ H5O_DTYPE_VERSION_3, /* H5F_LIBVER_V110 */
+ H5O_DTYPE_VERSION_3, /* H5F_LIBVER_V112 */
H5O_DTYPE_VERSION_LATEST /* H5F_LIBVER_LATEST */
};
@@ -547,7 +569,7 @@ static const H5I_class_t H5I_DATATYPE_CLS[1] = {{
static hbool_t H5T_top_package_initialize_s = FALSE;
-
+
/*-------------------------------------------------------------------------
* Function: H5T_init
*
@@ -573,7 +595,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T_init() */
-
+
/*-------------------------------------------------------------------------
* Function: H5T__init_inf
*
@@ -686,7 +708,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T__init_inf() */
-
+
/*--------------------------------------------------------------------------
NAME
H5T__init_package -- Initialize interface-specific information
@@ -733,7 +755,9 @@ H5T__init_package(void)
H5T_t *enum_type=NULL; /* Datatype structure for enum objects */
H5T_t *vlen=NULL; /* Datatype structure for vlen objects */
H5T_t *array=NULL; /* Datatype structure for array objects */
- H5T_t *objref=NULL; /* Datatype structure for object reference objects */
+ H5T_t *objref=NULL; /* Datatype structure for deprecated reference objects */
+ H5T_t *regref=NULL; /* Datatype structure for deprecated region references */
+ H5T_t *ref=NULL; /* Datatype structure for opaque references */
hsize_t dim[1]={1}; /* Dimension info for array datatype */
herr_t status;
hbool_t copied_dtype = TRUE; /* Flag to indicate whether datatype was copied or allocated (for error cleanup) */
@@ -985,12 +1009,23 @@ H5T__init_package(void)
*------------------------------------------------------------
*/
- /* Object reference (i.e. object header address in file) */
- H5T_INIT_TYPE(OBJREF, H5T_STD_REF_OBJ_g, ALLOC, -, SET, H5R_OBJ_REF_BUF_SIZE)
+ /* Deprecated object reference type */
+ H5T_INIT_TYPE(OBJREF, H5T_STD_REF_OBJ_g, ALLOC, -, NOSET, -)
+ if(H5T_set_loc(dt, NULL, H5T_LOC_MEMORY) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location")
objref = dt; /* Keep type for later */
- /* Dataset Region reference (i.e. selection inside a dataset) */
- H5T_INIT_TYPE(REGREF, H5T_STD_REF_DSETREG_g, ALLOC, -, SET, H5R_DSET_REG_REF_BUF_SIZE)
+ /* Deprecated region reference type */
+ H5T_INIT_TYPE(REGREF, H5T_STD_REF_DSETREG_g, ALLOC, -, NOSET, -)
+ if(H5T_set_loc(dt, NULL, H5T_LOC_MEMORY) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location")
+ regref = dt; /* Keep type for later */
+
+ /* Opaque reference type */
+ H5T_INIT_TYPE(REF, H5T_STD_REF_g, ALLOC, -, NOSET, -)
+ if(H5T_set_loc(dt, NULL, H5T_LOC_MEMORY) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location")
+ ref = dt; /* Keep type for later */
/*
* Register conversion functions beginning with the most general and
@@ -1025,7 +1060,11 @@ H5T__init_package(void)
status |= H5T__register_int(H5T_PERS_SOFT, "enum_f", enum_type, floatpt, H5T__conv_enum_numeric);
status |= H5T__register_int(H5T_PERS_SOFT, "vlen", vlen, vlen, H5T__conv_vlen);
status |= H5T__register_int(H5T_PERS_SOFT, "array", array, array, H5T__conv_array);
- status |= H5T__register_int(H5T_PERS_SOFT, "objref", objref, objref, H5T__conv_order_opt);
+ status |= H5T__register_int(H5T_PERS_SOFT, "objref", objref, objref, H5T__conv_noop);
+ status |= H5T__register_int(H5T_PERS_SOFT, "regref", regref, regref, H5T__conv_noop);
+ status |= H5T__register_int(H5T_PERS_SOFT, "ref", ref, ref, H5T__conv_ref);
+ status |= H5T__register_int(H5T_PERS_SOFT, "objref_ref", objref, ref, H5T__conv_ref);
+ status |= H5T__register_int(H5T_PERS_SOFT, "regref_ref", regref, ref, H5T__conv_ref);
/*
* Native conversions should be listed last since we can use hardware to
@@ -1310,7 +1349,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T__init_package() */
-
+
/*-------------------------------------------------------------------------
* Function: H5T__unlock_cb
*
@@ -1343,7 +1382,7 @@ H5T__unlock_cb(void *_dt, hid_t H5_ATTR_UNUSED id, void *_udata)
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5T__unlock_cb() */
-
+
/*-------------------------------------------------------------------------
* Function: H5T_top_term_package
*
@@ -1395,7 +1434,7 @@ H5T_top_term_package(void)
if((path->conv.u.lib_func)((hid_t)FAIL, (hid_t)FAIL, &(path->cdata), (size_t)0, (size_t)0, (size_t)0, NULL, NULL) < 0) {
#ifdef H5T_DEBUG
if (H5DEBUG(T)) {
- fprintf(H5DEBUG(T), "H5T: conversion function "
+ HDfprintf(H5DEBUG(T), "H5T: conversion function "
"0x%08lx failed to free private data for "
"%s (ignored)\n",
(unsigned long)(path->conv.u.lib_func), path->name);
@@ -1469,6 +1508,7 @@ H5T_top_term_package(void)
H5T_STD_B64LE_g = FAIL;
H5T_STD_REF_OBJ_g = FAIL;
H5T_STD_REF_DSETREG_g = FAIL;
+ H5T_STD_REF_g = FAIL;
H5T_UNIX_D32BE_g = FAIL;
H5T_UNIX_D32LE_g = FAIL;
@@ -1544,7 +1584,7 @@ H5T_top_term_package(void)
FUNC_LEAVE_NOAPI(n)
} /* end H5T_top_term_package() */
-
+
/*-------------------------------------------------------------------------
* Function: H5T_term_package
*
@@ -1586,7 +1626,7 @@ H5T_term_package(void)
FUNC_LEAVE_NOAPI(n)
} /* end H5T_term_package() */
-
+
/*-------------------------------------------------------------------------
* Function: H5T__close_cb
*
@@ -1607,15 +1647,29 @@ H5T__close_cb(H5T_t *dt)
HDassert(dt);
HDassert(dt->shared);
+ /* If this datatype is VOL-managed (i.e.: has a VOL object),
+ * close it through the VOL connector.
+ */
+ if(NULL != dt->vol_obj) {
+ /* Close the connector-managed datatype data */
+ if(H5VL_datatype_close(dt->vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CLOSEERROR, FAIL, "unable to close datatype")
+
+ /* Free the VOL object */
+ if(H5VL_free_object(dt->vol_obj) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTDEC, FAIL, "unable to free VOL object")
+ dt->vol_obj = NULL;
+ } /* end if */
+
/* Close the datatype */
if(H5T_close(dt) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CLOSEERROR, FAIL, "unable to close datatype");
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CLOSEERROR, FAIL, "unable to close datatype")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T__close_cb() */
-
+
/*-------------------------------------------------------------------------
* Function: H5Tcreate
*
@@ -1650,17 +1704,17 @@ H5Tcreate(H5T_class_t type, size_t size)
/* create the type */
if(NULL == (dt = H5T__create(type, size)))
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to create type")
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to create type")
/* Get an ID for the datatype */
if((ret_value = H5I_register(H5I_DATATYPE, dt, TRUE)) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register datatype ID")
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register datatype ID")
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Tcreate() */
-
+
/*-------------------------------------------------------------------------
* Function: H5Tcopy
*
@@ -1680,33 +1734,42 @@ done:
*-------------------------------------------------------------------------
*/
hid_t
-H5Tcopy(hid_t type_id)
+H5Tcopy(hid_t obj_id)
{
- H5T_t *dt = NULL; /* Pointer to the datatype to copy */
- H5T_t *new_dt = NULL;
- hid_t ret_value = H5I_INVALID_HID; /* Return value */
+ H5T_t *dt = NULL; /* Pointer to the datatype to copy */
+ H5T_t *new_dt = NULL; /* Pointer to the new datatype */
+ hid_t dset_tid = H5I_INVALID_HID; /* Datatype ID from dataset */
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
FUNC_ENTER_API(H5I_INVALID_HID)
- H5TRACE1("i", "i", type_id);
+ H5TRACE1("i", "i", obj_id);
- switch(H5I_get_type(type_id)) {
+ switch(H5I_get_type(obj_id)) {
case H5I_DATATYPE:
- /* The argument is a datatype handle */
- if(NULL == (dt = (H5T_t *)H5I_object(type_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a datatype")
+ if(NULL == (dt = (H5T_t *)H5I_object(obj_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "type_id is not a datatype ID")
break;
case H5I_DATASET:
- {
- H5D_t *dset; /* Dataset for datatype */
+ {
+ H5VL_object_t *vol_obj = NULL; /* Dataset structure */
+
+ /* Check args */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(obj_id, H5I_DATASET)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "type_id is not a dataset ID")
+
+ /* Get the datatype from the dataset
+ * NOTE: This will have to be closed after we're done with it.
+ */
+ if(H5VL_dataset_get(vol_obj, H5VL_DATASET_GET_TYPE, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &dset_tid) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, H5I_INVALID_HID, "unable to get datatype from the dataset")
+
+ /* Unwrap the type ID */
+ if(NULL == (dt = (H5T_t *)H5I_object(dset_tid)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, H5I_INVALID_HID, "received invalid datatype from the dataset")
- /* The argument is a dataset handle */
- if(NULL == (dset = (H5D_t *)H5I_object(type_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a dataset")
- if(NULL == (dt = H5D_typeof(dset)))
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, H5I_INVALID_HID, "unable to get the dataset datatype")
- }
break;
+ }
case H5I_UNINIT:
case H5I_BADID:
@@ -1714,13 +1777,15 @@ H5Tcopy(hid_t type_id)
case H5I_GROUP:
case H5I_DATASPACE:
case H5I_ATTR:
- case H5I_REFERENCE:
+ case H5I_MAP:
case H5I_VFL:
+ case H5I_VOL:
case H5I_GENPROP_CLS:
case H5I_GENPROP_LST:
case H5I_ERROR_CLASS:
case H5I_ERROR_MSG:
case H5I_ERROR_STACK:
+ case H5I_SPACE_SEL_ITER:
case H5I_NTYPES:
default:
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a datatype or dataset")
@@ -1728,13 +1793,20 @@ H5Tcopy(hid_t type_id)
/* Copy datatype */
if(NULL == (new_dt = H5T_copy(dt, H5T_COPY_TRANSIENT)))
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5I_INVALID_HID, "unable to copy");
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5I_INVALID_HID, "unable to copy")
- /* Atomize result */
+ /* Get an ID for the copied datatype */
if((ret_value = H5I_register(H5I_DATATYPE, new_dt, TRUE)) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register datatype atom")
done:
+
+ /* If we got a type ID from a passed-in dataset, we need to close that */
+ if(dset_tid != H5I_INVALID_HID)
+ if(H5I_dec_app_ref(dset_tid) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_BADATOM, FAIL, "problem freeing temporary dataset type ID")
+
+ /* Close the new datatype on errors */
if(H5I_INVALID_HID == ret_value)
if(new_dt && H5T_close_real(new_dt) < 0)
HDONE_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, H5I_INVALID_HID, "unable to release datatype info")
@@ -1742,7 +1814,7 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Tcopy() */
-
+
/*-------------------------------------------------------------------------
* Function: H5Tclose
*
@@ -1777,7 +1849,7 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Tclose() */
-
+
/*-------------------------------------------------------------------------
* Function: H5Tequal
*
@@ -1814,7 +1886,7 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Tequal() */
-
+
/*-------------------------------------------------------------------------
* Function: H5Tlock
*
@@ -1861,7 +1933,7 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Tlock() */
-
+
/*-------------------------------------------------------------------------
* Function: H5Tget_class
*
@@ -1896,7 +1968,7 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Tget_class() */
-
+
/*-------------------------------------------------------------------------
* Function: H5T_get_class
*
@@ -1938,7 +2010,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T_get_class() */
-
+
/*-------------------------------------------------------------------------
* Function: H5Tdetect_class
*
@@ -1974,7 +2046,7 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Tdetect_class() */
-
+
/*-------------------------------------------------------------------------
* Function: H5T_detect_class
*
@@ -2050,7 +2122,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T_detect_class() */
-
+
/*-------------------------------------------------------------------------
* Function: H5Tis_variable_str
*
@@ -2084,7 +2156,7 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Tis_variable_str() */
-
+
/*-------------------------------------------------------------------------
* Function: H5T_is_variable_str
*
@@ -2105,7 +2177,7 @@ H5T_is_variable_str(const H5T_t *dt)
FUNC_LEAVE_NOAPI(H5T_IS_VL_STRING(dt->shared))
} /* end H5T_is_variable_str() */
-
+
/*-------------------------------------------------------------------------
* Function: H5Tget_size
*
@@ -2142,7 +2214,7 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Tget_size() */
-
+
/*-------------------------------------------------------------------------
* Function: H5Tset_size
*
@@ -2198,7 +2270,7 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Tset_size() */
-
+
/*-------------------------------------------------------------------------
* Function: H5Tget_super
*
@@ -2238,7 +2310,7 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Tget_super() */
-
+
/*-------------------------------------------------------------------------
* Function: H5T_get_super
*
@@ -2247,32 +2319,32 @@ done:
* the return value is an integer type.
*
* Return: Success: Data type for base data type.
- *
* Failure: NULL
*
* Programmer: Raymond Lu
- * October 9, 2002
+ * October 9, 2002
+ *
*-------------------------------------------------------------------------
*/
H5T_t *
H5T_get_super(const H5T_t *dt)
{
- H5T_t *ret_value=NULL;
+ H5T_t *ret_value = NULL;
FUNC_ENTER_NOAPI(NULL)
HDassert(dt);
- if (!dt->shared->parent)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "not a derived data type");
- if (NULL==(ret_value=H5T_copy(dt->shared->parent, H5T_COPY_ALL)))
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy parent data type");
+ if(!dt->shared->parent)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "not a derived data type")
+ if(NULL == (ret_value = H5T_copy(dt->shared->parent, H5T_COPY_ALL)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy parent data type")
done:
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5T_get_super() */
+
-
/*-------------------------------------------------------------------------
* Function: H5T__register_int
*
@@ -2312,7 +2384,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T__register_int() */
-
+
/*-------------------------------------------------------------------------
* Function: H5T__register
*
@@ -2496,7 +2568,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T__register() */
-
+
/*-------------------------------------------------------------------------
* Function: H5Tregister
*
@@ -2552,7 +2624,7 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Tregister() */
-
+
/*-------------------------------------------------------------------------
* Function: H5T__unregister
*
@@ -2656,7 +2728,7 @@ H5T__unregister(H5T_pers_t pers, const char *name, H5T_t *src, H5T_t *dst,
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5T__unregister() */
-
+
/*-------------------------------------------------------------------------
* Function: H5Tunregister
*
@@ -2696,7 +2768,7 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Tunregister() */
-
+
/*-------------------------------------------------------------------------
* Function: H5Tfind
*
@@ -2746,7 +2818,7 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Tfind() */
-
+
/*-------------------------------------------------------------------------
* Function: H5Tcompiler_conv
*
@@ -2786,7 +2858,7 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Tcompiler_conv() */
-
+
/*-------------------------------------------------------------------------
* Function: H5Tconvert
*
@@ -2845,7 +2917,57 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Tconvert() */
-
+
+/*-------------------------------------------------------------------------
+ * Function: H5Treclaim
+ *
+ * Purpose: Frees the buffers allocated for storing variable-length data
+ * in memory. Only frees the VL data in the selection defined in the
+ * dataspace. The dataset transfer property list is required to find the
+ * correct allocation/free methods for the VL data in the buffer.
+ *
+ * Return: Non-negative on success, negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, June 10, 1999
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Treclaim(hid_t type_id, hid_t space_id, hid_t dxpl_id, void *buf)
+{
+ H5S_t *space; /* Dataspace for iteration */
+ herr_t ret_value; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE4("e", "iii*x", type_id, space_id, dxpl_id, buf);
+
+ /* Check args */
+ if(H5I_DATATYPE != H5I_get_type(type_id) || buf == NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid argument")
+ if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid dataspace")
+ if(!(H5S_has_extent(space)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dataspace does not have extent set")
+
+ /* Get the default dataset transfer property list if the user didn't provide one */
+ if(H5P_DEFAULT == dxpl_id)
+ dxpl_id = H5P_DATASET_XFER_DEFAULT;
+ else
+ if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms")
+
+ /* Set DXPL for operation */
+ H5CX_set_dxpl(dxpl_id);
+
+ /* Call internal routine */
+ ret_value = H5T_reclaim(type_id, space, buf);
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Treclaim() */
+
+
/*-------------------------------------------------------------------------
* Function: H5Tencode
*
@@ -2884,7 +3006,7 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Tencode() */
-
+
/*-------------------------------------------------------------------------
* Function: H5Tdecode
*
@@ -2939,7 +3061,7 @@ done:
*-------------------------------------------------------------------------
*/
-
+
/*-------------------------------------------------------------------------
* Function: H5T_encode
*
@@ -2995,7 +3117,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T_encode() */
-
+
/*-------------------------------------------------------------------------
* Function: H5T_decode
*
@@ -3039,6 +3161,8 @@ H5T_decode(size_t buf_size, const unsigned char *buf)
if(H5T_set_loc(ret_value, NULL, H5T_LOC_MEMORY) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "invalid datatype location")
+ /* No VOL object */
+ ret_value->vol_obj = NULL;
done:
/* Release fake file structure */
if(f && H5F_fake_free(f) < 0)
@@ -3047,7 +3171,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T_decode() */
-
+
/*-------------------------------------------------------------------------
* Function: H5T__create
*
@@ -3089,7 +3213,7 @@ H5T__create(H5T_class_t type, size_t size)
/* Copy the default string datatype */
if(NULL == (dt = H5T_copy(origin_dt, H5T_COPY_TRANSIENT)))
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy");
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy")
/* Modify the datatype */
if(H5T__set_size(dt, size) < 0)
@@ -3162,6 +3286,9 @@ H5T__create(H5T_class_t type, size_t size)
if(H5T_STRING != type || H5T_VARIABLE != size)
dt->shared->size = size;
+ /* No VOL object */
+ dt->vol_obj = NULL;
+
/* Set return value */
ret_value = dt;
@@ -3176,7 +3303,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T__create() */
-
+
/*-------------------------------------------------------------------------
* Function: H5T_copy
*
@@ -3208,13 +3335,16 @@ H5T_copy(const H5T_t *old_dt, H5T_copy_t method)
/* Allocate space */
if(NULL == (new_dt = H5FL_MALLOC(H5T_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
if(NULL == (new_dt->shared = H5FL_MALLOC(H5T_shared_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* Copy shared information (entry information is copied last) */
*(new_dt->shared) = *(old_dt->shared);
+ /* No VOL object */
+ new_dt->vol_obj = NULL;
+
/* Check what sort of copy we are making */
switch (method) {
case H5T_COPY_TRANSIENT:
@@ -3248,7 +3378,7 @@ H5T_copy(const H5T_t *old_dt, H5T_copy_t method)
/* Open named datatype again */
if(H5O_open(&old_dt->oloc) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to reopen named data type");
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to reopen named data type")
/* Insert opened named datatype into opened object list for the file */
if(H5FO_insert(old_dt->sh_loc.file, old_dt->sh_loc.u.loc.oh_addr, new_dt->shared, FALSE)<0)
@@ -3312,9 +3442,9 @@ H5T_copy(const H5T_t *old_dt, H5T_copy_t method)
new_dt->shared->u.compnd.memb =
(H5T_cmemb_t *)H5MM_malloc(new_dt->shared->u.compnd.nalloc * sizeof(H5T_cmemb_t));
if (NULL == new_dt->shared->u.compnd.memb)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- HDmemcpy(new_dt->shared->u.compnd.memb, old_dt->shared->u.compnd.memb,
+ H5MM_memcpy(new_dt->shared->u.compnd.memb, old_dt->shared->u.compnd.memb,
new_dt->shared->u.compnd.nmembs * sizeof(H5T_cmemb_t));
} /* end if */
@@ -3330,7 +3460,7 @@ H5T_copy(const H5T_t *old_dt, H5T_copy_t method)
/* Range check against compound member's offset */
if ((accum_change < 0) && ((ssize_t) new_dt->shared->u.compnd.memb[i].offset < accum_change))
- HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, NULL, "invalid field size in datatype");
+ HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, NULL, "invalid field size in datatype")
/* Apply the accumulated size change to the offset of the field */
new_dt->shared->u.compnd.memb[i].offset += (size_t) accum_change;
@@ -3345,7 +3475,7 @@ H5T_copy(const H5T_t *old_dt, H5T_copy_t method)
/* check if we couldn't find a match */
if(old_match < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "fields in datatype corrupted");
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "fields in datatype corrupted")
} /* end if */
else
old_match = (int) i;
@@ -3361,7 +3491,7 @@ H5T_copy(const H5T_t *old_dt, H5T_copy_t method)
/* Range check against datatype size */
if ((accum_change < 0) && ((ssize_t) new_dt->shared->size < accum_change))
- HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, NULL, "invalid field size in datatype");
+ HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, NULL, "invalid field size in datatype")
/* Apply the accumulated size change to the size of the compound struct */
new_dt->shared->size += (size_t) accum_change;
@@ -3379,8 +3509,8 @@ H5T_copy(const H5T_t *old_dt, H5T_copy_t method)
new_dt->shared->u.enumer.value =
(uint8_t *)H5MM_malloc(new_dt->shared->u.enumer.nalloc * new_dt->shared->size);
if(NULL == new_dt->shared->u.enumer.value)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
- HDmemcpy(new_dt->shared->u.enumer.value, old_dt->shared->u.enumer.value,
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ H5MM_memcpy(new_dt->shared->u.enumer.value, old_dt->shared->u.enumer.value,
new_dt->shared->u.enumer.nmembs * new_dt->shared->size);
for(i = 0; i < new_dt->shared->u.enumer.nmembs; i++) {
s = old_dt->shared->u.enumer.name[i];
@@ -3393,7 +3523,7 @@ H5T_copy(const H5T_t *old_dt, H5T_copy_t method)
if(method == H5T_COPY_TRANSIENT || method == H5T_COPY_REOPEN) {
/* H5T_copy converts any type into a memory type */
if(H5T_set_loc(new_dt, NULL, H5T_LOC_MEMORY) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "invalid datatype location");
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "invalid datatype location")
} /* end if */
break;
@@ -3463,7 +3593,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T_copy() */
-
+
/*-------------------------------------------------------------------------
* Function: H5T_lock
*
@@ -3510,7 +3640,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
}
-
+
/*-------------------------------------------------------------------------
* Function: H5T__alloc
*
@@ -3543,6 +3673,9 @@ H5T__alloc(void)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
dt->shared->version = H5O_DTYPE_VERSION_1;
+ /* No VOL object initially */
+ dt->vol_obj = NULL;
+
/* Assign return value */
ret_value = dt;
@@ -3557,7 +3690,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T__alloc() */
-
+
/*-------------------------------------------------------------------------
* Function: H5T__free
*
@@ -3637,13 +3770,14 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T__free() */
-
+
/*-------------------------------------------------------------------------
* Function: H5T_close_real
*
* Purpose: Frees a datatype and all associated memory.
*
- * Hote: Does _not_ deal with open named datatypes, etc.
+ * Note: Does _not_ deal with open named datatypes, etc. so this
+ * should never see a type managed by a VOL connector.
*
* Return: Non-negative on success/Negative on failure
*
@@ -3665,7 +3799,7 @@ H5T_close_real(H5T_t *dt)
/* Clean up resources, depending on shared state */
if(dt->shared->state != H5T_STATE_OPEN) {
if(H5T__free(dt) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "unable to free datatype");
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "unable to free datatype")
dt->shared = H5FL_FREE(H5T_shared_t, dt->shared);
} /* end if */
@@ -3680,7 +3814,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T_close_real() */
-
+
/*-------------------------------------------------------------------------
* Function: H5T_close
*
@@ -3759,13 +3893,13 @@ H5T_close(H5T_t *dt)
/* Clean up resources */
if(H5T_close_real(dt) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "unable to free datatype");
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "unable to free datatype")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T_close() */
-
+
/*-------------------------------------------------------------------------
* Function: H5T__set_size
*
@@ -3808,7 +3942,7 @@ H5T__set_size(H5T_t *dt, size_t size)
if(dt->shared->parent) {
if(H5T__set_size(dt->shared->parent, size) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to set size for parent data type");
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to set size for parent data type")
/* Adjust size of datatype appropriately */
if(dt->shared->type==H5T_ARRAY)
@@ -3850,7 +3984,7 @@ H5T__set_size(H5T_t *dt, size_t size)
size_t max_size;
if((num_membs = H5T_get_nmembers(dt)) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to get number of members");
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to get number of members")
if(num_membs) {
for(i = 0; i < (unsigned)num_membs; i++) {
@@ -3864,7 +3998,7 @@ H5T__set_size(H5T_t *dt, size_t size)
max_size = H5T__get_member_size(dt, max_index);
if(size < (max_offset + max_size))
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "size shrinking will cut off last member ");
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "size shrinking will cut off last member ")
} /* end if */
/* Compound must not have been packed previously */
@@ -3884,7 +4018,7 @@ H5T__set_size(H5T_t *dt, size_t size)
/* Get a copy of unsigned char type as the base/parent type */
if(NULL == (base = (H5T_t *)H5I_object(H5T_NATIVE_UCHAR)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid base datatype");
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid base datatype")
dt->shared->parent=H5T_copy(base,H5T_COPY_ALL);
/* change this datatype into a VL string */
@@ -3910,7 +4044,7 @@ H5T__set_size(H5T_t *dt, size_t size)
/* Set up VL information */
if (H5T_set_loc(dt, NULL, H5T_LOC_MEMORY)<0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location");
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location")
} /* end if */
else {
prec = 8 * size;
@@ -3926,7 +4060,7 @@ H5T__set_size(H5T_t *dt, size_t size)
if(dt->shared->u.atomic.u.f.sign >= prec+offset ||
dt->shared->u.atomic.u.f.epos + dt->shared->u.atomic.u.f.esize > prec+offset ||
dt->shared->u.atomic.u.f.mpos + dt->shared->u.atomic.u.f.msize > prec+offset) {
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "adjust sign, mantissa, and exponent fields first");
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "adjust sign, mantissa, and exponent fields first")
}
break;
@@ -3965,7 +4099,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T__set_size() */
-
+
/*-------------------------------------------------------------------------
* Function: H5T_get_size
*
@@ -3993,7 +4127,7 @@ H5T_get_size(const H5T_t *dt)
FUNC_LEAVE_NOAPI(dt->shared->size)
} /* end H5T_get_size() */
-
+
/*-------------------------------------------------------------------------
* Function: H5T_cmp
*
@@ -4066,7 +4200,7 @@ H5T_cmp(const H5T_t *dt1, const H5T_t *dt2, hbool_t superset)
/* Build an index for each type so the names are sorted */
if(NULL == (idx1 = (unsigned *)H5MM_malloc(dt1->shared->u.compnd.nmembs * sizeof(unsigned))) ||
NULL == (idx2 = (unsigned *)H5MM_malloc(dt2->shared->u.compnd.nmembs * sizeof(unsigned))))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "memory allocation failed");
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "memory allocation failed")
for(u = 0; u < dt1->shared->u.compnd.nmembs; u++)
idx1[u] = idx2[u] = u;
if(dt1->shared->u.enumer.nmembs > 1) {
@@ -4152,7 +4286,7 @@ H5T_cmp(const H5T_t *dt1, const H5T_t *dt2, hbool_t superset)
/* Build an index for each type so the names are sorted */
if(NULL == (idx1 = (unsigned *)H5MM_malloc(dt1->shared->u.enumer.nmembs * sizeof(unsigned))) ||
NULL == (idx2 = (unsigned *)H5MM_malloc(dt2->shared->u.enumer.nmembs * sizeof(unsigned))))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "memory allocation failed");
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "memory allocation failed")
for(u=0; u<dt1->shared->u.enumer.nmembs; u++)
idx1[u] = u;
if(dt1->shared->u.enumer.nmembs > 1) {
@@ -4241,8 +4375,8 @@ H5T_cmp(const H5T_t *dt1, const H5T_t *dt2, hbool_t superset)
idx = u;
} /* end else */
- tmp = HDmemcmp(dt1->shared->u.enumer.value+idx1[u]*base_size,
- dt2->shared->u.enumer.value+idx2[idx]*base_size,
+ tmp = HDmemcmp((uint8_t *)dt1->shared->u.enumer.value + idx1[u] * base_size,
+ (uint8_t *)dt2->shared->u.enumer.value + idx2[idx] * base_size,
base_size);
if(tmp<0) HGOTO_DONE(-1);
if(tmp>0) HGOTO_DONE(1);
@@ -4408,28 +4542,10 @@ H5T_cmp(const H5T_t *dt1, const H5T_t *dt2, hbool_t superset)
HGOTO_DONE(-1);
if(dt1->shared->u.atomic.u.r.rtype > dt2->shared->u.atomic.u.r.rtype)
HGOTO_DONE(1);
-
- switch(dt1->shared->u.atomic.u.r.rtype) {
- case H5R_OBJECT:
- if(dt1->shared->u.atomic.u.r.loc < dt2->shared->u.atomic.u.r.loc)
- HGOTO_DONE(-1);
- if(dt1->shared->u.atomic.u.r.loc > dt2->shared->u.atomic.u.r.loc)
- HGOTO_DONE(1);
- break;
-
- case H5R_DATASET_REGION:
- /* Does this need more to distinguish it? -QAK 11/30/98 */
- /*void */
- break;
-
- case H5R_BADTYPE:
- case H5R_MAXTYPE:
- HDassert("invalid type" && 0);
- break;
- default:
- HDassert("not implemented yet" && 0);
- break;
- }
+ if(dt1->shared->u.atomic.u.r.loc < dt2->shared->u.atomic.u.r.loc)
+ HGOTO_DONE(-1);
+ if(dt1->shared->u.atomic.u.r.loc > dt2->shared->u.atomic.u.r.loc)
+ HGOTO_DONE(1);
break;
case H5T_NO_CLASS:
@@ -4455,7 +4571,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T_cmp() */
-
+
/*-------------------------------------------------------------------------
* Function: H5T_path_find
*
@@ -4502,7 +4618,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T_path_find() */
-
+
/*-------------------------------------------------------------------------
* Function: H5T__path_find_real
*
@@ -4686,14 +4802,14 @@ H5T__path_find_real(const H5T_t *src, const H5T_t *dst, const char *name,
if(H5T_g.soft[i].conv.is_app) {
if((H5T_g.soft[i].conv.u.app_func)(src_id, dst_id, &(path->cdata), (size_t)0, (size_t)0, (size_t)0, NULL, NULL, H5CX_get_dxpl()) < 0) {
HDmemset(&(path->cdata), 0, sizeof(H5T_cdata_t));
- H5E_clear_stack(H5E_DEFAULT); /*ignore the error*/
+ H5E_clear_stack(NULL); /*ignore the error*/
path_init_error = TRUE;
} /* end if */
} /* end if */
else
if((H5T_g.soft[i].conv.u.lib_func)(src_id, dst_id, &(path->cdata), (size_t)0, (size_t)0, (size_t)0, NULL, NULL) < 0) {
HDmemset(&(path->cdata), 0, sizeof(H5T_cdata_t));
- H5E_clear_stack(H5E_DEFAULT); /*ignore the error*/
+ H5E_clear_stack(NULL); /*ignore the error*/
path_init_error = TRUE;
} /* end if */
@@ -4809,7 +4925,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T__path_find_real() */
-
+
/*-------------------------------------------------------------------------
* Function: H5T_path_noop
*
@@ -4834,7 +4950,7 @@ H5T_path_noop(const H5T_path_t *p)
FUNC_LEAVE_NOAPI(p->is_noop || (p->is_hard && 0==H5T_cmp(p->src, p->dst, FALSE)))
} /* end H5T_path_noop() */
-
+
/*-------------------------------------------------------------------------
* Function: H5T_path_compound_subset
*
@@ -4878,7 +4994,7 @@ H5T_path_compound_subset(const H5T_path_t *p)
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T_path_compound_subset */
-
+
/*-------------------------------------------------------------------------
* Function: H5T_path_bkg
*
@@ -4900,7 +5016,7 @@ H5T_path_bkg(const H5T_path_t *p)
FUNC_LEAVE_NOAPI(p->cdata.need_bkg)
} /* end H5T_path_bkg() */
-
+
/*-------------------------------------------------------------------------
* Function: H5T__compiler_conv
*
@@ -4934,7 +5050,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T__compiler_conv() */
-
+
/*-------------------------------------------------------------------------
* Function: H5T_convert
*
@@ -4985,7 +5101,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T_convert() */
-
+
/*-------------------------------------------------------------------------
* Function: H5T_oloc
*
@@ -5026,7 +5142,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T_oloc() */
-
+
/*-------------------------------------------------------------------------
* Function: H5T_nameof
*
@@ -5041,7 +5157,7 @@ done:
*-------------------------------------------------------------------------
*/
H5G_name_t *
-H5T_nameof(H5T_t *dt)
+H5T_nameof(const H5T_t *dt)
{
H5G_name_t *ret_value = NULL;
@@ -5066,7 +5182,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T_nameof() */
-
+
/*-------------------------------------------------------------------------
* Function: H5T_is_immutable
*
@@ -5096,7 +5212,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
}
-
+
/*-------------------------------------------------------------------------
* Function: H5T_is_named
*
@@ -5115,8 +5231,10 @@ H5T_is_named(const H5T_t *dt)
HDassert(dt);
- if(dt->shared->state == H5T_STATE_OPEN || dt->shared->state == H5T_STATE_NAMED)
+ if(dt->vol_obj)
ret_value = TRUE;
+ else
+ ret_value = (H5T_STATE_OPEN == dt->shared->state || H5T_STATE_NAMED == dt->shared->state);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -5158,14 +5276,28 @@ H5T_convert_committed_datatype(H5T_t *dt, H5F_t *f)
if(H5G_name_free(&dt->path) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, FAIL, "unable to reset path")
+ /* If the datatype is committed through the VOL, close it */
+ if(NULL != dt->vol_obj) {
+ H5VL_object_t *vol_obj = dt->vol_obj;
+
+ /* Close the datatype through the VOL*/
+ if(H5VL_datatype_close(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CLOSEERROR, FAIL, "unable to close datatype")
+
+ /* Free the datatype and set the VOL object pointer to NULL */
+ if(H5VL_free_object(vol_obj) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTDEC, FAIL, "unable to free VOL object")
+ dt->vol_obj = NULL;
+ } /* end if */
+
dt->shared->state = H5T_STATE_TRANSIENT;
- }
+ } /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T_convert_committed_datatype() */
-
+
/*--------------------------------------------------------------------------
* Function: H5T_get_ref_type
*
@@ -5194,7 +5326,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T_get_ref_type() */
-
+
/*-------------------------------------------------------------------------
* Function: H5T_is_sensible
*
@@ -5256,7 +5388,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
}
-
+
/*--------------------------------------------------------------------------
NAME
H5T_set_loc
@@ -5266,7 +5398,7 @@ done:
htri_t H5T_set_loc(dt,f,loc)
H5T_t *dt; IN/OUT: Pointer to the datatype to mark
H5F_t *f; IN: Pointer to the file the datatype is in
- H5T_vlen_type_t loc IN: location of type
+ H5T_loc_t loc IN: location of type
RETURNS
One of two values on success:
@@ -5304,7 +5436,7 @@ H5T_set_loc(H5T_t *dt, H5F_t *f, H5T_loc_t loc)
/* Mark the VL, compound or array type */
if((changed=H5T_set_loc(dt->shared->parent,f,loc))<0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "Unable to set VL location");
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "Unable to set VL location")
if(changed>0)
ret_value=changed;
@@ -5328,7 +5460,7 @@ H5T_set_loc(H5T_t *dt, H5F_t *f, H5T_loc_t loc)
/* Range check against compound member's offset */
if ((accum_change < 0) && ((ssize_t) dt->shared->u.compnd.memb[i].offset < accum_change))
- HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, "invalid field size in datatype");
+ HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, "invalid field size in datatype")
/* Apply the accumulated size change to the offset of the field */
dt->shared->u.compnd.memb[i].offset += (size_t) accum_change;
@@ -5344,7 +5476,7 @@ H5T_set_loc(H5T_t *dt, H5F_t *f, H5T_loc_t loc)
/* Mark the VL, compound, enum or array type */
if((changed = H5T_set_loc(memb_type,f,loc)) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "Unable to set VL location");
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "Unable to set VL location")
if(changed > 0)
ret_value = changed;
@@ -5353,7 +5485,7 @@ H5T_set_loc(H5T_t *dt, H5F_t *f, H5T_loc_t loc)
/* Fail if the old_size is zero */
if (0 == old_size)
- HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, "old_size of zero would cause division by zero");
+ HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, "old_size of zero would cause division by zero")
/* Adjust the size of the member */
dt->shared->u.compnd.memb[i].size = (dt->shared->u.compnd.memb[i].size*memb_type->shared->size)/old_size;
@@ -5366,7 +5498,7 @@ H5T_set_loc(H5T_t *dt, H5F_t *f, H5T_loc_t loc)
/* Range check against datatype size */
if ((accum_change < 0) && ((ssize_t) dt->shared->size < accum_change))
- HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, "invalid field size in datatype");
+ HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, "invalid field size in datatype")
/* Apply the accumulated size change to the datatype */
dt->shared->size += (size_t) accum_change;
@@ -5378,30 +5510,22 @@ H5T_set_loc(H5T_t *dt, H5F_t *f, H5T_loc_t loc)
/* (If the force_conv flag is _not_ set, the type cannot change in size, so don't recurse) */
if(dt->shared->parent->shared->force_conv && H5T_IS_COMPLEX(dt->shared->parent->shared->type)) {
if((changed = H5T_set_loc(dt->shared->parent,f,loc)) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "Unable to set VL location");
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "Unable to set VL location")
if(changed > 0)
ret_value = changed;
} /* end if */
/* Mark this VL sequence */
if((changed = H5T__vlen_set_loc(dt, f, loc)) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "Unable to set VL location");
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "Unable to set VL location")
if(changed > 0)
ret_value = changed;
break;
case H5T_REFERENCE:
- /* Only need to change location of object references */
- if(dt->shared->u.atomic.u.r.rtype == H5R_OBJECT) {
- /* Mark this reference */
- if(loc != dt->shared->u.atomic.u.r.loc) {
- /* Set the location */
- dt->shared->u.atomic.u.r.loc = loc;
-
- /* Indicate that the location changed */
- ret_value = TRUE;
- } /* end if */
- } /* end if */
+ /* Reference types go through type conversion */
+ if((ret_value = H5T__ref_set_loc(dt, f, loc)) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "Unable to set reference location");
break;
case H5T_NO_CLASS:
@@ -5422,13 +5546,13 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T_set_loc() */
-
+
/*-------------------------------------------------------------------------
* Function: H5T_is_relocatable
*
* Purpose: Check if a datatype will change between disk and memory.
*
- * Notes: Currently, only variable-length and object references change
+ * Notes: Currently, only variable-length and references change
* between disk & memory (see cases where things are changed in
* the H5T_set_loc() code above).
*
@@ -5461,7 +5585,113 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T_is_relocatable() */
-
+
+/*-------------------------------------------------------------------------
+ * Function: H5T__detect_vlen_ref
+ *
+ * Purpose: Check whether a datatype contains (or is) a vlen reference
+ * datatype.
+ *
+ * Return: TRUE (1) or FALSE (0) on success
+ * (Can't fail)
+ *
+ * Programmer: Quincey Koziol
+ * Saturday, January 5, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+static hbool_t
+H5T__detect_vlen_ref(const H5T_t *dt)
+{
+ unsigned u; /* Local index variable */
+ hbool_t ret_value = FALSE; /* Return value */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Sanity checks */
+ HDassert(dt);
+
+ /* Check if this datatype is a vlen reference */
+ /* TODO currently H5T_STD_REF is always considered as a vlen type */
+ if(H5T_REFERENCE == dt->shared->type && !dt->shared->u.atomic.u.r.opaque)
+ HGOTO_DONE(TRUE);
+
+ /* Check for types that might have the correct type as a component */
+ switch(dt->shared->type) {
+ case H5T_COMPOUND:
+ /* Iterate over all the compound datatype's fields */
+ for(u = 0; u < dt->shared->u.compnd.nmembs; u++)
+ /* Recurse on field's datatype */
+ if(H5T__detect_vlen_ref(dt->shared->u.compnd.memb[u].type))
+ HGOTO_DONE(TRUE);
+ break;
+
+ case H5T_ARRAY:
+ case H5T_VLEN:
+ case H5T_ENUM:
+ HGOTO_DONE(H5T__detect_vlen_ref(dt->shared->parent));
+ break;
+
+ case H5T_NO_CLASS:
+ case H5T_INTEGER:
+ case H5T_FLOAT:
+ case H5T_TIME:
+ case H5T_STRING:
+ case H5T_BITFIELD:
+ case H5T_OPAQUE:
+ case H5T_REFERENCE:
+ case H5T_NCLASSES:
+ default:
+ break;
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T__detect_vlen_ref() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5T_is_vl_storage
+ *
+ * Purpose: Check if a datatype will be stored in a variable-length form.
+ *
+ * Notes: Currently, only variable-length string & sequences and region
+ * references are stored in a variable-length form.
+ *
+ * Return:
+ * One of two values on success:
+ * TRUE - If the datatype will be stored in a variable-length form
+ * FALSE - If the datatype will NOT be stored in a variable-length form
+ * <0 is returned on failure
+ *
+ * Programmer: Quincey Koziol
+ * Saturday, January 5, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5T_is_vl_storage(const H5T_t *dt)
+{
+ htri_t ret_value = FALSE;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check */
+ HDassert(dt);
+
+ /* VL and region reference datatypes are stored in variable-length form */
+ if(H5T_detect_class(dt, H5T_VLEN, FALSE))
+ ret_value = TRUE;
+ else if(H5T_detect_class(dt, H5T_REFERENCE, FALSE))
+ ret_value = H5T__detect_vlen_ref(dt);
+ else
+ ret_value = FALSE;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T_is_vl_storage() */
+
+
/*-------------------------------------------------------------------------
* Function: H5T_upgrade_version_cb
*
@@ -5519,7 +5749,7 @@ H5T_upgrade_version_cb(H5T_t *dt, void *op_value)
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5T_upgrade_version_cb() */
-
+
/*-------------------------------------------------------------------------
* Function: H5T__upgrade_version
*
@@ -5552,12 +5782,12 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T__upgrade_version() */
-
+
/*-------------------------------------------------------------------------
* Function: H5T_set_version
*
* Purpose: Set the encoding for a datatype to the version indicated by
- * the file's low bound if that is higher than the datatype's
+ * the file's low bound if that is higher than the datatype's
* version.
*
* Return: Non-negative on success/Negative on failure
@@ -5584,7 +5814,7 @@ H5T_set_version(H5F_t *f, H5T_t *dt)
if(H5T__upgrade_version(dt, vers) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "can't upgrade datatype encoding")
}
-
+
/* Version bounds check */
if(dt->shared->version > H5O_dtype_ver_bounds[H5F_HIGH_BOUND(f)])
HGOTO_ERROR(H5E_DATATYPE, H5E_BADRANGE, FAIL, "Datatype version out of bounds")
@@ -5593,7 +5823,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T_set_version() */
-
+
/*-------------------------------------------------------------------------
* Function: H5T_patch_file
*
@@ -5629,7 +5859,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T_patch_file() */
-
+
/*-------------------------------------------------------------------------
* Function: H5T_patch_vlen_file
*
diff --git a/src/H5Tcommit.c b/src/H5Tcommit.c
index ce537dc..c6b85a5 100644
--- a/src/H5Tcommit.c
+++ b/src/H5Tcommit.c
@@ -30,12 +30,15 @@
#include "H5ACprivate.h" /* Metadata cache */
#include "H5CXprivate.h" /* API Contexts */
#include "H5Eprivate.h" /* Error handling */
+#include "H5FLprivate.h" /* Free lists */
#include "H5FOprivate.h" /* File objects */
#include "H5Iprivate.h" /* IDs */
#include "H5Lprivate.h" /* Links */
#include "H5MMprivate.h" /* Memory Management */
+#include "H5Oprivate.h" /* Object headers */
#include "H5Pprivate.h" /* Property lists */
#include "H5Tpkg.h" /* Datatypes */
+#include "H5VLprivate.h" /* Virtual Object Layer */
/****************/
@@ -78,6 +81,12 @@ static H5T_t *H5T__open_oid(const H5G_loc_t *loc);
/* Local Variables */
/*******************/
+/* Declare a free list to manage the H5VL_t struct */
+H5FL_EXTERN(H5VL_t);
+
+/* Declare a free list to manage the H5VL_object_t struct */
+H5FL_EXTERN(H5VL_object_t);
+
/*-------------------------------------------------------------------------
@@ -94,22 +103,25 @@ herr_t
H5Tcommit2(hid_t loc_id, const char *name, hid_t type_id, hid_t lcpl_id,
hid_t tcpl_id, hid_t tapl_id)
{
- H5G_loc_t loc; /* Location to create datatype */
- H5T_t *type = NULL; /* Datatype for ID */
+ void *data = NULL; /* VOL-managed datatype data */
+ H5VL_object_t *new_obj = NULL; /* VOL object that holds the datatype object and the VOL info */
+ H5T_t *dt = NULL; /* High level datatype object that wraps the VOL object */
+ H5VL_object_t *vol_obj = NULL; /* object token of loc_id */
+ H5VL_loc_params_t loc_params;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE6("e", "i*siiii", loc_id, name, type_id, lcpl_id, tcpl_id, tapl_id);
/* Check arguments */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "name parameter cannot be NULL")
if(!*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "name parameter cannot be an empty string")
- if(NULL == (type = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
+ if(NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
+ if(H5T_is_named(dt))
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTSET, FAIL, "datatype is already committed")
/* Get correct property list */
if(H5P_DEFAULT == lcpl_id)
@@ -119,7 +131,7 @@ H5Tcommit2(hid_t loc_id, const char *name, hid_t type_id, hid_t lcpl_id,
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not link creation property list")
/* Get correct property list */
- if(H5P_DEFAULT == tcpl_id)
+ if (H5P_DEFAULT == tcpl_id)
tcpl_id = H5P_DATATYPE_CREATE_DEFAULT;
else
if(TRUE != H5P_isa_class(tcpl_id, H5P_DATATYPE_CREATE))
@@ -129,10 +141,28 @@ H5Tcommit2(hid_t loc_id, const char *name, hid_t type_id, hid_t lcpl_id,
if(H5CX_set_apl(&tapl_id, H5P_CLS_TACC, loc_id, TRUE) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "can't set access property list info")
+ /* Fill in location struct fields */
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* Get the object from the loc_id */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier")
+
/* Commit the type */
- if(H5T__commit_named(&loc, name, type, lcpl_id, tcpl_id) < 0)
+ if(NULL == (data = H5VL_datatype_commit(vol_obj, &loc_params, name, type_id, lcpl_id, tcpl_id, tapl_id, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to commit datatype")
+ /* Set up VOL object */
+ if(NULL == (new_obj = H5FL_CALLOC(H5VL_object_t)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "can't allocate top object structure")
+ new_obj->connector = vol_obj->connector;
+ new_obj->connector->nrefs ++;
+ new_obj->data = data;
+
+ /* Set the committed type object to the VOL connector pointer in the H5T_t struct */
+ dt->vol_obj = new_obj;
+
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Tcommit2() */
@@ -237,16 +267,17 @@ done:
herr_t
H5Tcommit_anon(hid_t loc_id, hid_t type_id, hid_t tcpl_id, hid_t tapl_id)
{
- H5G_loc_t loc; /* Group location for location */
+ void *dt = NULL; /* datatype object created by VOL connector */
+ H5VL_object_t *new_obj = NULL; /* VOL object that holds the datatype object and the VOL info */
H5T_t *type = NULL; /* Datatype created */
+ H5VL_object_t *vol_obj = NULL; /* object token of loc_id */
+ H5VL_loc_params_t loc_params;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE4("e", "iiii", loc_id, type_id, tcpl_id, tapl_id);
/* Check arguments */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(NULL == (type = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
if(H5T_is_named(type))
@@ -263,10 +294,28 @@ H5Tcommit_anon(hid_t loc_id, hid_t type_id, hid_t tcpl_id, hid_t tapl_id)
if(H5CX_set_apl(&tapl_id, H5P_CLS_TACC, loc_id, TRUE) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "can't set access property list info")
+ /* Fill in location struct fields */
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* Get the file object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier")
+
/* Commit the datatype */
- if(H5T__commit_anon(loc.oloc->file, type, tcpl_id) < 0)
+ if(NULL == (dt = H5VL_datatype_commit(vol_obj, &loc_params, NULL, type_id, H5P_DEFAULT, tcpl_id, tapl_id, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to commit datatype")
+ /* Setup VOL object */
+ if(NULL == (new_obj = H5FL_CALLOC(H5VL_object_t)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "can't allocate top object structure")
+ new_obj->connector = vol_obj->connector;
+ new_obj->connector->nrefs ++;
+ new_obj->data = dt;
+
+ /* Set the committed type object to the VOL connector pointer in the H5T_t struct */
+ type->vol_obj = new_obj;
+
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Tcommit_anon() */
@@ -515,16 +564,15 @@ done:
hid_t
H5Topen2(hid_t loc_id, const char *name, hid_t tapl_id)
{
- H5T_t *type = NULL; /* Datatype opened in file */
- H5G_loc_t loc; /* Group location of object to open */
+ void *dt = NULL; /* datatype token created by VOL connector */
+ H5VL_object_t *vol_obj = NULL; /* object token of loc_id */
+ H5VL_loc_params_t loc_params;
hid_t ret_value = H5I_INVALID_HID; /* Return value */
FUNC_ENTER_API(H5I_INVALID_HID)
H5TRACE3("i", "i*si", loc_id, name, tapl_id);
/* Check args */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a location")
if(!name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "name parameter cannot be NULL")
if(!*name)
@@ -534,19 +582,27 @@ H5Topen2(hid_t loc_id, const char *name, hid_t tapl_id)
if(H5CX_set_apl(&tapl_id, H5P_CLS_TACC, loc_id, FALSE) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "can't set access property list info")
+ /* Fill in location struct fields */
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* get the location object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid file identifier")
+
/* Open the datatype */
- if(NULL == (type = H5T__open_name(&loc, name)))
+ if(NULL == (dt = H5VL_datatype_open(vol_obj, &loc_params, name, tapl_id, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open named datatype")
/* Register the type and return the ID */
- if((ret_value = H5I_register(H5I_DATATYPE, type, TRUE)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register named datatype")
+ if((ret_value = H5VL_register(H5I_DATATYPE, dt, vol_obj->connector, TRUE)) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register named datatype")
done:
/* Cleanup on error */
if(H5I_INVALID_HID == ret_value)
- if(type != NULL)
- (void)H5T_close(type);
+ if(dt && H5VL_datatype_close(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
+ HDONE_ERROR(H5E_DATATYPE, H5E_CLOSEERROR, H5I_INVALID_HID, "unable to release datatype")
FUNC_LEAVE_API(ret_value)
} /* end H5Topen2() */
@@ -597,12 +653,15 @@ H5Tget_create_plist(hid_t dtype_id)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "can't get default creation property list")
if((ret_value = H5P_copy_plist(tcpl_plist, TRUE)) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, H5I_INVALID_HID, "unable to copy the creation property list")
- }
+ } /* end if */
/* If the datatype is committed, retrieve further information */
else {
- if((ret_value = H5T__get_create_plist(type)) < 0)
+ H5VL_object_t *vol_obj = type->vol_obj;
+
+ /* Get the property list through the VOL */
+ if(H5VL_datatype_get(vol_obj, H5VL_DATATYPE_GET_TCPL, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &ret_value) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, H5I_INVALID_HID, "can't get object creation info")
- }
+ } /* end else */
done:
FUNC_LEAVE_API(ret_value)
@@ -641,8 +700,9 @@ H5Tflush(hid_t type_id)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "can't set access property list info")
/* Flush metadata for named datatype */
- if(H5O_flush_common(&dt->oloc, type_id) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFLUSH, FAIL, "unable to flush datatype")
+ if(dt->vol_obj)
+ if(H5VL_datatype_specific(dt->vol_obj, H5VL_DATATYPE_FLUSH, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, type_id) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFLUSH, FAIL, "unable to flush datatype")
done:
FUNC_LEAVE_API(ret_value)
@@ -681,8 +741,9 @@ H5Trefresh(hid_t type_id)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "can't set access property list info")
/* Refresh the datatype's metadata */
- if((H5O_refresh_metadata(type_id, dt->oloc)) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTLOAD, FAIL, "unable to refresh datatype")
+ if(dt->vol_obj)
+ if(H5VL_datatype_specific(dt->vol_obj, H5VL_DATATYPE_REFRESH, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, type_id) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTLOAD, FAIL, "unable to refresh datatype")
done:
FUNC_LEAVE_API(ret_value)
@@ -865,6 +926,7 @@ H5T_open(const H5G_loc_t *loc)
else {
if(NULL == (dt = H5FL_MALLOC(H5T_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate space for datatype")
+ dt->vol_obj = NULL;
#if defined(H5_USING_MEMCHECKER) || !defined(NDEBUG)
/* Clear object location */
@@ -1014,3 +1076,206 @@ H5T_update_shared(H5T_t *dt)
FUNC_LEAVE_NOAPI(SUCCEED)
} /* H5T_update_shared() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5T_construct_datatype
+ *
+ * Purpose: Create a Library datatype with a connector specific datatype object
+ *
+ * Return: Success: A type structure
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+H5T_t *
+H5T_construct_datatype(H5VL_object_t *vol_obj)
+{
+ ssize_t nalloc;
+ void *buf = NULL;
+ H5T_t *dt = NULL; /* datatype token from VOL connector */
+ H5T_t *ret_value = NULL;
+
+ FUNC_ENTER_NOAPI(NULL)
+
+ /* get required buf size for encoding the datatype */
+ if(H5VL_datatype_get(vol_obj, H5VL_DATATYPE_GET_BINARY, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &nalloc, NULL, 0) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to get datatype serialized size")
+
+ /* allocate buffer to store binary description of the datatype */
+ if(NULL == (buf = (void *)H5MM_calloc((size_t)nalloc)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate space for datatype")
+
+ /* get binary description of the datatype */
+ if(H5VL_datatype_get(vol_obj, H5VL_DATATYPE_GET_BINARY, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, &nalloc, buf, (size_t)nalloc) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to get serialized datatype")
+
+ if(NULL == (dt = H5T_decode((size_t)nalloc, (const unsigned char *)buf)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "can't decode datatype")
+
+ dt->vol_obj = vol_obj;
+
+ ret_value = dt;
+
+done:
+ if(buf)
+ buf = H5MM_xfree(buf);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T_construct_datatype() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5T_get_named_type
+ *
+ * Purpose: Returns the VOL object for the named datatype if it exists
+ *
+ * Return: Success: Pointer to the VOL object for the datatype
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+H5VL_object_t *
+H5T_get_named_type(const H5T_t *dt)
+{
+ H5VL_object_t *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ if(NULL != dt->vol_obj)
+ ret_value = dt->vol_obj;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T_get_named_type() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5T_get_actual_type
+ *
+ * Purpose: Returns underlying native datatype created by native connector
+ * if datatype is committed, otherwise return the datatype
+ * object associate with the ID.
+ *
+ * Return: Success: Pointer to the VOL-managed data for this datatype
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+H5T_t *
+H5T_get_actual_type(H5T_t *dt)
+{
+ H5T_t *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ /* Check if the datatype is committed */
+ if(NULL == dt->vol_obj)
+ ret_value = dt;
+ else
+ ret_value = (H5T_t *)H5VL_object_data(dt->vol_obj);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T_get_actual_type() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5T_save_refresh_state
+ *
+ * Purpose: Save state for datatype reconstuction after a refresh.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5T_save_refresh_state(hid_t tid, H5O_shared_t *cached_H5O_shared)
+{
+ H5T_t *dt = NULL; /* High level datatype object that wraps the VOL object */
+ H5T_t *vol_dt = NULL; /* H5T_t pointer stored in the datatype's vol_obj field */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ HDassert(cached_H5O_shared);
+
+ if(NULL == (dt = (H5T_t *)H5I_object_verify(tid, H5I_DATATYPE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "tid is not a datatype ID")
+ vol_dt = (H5T_t *)(dt->vol_obj->data);
+ if(NULL == vol_dt)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "tid is not not a named datatype ID")
+
+ /* Increase the count on the file object */
+ vol_dt->shared->fo_count += 1;
+
+ /* Increment object count for the object in the top file */
+ if(H5FO_top_incr(vol_dt->sh_loc.file, vol_dt->sh_loc.u.loc.oh_addr) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, FAIL, "can't increment object count")
+
+ /* Cache the H5O_shared_t data */
+ H5MM_memcpy(cached_H5O_shared, &(vol_dt->sh_loc), sizeof(H5O_shared_t));
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T_save_refresh_state() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5T_restore_refresh_state
+ *
+ * Purpose: Restore state for datatype reconstuction after a refresh.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5T_restore_refresh_state(hid_t tid, H5O_shared_t *cached_H5O_shared)
+{
+ H5T_t *dt = NULL; /* High level datatype object that wraps the VOL object */
+ H5T_t *vol_dt = NULL; /* H5T_t pointer stored in the datatype's vol_obj field */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ HDassert(cached_H5O_shared);
+
+ if(NULL == (dt = (H5T_t *)H5I_object_verify(tid, H5I_DATATYPE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "tid not a datatype ID")
+ vol_dt = (H5T_t *)(dt->vol_obj->data);
+ if(NULL == vol_dt)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "tid is not not a named datatype ID")
+
+ /* Restore the H5O_shared_t data */
+ H5MM_memcpy(&(vol_dt->sh_loc), cached_H5O_shared, sizeof(H5O_shared_t));
+
+ /* Decrement the ref. count for this object in the top file */
+ if(H5FO_top_decr(vol_dt->sh_loc.file, vol_dt->sh_loc.u.loc.oh_addr) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDEC, FAIL, "can't decrement object count")
+
+ /* Decrease the count on the file object */
+ vol_dt->shared->fo_count -= 1;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T_restore_refresh_state() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5T_already_vol_managed
+ *
+ * Purpose: Check if the committed datatype is already VOL managed
+ *
+ * Return: TRUE / FALSE
+ *
+ *-------------------------------------------------------------------------
+ */
+hbool_t
+H5T_already_vol_managed(const H5T_t *dt)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ /* Sanity check */
+ HDassert(dt);
+
+ FUNC_LEAVE_NOAPI( dt->vol_obj != NULL )
+} /* end H5T_already_vol_managed() */
+
diff --git a/src/H5Tconv.c b/src/H5Tconv.c
index 563de65..84642f4 100644
--- a/src/H5Tconv.c
+++ b/src/H5Tconv.c
@@ -30,7 +30,6 @@
#include "H5Dprivate.h" /* Datasets */
#include "H5Eprivate.h" /* Error handling */
#include "H5FLprivate.h" /* Free Lists */
-#include "H5HGprivate.h" /* Global Heaps */
#include "H5Iprivate.h" /* IDs */
#include "H5MMprivate.h" /* Memory management */
#include "H5Pprivate.h" /* Property lists */
@@ -668,8 +667,8 @@
{ \
size_t elmtno; /*element number */ \
H5T_CONV_DECL_PREC(PREC) /*declare precision variables, or not */ \
- uint8_t *src_buf; /*'raw' source buffer */ \
- uint8_t *dst_buf; /*'raw' destination buffer */ \
+ void *src_buf; /*'raw' source buffer */ \
+ void *dst_buf; /*'raw' destination buffer */ \
ST *src, *s; /*source buffer */ \
DT *dst, *d; /*destination buffer */ \
H5T_t *st, *dt; /*datatype descriptors */ \
@@ -745,22 +744,22 @@
/* If we're down to the last few elements, just wrap up */ \
/* with a "real" reverse copy */ \
if(safe<2) { \
- src = (ST *)(src_buf = (uint8_t *)buf + (nelmts - 1) * (size_t)s_stride); \
- dst = (DT *)(dst_buf = (uint8_t *)buf + (nelmts - 1) * (size_t)d_stride); \
+ src = (ST *)(src_buf = (void *)((uint8_t *)buf + (nelmts - 1) * (size_t)s_stride)); \
+ dst = (DT *)(dst_buf = (void *)((uint8_t *)buf + (nelmts - 1) * (size_t)d_stride)); \
s_stride = -s_stride; \
d_stride = -d_stride; \
\
safe=nelmts; \
} /* end if */ \
else { \
- src = (ST *)(src_buf = (uint8_t *)buf + (nelmts - safe) * (size_t)s_stride); \
- dst = (DT *)(dst_buf = (uint8_t *)buf + (nelmts - safe) * (size_t)d_stride); \
+ src = (ST *)(src_buf = (void *)((uint8_t *)buf + (nelmts - safe) * (size_t)s_stride)); \
+ dst = (DT *)(dst_buf = (void *)((uint8_t *)buf + (nelmts - safe) * (size_t)d_stride)); \
} /* end else */ \
} /* end if */ \
else { \
/* Single forward pass over all data */ \
- src = (ST *)(src_buf = (uint8_t*)buf); \
- dst = (DT *)(dst_buf = (uint8_t*)buf); \
+ src = (ST *)(src_buf = buf); \
+ dst = (DT *)(dst_buf = buf); \
safe=nelmts; \
} /* end else */ \
\
@@ -828,7 +827,7 @@ done: \
/* Macro defining action on source data which needs to be aligned (before main action) */
#define H5T_CONV_LOOP_PRE_SALIGN(ST) { \
- HDmemcpy(&src_aligned, src, sizeof(ST)); \
+ H5MM_memcpy(&src_aligned, src, sizeof(ST)); \
}
/* Macro defining action on source data which doesn't need to be aligned (before main action) */
@@ -854,7 +853,7 @@ done: \
/* Macro defining action on destination data which needs to be aligned (after main action) */
#define H5T_CONV_LOOP_POST_DALIGN(DT) { \
- HDmemcpy(dst, &dst_aligned, sizeof(DT)); \
+ H5MM_memcpy(dst, &dst_aligned, sizeof(DT)); \
}
/* Macro defining action on destination data which doesn't need to be aligned (after main action) */
@@ -889,9 +888,9 @@ done: \
H5_GLUE(H5T_CONV_LOOP_,POST_DALIGN_GUTS)(DT) \
\
/* Advance pointers */ \
- src_buf += s_stride; \
+ src_buf = (void *)((uint8_t *)src_buf + s_stride); \
src = (ST *)src_buf; \
- dst_buf += d_stride; \
+ dst_buf = (void *)((uint8_t *)dst_buf + d_stride); \
dst = (DT *)dst_buf; \
}
@@ -1019,6 +1018,9 @@ H5FL_BLK_DEFINE_STATIC(vlen_seq);
/* Declare a free list to manage pieces of array data */
H5FL_BLK_DEFINE_STATIC(array_seq);
+/* Declare a free list to manage pieces of reference data */
+H5FL_BLK_DEFINE_STATIC(ref_seq);
+
/*-------------------------------------------------------------------------
* Function: H5T__conv_noop
@@ -1797,7 +1799,7 @@ H5T__conv_b_b(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
* should copy the value to the true destination buffer.
*/
if(d == dbuf)
- HDmemcpy(dp, d, dst->shared->size);
+ H5MM_memcpy(dp, d, dst->shared->size);
if(buf_stride) {
sp += direction * (ssize_t)buf_stride; /* Note that cast is checked with H5_CHECK_OVERFLOW, above */
dp += direction * (ssize_t)buf_stride; /* Note that cast is checked with H5_CHECK_OVERFLOW, above */
@@ -2658,11 +2660,11 @@ H5T_conv_enum_init(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata)
if(1 == src->shared->size || sizeof(short) == src->shared->size || sizeof(int) == src->shared->size) {
for(i = 0; i < src->shared->u.enumer.nmembs; i++) {
if(1 == src->shared->size)
- n = *((signed char *)(src->shared->u.enumer.value + i));
+ n = *((signed char *)((uint8_t *)src->shared->u.enumer.value + i));
else if (sizeof(short) == src->shared->size)
- n = *((short *)(src->shared->u.enumer.value + i * src->shared->size));
+ n = *((short *)((void *)((uint8_t *)src->shared->u.enumer.value + (i * src->shared->size))));
else
- n = *((int *)(src->shared->u.enumer.value + i * src->shared->size));
+ n = *((int *)((void *)((uint8_t *)src->shared->u.enumer.value + (i * src->shared->size))));
if(0 == i) {
domain[0] = domain[1] = n;
} else {
@@ -2683,11 +2685,11 @@ H5T_conv_enum_init(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata)
map[i] = -1; /*entry unused*/
for(i = 0; i < src->shared->u.enumer.nmembs; i++) {
if(1 == src->shared->size)
- n = *((signed char *)(src->shared->u.enumer.value + i));
+ n = *((signed char *)((uint8_t *)src->shared->u.enumer.value + i));
else if(sizeof(short) == src->shared->size)
- n = *((short *)(src->shared->u.enumer.value + i * src->shared->size));
+ n = *((short *)((void *)((uint8_t *)src->shared->u.enumer.value + (i * src->shared->size))));
else
- n = *((int *)(src->shared->u.enumer.value + i * src->shared->size));
+ n = *((int *)((void *)((uint8_t *)src->shared->u.enumer.value + (i * src->shared->size))));
n -= priv->base;
HDassert(n >= 0 && (unsigned)n < priv->length);
HDassert(map[n] < 0);
@@ -2771,7 +2773,7 @@ H5T__conv_enum(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
case H5T_CONV_FREE:
#ifdef H5T_DEBUG
if (H5DEBUG(T)) {
- fprintf(H5DEBUG(T), " Using %s mapping function%s\n",
+ HDfprintf(H5DEBUG(T), " Using %s mapping function%s\n",
priv->length?"O(1)":"O(log N)",
priv->length?"":", where N is the number of enum members");
}
@@ -2835,9 +2837,9 @@ H5T__conv_enum(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
if(1 == src->shared->size)
n = *((signed char*)s);
else if(sizeof(short) == src->shared->size)
- n = *((short*)s);
+ n = *((short *)((void *)s));
else
- n = *((int*)s);
+ n = *((int *)((void *)s));
n -= priv->base;
if(n < 0 || (unsigned)n >= priv->length || priv->src2dst[n] < 0) {
/*overflow*/
@@ -2852,8 +2854,8 @@ H5T__conv_enum(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
else if(except_ret == H5T_CONV_ABORT)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception")
} else
- HDmemcpy(d,
- dst->shared->u.enumer.value + (unsigned)priv->src2dst[n] * dst->shared->size,
+ H5MM_memcpy(d,
+ (uint8_t *)dst->shared->u.enumer.value + ((unsigned)priv->src2dst[n] * dst->shared->size),
dst->shared->size);
} /* end if */
else {
@@ -2865,7 +2867,7 @@ H5T__conv_enum(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
while(lt < rt) {
md = (lt + rt) / 2;
- cmp = HDmemcmp(s, src->shared->u.enumer.value + md * src->shared->size,
+ cmp = HDmemcmp(s, (uint8_t *)src->shared->u.enumer.value + (md * src->shared->size),
src->shared->size);
if(cmp < 0)
rt = md;
@@ -2888,8 +2890,8 @@ H5T__conv_enum(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
} /* end if */
else {
HDassert(priv->src2dst[md] >= 0);
- HDmemcpy(d,
- dst->shared->u.enumer.value + (unsigned)priv->src2dst[md] * dst->shared->size,
+ H5MM_memcpy(d,
+ (uint8_t *)dst->shared->u.enumer.value + ((unsigned)priv->src2dst[md] * dst->shared->size),
dst->shared->size);
} /* end else */
} /* end else */
@@ -3020,17 +3022,16 @@ H5T__conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
hbool_t noop_conv = FALSE; /* Flag to indicate a noop conversion */
hbool_t write_to_file = FALSE; /* Flag to indicate writing to file */
htri_t parent_is_vlen; /* Flag to indicate parent is vlen datatyp */
+ size_t bg_seq_len = 0; /* The number of elements in the background sequence */
hid_t tsrc_id = -1, tdst_id = -1;/*temporary type atoms */
H5T_t *src = NULL; /*source datatype */
H5T_t *dst = NULL; /*destination datatype */
- H5HG_t bg_hobjid, parent_hobjid;
uint8_t *s = NULL; /*source buffer */
uint8_t *d = NULL; /*destination buffer */
uint8_t *b = NULL; /*background buffer */
ssize_t s_stride, d_stride; /*src and dst strides */
ssize_t b_stride; /*bkg stride */
size_t safe; /*how many elements are safe to process in each pass */
- size_t bg_seq_len = 0;
size_t src_base_size, dst_base_size;/*source & destination base size*/
void *conv_buf = NULL; /*temporary conversion buffer */
size_t conv_buf_size = 0; /*size of conversion buffer in bytes */
@@ -3055,13 +3056,13 @@ H5T__conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "not a datatype")
if(H5T_VLEN != src->shared->type)
HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "not a H5T_VLEN datatype")
- if(H5T_VLEN != dst->shared->type)
+ if(H5T_VLEN != dst->shared->type)
HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "not a H5T_VLEN datatype")
if(H5T_VLEN_STRING == src->shared->u.vlen.type && H5T_VLEN_STRING == dst->shared->u.vlen.type) {
if((H5T_CSET_ASCII == src->shared->u.vlen.cset && H5T_CSET_UTF8 == dst->shared->u.vlen.cset)
- || (H5T_CSET_ASCII == dst->shared->u.vlen.cset && H5T_CSET_UTF8 == src->shared->u.vlen.cset))
+ || (H5T_CSET_ASCII == dst->shared->u.vlen.cset && H5T_CSET_UTF8 == src->shared->u.vlen.cset))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "The library doesn't convert between strings of ASCII and UTF")
- }
+ } /* end if */
/* Variable-length types don't need a background buffer */
cdata->need_bkg = H5T_BKG_NO;
@@ -3179,25 +3180,27 @@ H5T__conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
} /* end else */
for(elmtno = 0; elmtno < safe; elmtno++) {
+ hbool_t is_nil; /* Whether sequence is "nil" */
+
/* Check for "nil" source sequence */
- if((*(src->shared->u.vlen.isnull))(src->shared->u.vlen.f, s)) {
+ if((*(src->shared->u.vlen.cls->isnull))(src->shared->u.vlen.f, s, &is_nil) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "can't check if VL data is 'nil'")
+ else if(is_nil) {
/* Write "nil" sequence to destination location */
- if((*(dst->shared->u.vlen.setnull))(dst->shared->u.vlen.f, d, b) < 0)
+ if((*(dst->shared->u.vlen.cls->setnull))(dst->shared->u.vlen.f, d, b) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_WRITEERROR, FAIL, "can't set VL data to 'nil'")
- } /* end if */
+ } /* end else-if */
else {
- ssize_t sseq_len; /* (signed) The number of elements in the current sequence*/
- size_t seq_len; /* The number of elements in the current sequence*/
+ size_t seq_len; /* The number of elements in the current sequence */
/* Get length of element sequences */
- if((sseq_len = (*(src->shared->u.vlen.getlen))(s)) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "incorrect length")
- seq_len = (size_t)sseq_len;
+ if((*(src->shared->u.vlen.cls->getlen))(src->shared->u.vlen.f, s, &seq_len) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "bad sequence length")
/* If we are reading from memory and there is no conversion, just get the pointer to sequence */
if(write_to_file && noop_conv) {
/* Get direct pointer to sequence */
- if(NULL == (conv_buf = (*(src->shared->u.vlen.getptr))(s)))
+ if(NULL == (conv_buf = (*(src->shared->u.vlen.cls->getptr))(s)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid source pointer")
} /* end if */
else {
@@ -3213,17 +3216,17 @@ H5T__conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
conv_buf_size = ((1 / H5T_VLEN_MIN_CONF_BUF_SIZE) + 1) * H5T_VLEN_MIN_CONF_BUF_SIZE;
if(NULL == (conv_buf = H5FL_BLK_CALLOC(vlen_seq, conv_buf_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion")
- }
+ } /* end if */
else if(conv_buf_size < MAX(src_size, dst_size)) {
/* Only allocate conversion buffer in H5T_VLEN_MIN_CONF_BUF_SIZE increments */
conv_buf_size = ((MAX(src_size, dst_size) / H5T_VLEN_MIN_CONF_BUF_SIZE) + 1) * H5T_VLEN_MIN_CONF_BUF_SIZE;
if(NULL == (conv_buf = H5FL_BLK_REALLOC(vlen_seq, conv_buf, conv_buf_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion")
HDmemset(conv_buf, 0, conv_buf_size);
- } /* end if */
+ } /* end else-if */
/* Read in VL sequence */
- if((*(src->shared->u.vlen.read))(src->shared->u.vlen.f, s, conv_buf, src_size) < 0)
+ if((*(src->shared->u.vlen.cls->read))(src->shared->u.vlen.f, s, conv_buf, src_size) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_READERROR, FAIL, "can't read VL data")
} /* end else */
@@ -3241,9 +3244,14 @@ H5T__conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
/* If we are writing and there is a nested VL type, read
* the sequence into the background buffer */
if(nested) {
- const uint8_t *tmp = b;
+ /* Sanity check */
+ HDassert(write_to_file);
+
+ /* Get length of background element sequence */
+ if((*(dst->shared->u.vlen.cls->getlen))(dst->shared->u.vlen.f, b, &bg_seq_len) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "bad sequence length")
- UINT32DECODE(tmp, bg_seq_len);
+ /* Read sequence if length > 0 */
if(bg_seq_len > 0) {
if(tmp_buf_size < (bg_seq_len * MAX(src_base_size, dst_base_size))) {
tmp_buf_size = (bg_seq_len * MAX(src_base_size, dst_base_size));
@@ -3251,10 +3259,10 @@ H5T__conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion")
HDmemset(tmp_buf, 0, tmp_buf_size);
} /* end if */
- H5F_addr_decode(dst->shared->u.vlen.f, &tmp, &(bg_hobjid.addr));
- UINT32DECODE(tmp, bg_hobjid.idx);
- if(NULL == H5HG_read(dst->shared->u.vlen.f, &bg_hobjid, tmp_buf, NULL))
- HGOTO_ERROR(H5E_DATATYPE, H5E_READERROR, FAIL, "can't read VL sequence into background buffer")
+
+ /* Read in background VL sequence */
+ if((*(dst->shared->u.vlen.cls->read))(dst->shared->u.vlen.f, b, tmp_buf, bg_seq_len) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_READERROR, FAIL, "can't read VL data")
} /* end if */
/* If the sequence gets shorter, pad out the original sequence with zeros */
@@ -3268,26 +3276,23 @@ H5T__conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
} /* end if */
/* Write sequence to destination location */
- if((*(dst->shared->u.vlen.write))(dst->shared->u.vlen.f, &vl_alloc_info, d, conv_buf, b, seq_len, dst_base_size) < 0)
+ if((*(dst->shared->u.vlen.cls->write))(dst->shared->u.vlen.f, &vl_alloc_info, d, conv_buf, b, seq_len, dst_base_size) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_WRITEERROR, FAIL, "can't write VL data")
if(!noop_conv) {
/* For nested VL case, free leftover heap objects from the deeper level if the length of new data elements is shorter than the old data elements.*/
if(nested && seq_len < bg_seq_len) {
- size_t parent_seq_len;
const uint8_t *tmp;
size_t u;
- /* TMP_P is reset each time in the loop because DST_BASE_SIZE may include some data in addition to VL info. - SLU */
- for(u = seq_len; u < bg_seq_len; u++) {
- tmp = (uint8_t *)tmp_buf + u * dst_base_size;
- UINT32DECODE(tmp, parent_seq_len);
- if(parent_seq_len > 0) {
- H5F_addr_decode(dst->shared->u.vlen.f, &tmp, &(parent_hobjid.addr));
- UINT32DECODE(tmp, parent_hobjid.idx);
- if(H5HG_remove(dst->shared->u.vlen.f, &parent_hobjid) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_WRITEERROR, FAIL, "Unable to remove heap object")
- } /* end if */
+ /* Sanity check */
+ HDassert(write_to_file);
+
+ tmp = (uint8_t *)tmp_buf + seq_len * dst_base_size;
+ for(u = seq_len; u < bg_seq_len; u++, tmp += dst_base_size) {
+ /* Delete sequence in destination location */
+ if((*(dst->shared->u.vlen.cls->del))(dst->shared->u.vlen.f, tmp) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREMOVE, FAIL, "unable to remove heap object")
} /* end for */
} /* end if */
} /* end if */
@@ -3474,6 +3479,195 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T__conv_array() */
+/*-------------------------------------------------------------------------
+ * Function: H5T__conv_ref
+ *
+ * Purpose: Converts between reference datatypes in memory and on disk.
+ * This is a soft conversion function.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5T__conv_ref(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
+ size_t buf_stride, size_t bkg_stride, void *buf, void *bkg)
+{
+ H5T_t *src = NULL; /* source datatype */
+ H5T_t *dst = NULL; /* destination datatype */
+ uint8_t *s = NULL; /* source buffer */
+ uint8_t *d = NULL; /* destination buffer */
+ uint8_t *b = NULL; /* background buffer */
+ ssize_t s_stride, d_stride; /* src and dst strides */
+ ssize_t b_stride; /* bkg stride */
+ size_t safe; /* how many elements are safe to process in each pass */
+ void *conv_buf = NULL; /* temporary conversion buffer */
+ size_t conv_buf_size = 0; /* size of conversion buffer in bytes */
+ size_t elmtno; /* element number counter */
+ herr_t ret_value = SUCCEED; /* return value */
+
+ FUNC_ENTER_PACKAGE
+
+ switch(cdata->command) {
+ case H5T_CONV_INIT:
+ /*
+ * First, determine if this conversion function applies to the
+ * conversion path SRC_ID-->DST_ID. If not, return failure;
+ * otherwise initialize the `priv' field of `cdata' with
+ * information that remains (almost) constant for this
+ * conversion path.
+ */
+ if(NULL == (src = (H5T_t *)H5I_object(src_id)) || NULL == (dst = (H5T_t *)H5I_object(dst_id)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "not a datatype")
+ if(H5T_REFERENCE != src->shared->type)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "not a H5T_REFERENCE datatype")
+ if(H5T_REFERENCE != dst->shared->type)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "not a H5T_REFERENCE datatype")
+ /* Only allow for source reference that is not an opaque type, destination must be opaque */
+ if(!dst->shared->u.atomic.u.r.opaque)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "not an H5T_STD_REF datatype")
+
+ /* Reference types don't need a background buffer */
+ cdata->need_bkg = H5T_BKG_NO;
+ break;
+
+ case H5T_CONV_FREE:
+ break;
+
+ case H5T_CONV_CONV:
+ {
+ /*
+ * Conversion.
+ */
+ if(NULL == (src = (H5T_t *)H5I_object(src_id)) || NULL == (dst = (H5T_t *)H5I_object(dst_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
+
+ HDassert(src->shared->u.atomic.u.r.cls);
+
+ /* Initialize source & destination strides */
+ if(buf_stride) {
+ HDassert(buf_stride >= src->shared->size);
+ HDassert(buf_stride >= dst->shared->size);
+ H5_CHECK_OVERFLOW(buf_stride, size_t, ssize_t);
+ s_stride = d_stride = (ssize_t)buf_stride;
+ } /* end if */
+ else {
+ H5_CHECK_OVERFLOW(src->shared->size, size_t, ssize_t);
+ H5_CHECK_OVERFLOW(dst->shared->size, size_t, ssize_t);
+ s_stride = (ssize_t)src->shared->size;
+ d_stride = (ssize_t)dst->shared->size;
+ } /* end else */
+ if(bkg) {
+ if(bkg_stride)
+ b_stride = (ssize_t)bkg_stride;
+ else
+ b_stride = d_stride;
+ } /* end if */
+ else
+ b_stride = 0;
+
+ /* The outer loop of the type conversion macro, controlling which */
+ /* direction the buffer is walked */
+ while(nelmts > 0) {
+ /* Check if we need to go backwards through the buffer */
+ if(d_stride > s_stride) {
+ /* Sanity check */
+ HDassert(s_stride > 0);
+ HDassert(d_stride > 0);
+ HDassert(b_stride >= 0);
+
+ /* Compute the number of "safe" destination elements at */
+ /* the end of the buffer (Those which don't overlap with */
+ /* any source elements at the beginning of the buffer) */
+ safe = nelmts - (((nelmts * (size_t)s_stride) + ((size_t)d_stride - 1)) / (size_t)d_stride);
+
+ /* If we're down to the last few elements, just wrap up */
+ /* with a "real" reverse copy */
+ if(safe < 2) {
+ s = (uint8_t *)buf + (nelmts - 1) * (size_t)s_stride;
+ d = (uint8_t *)buf + (nelmts - 1) * (size_t)d_stride;
+ b = (uint8_t *)bkg + (nelmts - 1) * (size_t)b_stride;
+ s_stride = -s_stride;
+ d_stride = -d_stride;
+ b_stride = -b_stride;
+
+ safe = nelmts;
+ } /* end if */
+ else {
+ s = (uint8_t *)buf + (nelmts - safe) * (size_t)s_stride;
+ d = (uint8_t *)buf + (nelmts - safe) * (size_t)d_stride;
+ b = (uint8_t *)bkg + (nelmts - safe) * (size_t)b_stride;
+ } /* end else */
+ } /* end if */
+ else {
+ /* Single forward pass over all data */
+ s = d = (uint8_t *)buf;
+ b = (uint8_t *)bkg;
+ safe = nelmts;
+ } /* end else */
+
+ for(elmtno = 0; elmtno < safe; elmtno++) {
+ size_t buf_size;
+ hbool_t dst_copy = FALSE;
+
+ /* Get size of references */
+ if(0 == (buf_size = src->shared->u.atomic.u.r.cls->getsize(
+ src->shared->u.atomic.u.r.f, s, src->shared->size,
+ dst->shared->u.atomic.u.r.f, &dst_copy)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "incorrect size")
+
+ /* Check if conversion buffer is large enough, resize if necessary. */
+ if(conv_buf_size < buf_size) {
+ conv_buf_size = buf_size;
+ if(NULL == (conv_buf = H5FL_BLK_REALLOC(ref_seq, conv_buf, conv_buf_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion")
+ HDmemset(conv_buf, 0, conv_buf_size);
+ } /* end if */
+
+ if(dst_copy && (src->shared->u.atomic.u.r.loc == H5T_LOC_DISK)) {
+ H5MM_memcpy(conv_buf, s, buf_size);
+ } else {
+ /* Read reference */
+ if(src->shared->u.atomic.u.r.cls->read(
+ src->shared->u.atomic.u.r.f, s, src->shared->size,
+ dst->shared->u.atomic.u.r.f, conv_buf, buf_size) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_READERROR, FAIL, "can't read reference data")
+ }
+
+ if(dst_copy && (dst->shared->u.atomic.u.r.loc == H5T_LOC_DISK)) {
+ H5MM_memcpy(d, conv_buf, buf_size);
+ } else {
+ /* Write reference to destination location */
+ if(dst->shared->u.atomic.u.r.cls->write(
+ src->shared->u.atomic.u.r.f, conv_buf, buf_size, src->shared->u.atomic.u.r.rtype,
+ dst->shared->u.atomic.u.r.f, d, dst->shared->size, b) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_WRITEERROR, FAIL, "can't write reference data")
+ }
+
+ /* Advance pointers */
+ s += s_stride;
+ d += d_stride;
+ b += b_stride;
+ } /* end for */
+
+ /* Decrement number of elements left to convert */
+ nelmts -= safe;
+ } /* end while */
+ } /* end case */
+ break;
+
+ default: /* Some other command we don't know about yet.*/
+ HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unknown conversion command")
+ } /* end switch */
+
+done:
+ /* Release the conversion buffer (always allocated, except on errors) */
+ if(conv_buf)
+ conv_buf = H5FL_BLK_FREE(ref_seq, conv_buf);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T__conv_ref() */
+
/*-------------------------------------------------------------------------
* Function: H5T__conv_i_i
@@ -3846,7 +4040,7 @@ H5T__conv_i_i(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
* should copy the value to the true destination buffer.
*/
if(d==dbuf)
- HDmemcpy(dp, d, dst->shared->size);
+ H5MM_memcpy(dp, d, dst->shared->size);
/* Advance source & destination pointers by delta amounts */
sp += src_delta;
@@ -4432,7 +4626,7 @@ H5T__conv_f_f(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
*/
next:
if(d == dbuf)
- HDmemcpy(dp, d, dst_p->shared->size);
+ H5MM_memcpy(dp, d, dst_p->shared->size);
/* Advance source & destination pointers by delta amounts */
sp += src_delta;
@@ -4604,7 +4798,7 @@ H5T__conv_s_s(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
--nchars;
nchars = MIN(dst->shared->size, nchars);
if(d != s)
- HDmemcpy(d, s, nchars);
+ H5MM_memcpy(d, s, nchars);
break;
case H5T_STR_RESERVED_3:
@@ -4666,7 +4860,7 @@ H5T__conv_s_s(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
* should copy the value to the true destination buffer.
*/
if(d == dbuf)
- HDmemcpy(dp, d, dst->shared->size);
+ H5MM_memcpy(dp, d, dst->shared->size);
/* Advance source & destination pointers by delta amounts */
sp += src_delta;
@@ -7480,7 +7674,7 @@ H5T__conv_llong_double (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
*
*-------------------------------------------------------------------------
*/
-#if H5T_CONV_INTERNAL_LLONG_LDOUBLE
+#ifdef H5T_CONV_INTERNAL_LLONG_LDOUBLE
herr_t
H5T__conv_llong_ldouble (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride,
@@ -7548,7 +7742,7 @@ H5T__conv_ullong_double (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
*
*-------------------------------------------------------------------------
*/
-#if H5T_CONV_INTERNAL_ULLONG_LDOUBLE
+#ifdef H5T_CONV_INTERNAL_ULLONG_LDOUBLE
herr_t
H5T__conv_ullong_ldouble (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride,
@@ -8244,7 +8438,7 @@ H5_GCC_DIAG_ON(float-equal)
*
*-------------------------------------------------------------------------
*/
-#if H5T_CONV_INTERNAL_LDOUBLE_LLONG
+#ifdef H5T_CONV_INTERNAL_LDOUBLE_LLONG
herr_t
H5T__conv_ldouble_llong (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride,
@@ -8825,7 +9019,7 @@ H5T__conv_f_i(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
* should copy the value to the true destination buffer.
*/
if (d==dbuf)
- HDmemcpy (dp, d, dst_p->shared->size);
+ H5MM_memcpy (dp, d, dst_p->shared->size);
if (buf_stride) {
sp += direction * (ssize_t) buf_stride;
dp += direction * (ssize_t) buf_stride;
@@ -9235,7 +9429,7 @@ H5T__conv_i_f(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
* should copy the value to the true destination buffer.
*/
if (d==dbuf)
- HDmemcpy (dp, d, dst_p->shared->size);
+ H5MM_memcpy (dp, d, dst_p->shared->size);
if (buf_stride) {
sp += direction * (ssize_t) buf_stride;
dp += direction * (ssize_t) buf_stride;
@@ -9305,3 +9499,84 @@ H5T_reverse_order(uint8_t *rev, uint8_t *s, size_t size, H5T_order_t order)
FUNC_LEAVE_NOAPI(SUCCEED)
}
+
+/*-------------------------------------------------------------------------
+ * Function: H5T_reclaim
+ *
+ * Purpose: Frees the buffers allocated for storing variable-length data
+ * in memory. Only frees the VL data in the selection defined in the
+ * dataspace.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5T_reclaim(hid_t type_id, H5S_t *space, void *buf)
+{
+ H5T_t *type; /* Datatype */
+ H5S_sel_iter_op_t dset_op; /* Operator for iteration */
+ H5T_vlen_alloc_info_t vl_alloc_info; /* VL allocation info */
+ herr_t ret_value = FAIL; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* Check args */
+ HDassert(H5I_DATATYPE == H5I_get_type(type_id));
+ HDassert(space);
+ HDassert(buf);
+
+ if(NULL == (type = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an valid base datatype")
+
+ /* Get the allocation info */
+ if(H5CX_get_vlen_alloc_info(&vl_alloc_info) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to retrieve VL allocation info")
+
+ /* Call H5S_select_iterate with args, etc. */
+ dset_op.op_type = H5S_SEL_ITER_OP_LIB;
+ dset_op.u.lib_op = H5T_reclaim_cb;
+
+ ret_value = H5S_select_iterate(buf, type, space, &dset_op, &vl_alloc_info);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T_reclaim() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5T_reclaim_cb
+ *
+ * Purpose: Iteration callback to reclaim conversion allocated memory for a
+ * buffer element.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5T_reclaim_cb(void *elem, const H5T_t *dt, unsigned H5_ATTR_UNUSED ndim,
+ const hsize_t H5_ATTR_UNUSED *point, void *op_data)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* Sanity check */
+ HDassert(elem);
+ HDassert(dt);
+
+ if(dt->shared->type == H5T_REFERENCE) {
+ if(H5T_ref_reclaim(elem, dt) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "can't reclaim ref elements")
+ } else {
+ HDassert(op_data);
+
+ /* Allow vlen reclaim to recurse into that routine */
+ if(H5T_vlen_reclaim(elem, dt, (H5T_vlen_alloc_info_t *)op_data) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "can't reclaim vlen elements")
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T_reclaim_cb() */
diff --git a/src/H5Tdbg.c b/src/H5Tdbg.c
index eb648f3..605310a 100644
--- a/src/H5Tdbg.c
+++ b/src/H5Tdbg.c
@@ -416,7 +416,7 @@ H5T_debug(const H5T_t *dt, FILE *stream)
HDfprintf(stream, "\n\"%s\" = 0x", dt->shared->u.enumer.name[i]);
for (k = 0; k < base_size; k++)
- HDfprintf(stream, "%02lx", (unsigned long)(dt->shared->u.enumer.value + (i * base_size) + k));
+ HDfprintf(stream, "%02lx", (unsigned long)((uint8_t *)dt->shared->u.enumer.value + (i * base_size) + k));
} /* end for */
HDfprintf(stream, "\n");
}
diff --git a/src/H5Tdeprec.c b/src/H5Tdeprec.c
index a7f54a7..6ee0cd7 100644
--- a/src/H5Tdeprec.c
+++ b/src/H5Tdeprec.c
@@ -43,6 +43,7 @@
#include "H5Iprivate.h" /* IDs */
#include "H5Ppublic.h" /* Property Lists */
#include "H5Tpkg.h" /* Datatypes */
+#include "H5VLprivate.h" /* Virtual Object Layer */
/****************/
@@ -79,6 +80,12 @@
/* Local Variables */
/*******************/
+/* Declare a free list to manage the H5VL_t struct */
+H5FL_EXTERN(H5VL_t);
+
+/* Declare a free list to manage the H5VL_object_t struct */
+H5FL_EXTERN(H5VL_object_t);
+
#ifndef H5_NO_DEPRECATED_SYMBOLS
@@ -100,29 +107,49 @@
herr_t
H5Tcommit1(hid_t loc_id, const char *name, hid_t type_id)
{
- H5G_loc_t loc; /* Location to create datatype */
- H5T_t *type; /* Datatype for ID */
+ void *data = NULL; /* VOL-managed datatype data */
+ H5VL_object_t *new_obj = NULL; /* VOL object that holds the datatype object and the VOL info */
+ H5T_t *dt = NULL; /* High level datatype object that wraps the VOL object */
+ H5VL_object_t *vol_obj = NULL; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE3("e", "i*si", loc_id, name, type_id);
/* Check arguments */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!name || !*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name")
- if(NULL == (type = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
+ if(NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
+ if(H5T_is_named(dt))
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTSET, FAIL, "datatype is already committed")
/* Set up collective metadata if appropriate */
if(H5CX_set_loc(loc_id) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "can't set access property list info")
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* get the object from the loc_id */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier")
+
/* Commit the datatype */
- if(H5T__commit_named(&loc, name, type, H5P_LINK_CREATE_DEFAULT, H5P_DATATYPE_CREATE_DEFAULT) < 0)
+ if(NULL == (data = H5VL_datatype_commit(vol_obj, &loc_params, name, type_id, H5P_LINK_CREATE_DEFAULT, H5P_DATATYPE_CREATE_DEFAULT, H5P_DATATYPE_ACCESS_DEFAULT, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to commit datatype")
+ /* Set up VOL object */
+ if(NULL == (new_obj = H5FL_CALLOC(H5VL_object_t)))
+ HGOTO_ERROR(H5E_VOL, H5E_NOSPACE, FAIL, "can't allocate top object structure")
+ new_obj->connector = vol_obj->connector;
+ new_obj->connector->nrefs ++;
+ new_obj->data = data;
+
+ /* Set the committed type object to the VOL connector pointer in the H5T_t struct */
+ dt->vol_obj = new_obj;
+
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Tcommit1() */
@@ -147,31 +174,37 @@ done:
hid_t
H5Topen1(hid_t loc_id, const char *name)
{
- H5T_t *type = NULL;
- H5G_loc_t loc;
+ void *dt = NULL; /* Datatype token created by VOL connector */
+ H5VL_object_t *vol_obj = NULL; /* Object token of loc_id */
+ H5VL_loc_params_t loc_params;
hid_t ret_value = H5I_INVALID_HID; /* Return value */
FUNC_ENTER_API(H5I_INVALID_HID)
H5TRACE2("i", "i*s", loc_id, name);
/* Check args */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a location")
if(!name || !*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "no name")
+ loc_params.type = H5VL_OBJECT_BY_SELF;
+ loc_params.obj_type = H5I_get_type(loc_id);
+
+ /* Get the location object */
+ if(NULL == (vol_obj = (H5VL_object_t *)H5I_object(loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier")
+
/* Open the datatype */
- if(NULL == (type = H5T__open_name(&loc, name)))
+ if(NULL == (dt = H5VL_datatype_open(vol_obj, &loc_params, name, H5P_DATATYPE_ACCESS_DEFAULT, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open named datatype")
/* Register the type and return the ID */
- if((ret_value = H5I_register(H5I_DATATYPE, type, TRUE)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register named datatype")
+ if((ret_value = H5VL_register(H5I_DATATYPE, dt, vol_obj->connector, TRUE)) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register named datatype")
done:
/* Cleanup on error */
if(H5I_INVALID_HID == ret_value)
- if(type && H5T_close(type) < 0)
+ if(dt && H5VL_datatype_close(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
HDONE_ERROR(H5E_DATATYPE, H5E_CLOSEERROR, H5I_INVALID_HID, "unable to close datatype")
FUNC_LEAVE_API(ret_value)
diff --git a/src/H5Tenum.c b/src/H5Tenum.c
index 0ed1775..6daa497 100644
--- a/src/H5Tenum.c
+++ b/src/H5Tenum.c
@@ -187,9 +187,7 @@ herr_t
H5T__enum_insert(const H5T_t *dt, const char *name, const void *value)
{
unsigned i;
- char **names=NULL;
- uint8_t *values=NULL;
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
@@ -198,15 +196,17 @@ H5T__enum_insert(const H5T_t *dt, const char *name, const void *value)
HDassert(value);
/* The name and value had better not already exist */
- for (i=0; i<dt->shared->u.enumer.nmembs; i++) {
- if (!HDstrcmp(dt->shared->u.enumer.name[i], name))
+ for(i = 0; i < dt->shared->u.enumer.nmembs; i++) {
+ if(!HDstrcmp(dt->shared->u.enumer.name[i], name))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "name redefinition")
- if (!HDmemcmp(dt->shared->u.enumer.value+i*dt->shared->size, value, dt->shared->size))
+ if(!HDmemcmp((uint8_t *)dt->shared->u.enumer.value + (i * dt->shared->size), value, dt->shared->size))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "value redefinition")
- }
+ } /* end for */
/* Increase table sizes */
if(dt->shared->u.enumer.nmembs >= dt->shared->u.enumer.nalloc) {
+ char **names;
+ uint8_t *values;
unsigned n = MAX(32, 2*dt->shared->u.enumer.nalloc);
if(NULL == (names = (char **)H5MM_realloc(dt->shared->u.enumer.name, n * sizeof(char *))))
@@ -217,13 +217,13 @@ H5T__enum_insert(const H5T_t *dt, const char *name, const void *value)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
dt->shared->u.enumer.value = values;
dt->shared->u.enumer.nalloc = n;
- }
+ } /* end for */
/* Insert new member at end of member arrays */
dt->shared->u.enumer.sorted = H5T_SORT_NONE;
i = dt->shared->u.enumer.nmembs++;
dt->shared->u.enumer.name[i] = H5MM_xstrdup(name);
- HDmemcpy(dt->shared->u.enumer.value+i*dt->shared->size, value, dt->shared->size);
+ H5MM_memcpy((uint8_t *)dt->shared->u.enumer.value + (i * dt->shared->size), value, dt->shared->size);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -298,7 +298,7 @@ H5T__get_member_value(const H5T_t *dt, unsigned membno, void *value/*out*/)
HDassert(dt);
HDassert(value);
- HDmemcpy(value, dt->shared->u.enumer.value + membno*dt->shared->size, dt->shared->size);
+ H5MM_memcpy(value, (uint8_t *)dt->shared->u.enumer.value + (membno * dt->shared->size), dt->shared->size);
FUNC_LEAVE_NOAPI(SUCCEED)
}
@@ -416,7 +416,7 @@ H5T_enum_nameof(const H5T_t *dt, const void *value, char *name/*out*/, size_t si
rt = copied_dt->shared->u.enumer.nmembs;
while(lt < rt) {
md = (lt + rt) / 2;
- cmp = HDmemcmp(value, copied_dt->shared->u.enumer.value + md * copied_dt->shared->size, copied_dt->shared->size);
+ cmp = HDmemcmp(value, (uint8_t *)copied_dt->shared->u.enumer.value + (md * copied_dt->shared->size), copied_dt->shared->size);
if(cmp < 0)
rt = md;
else if(cmp > 0)
@@ -569,7 +569,7 @@ H5T_enum_valueof(const H5T_t *dt, const char *name, void *value/*out*/)
if (cmp!=0)
HGOTO_ERROR(H5E_DATATYPE, H5E_NOTFOUND, FAIL, "string doesn't exist in the enumeration type")
- HDmemcpy(value, copied_dt->shared->u.enumer.value+md*copied_dt->shared->size, copied_dt->shared->size);
+ H5MM_memcpy(value, (uint8_t *)copied_dt->shared->u.enumer.value + (md * copied_dt->shared->size), copied_dt->shared->size);
done:
if(copied_dt)
diff --git a/src/H5Tfields.c b/src/H5Tfields.c
index be62d85..be0b5f2 100644
--- a/src/H5Tfields.c
+++ b/src/H5Tfields.c
@@ -344,17 +344,17 @@ H5T__sort_value(const H5T_t *dt, int *map)
HDassert(size <= sizeof(tbuf));
for(i = (nmembs - 1), swapped = TRUE; i > 0 && swapped; --i) {
for(j = 0, swapped = FALSE; j < i; j++) {
- if(HDmemcmp(dt->shared->u.enumer.value + (j * size), dt->shared->u.enumer.value + ((j + 1) * size), size) > 0) {
+ if(HDmemcmp((uint8_t *)dt->shared->u.enumer.value + (j * size), (uint8_t *)dt->shared->u.enumer.value + ((j + 1) * size), size) > 0) {
/* Swap names */
char *tmp = dt->shared->u.enumer.name[j];
dt->shared->u.enumer.name[j] = dt->shared->u.enumer.name[j + 1];
dt->shared->u.enumer.name[j + 1] = tmp;
/* Swap values */
- HDmemcpy(tbuf, dt->shared->u.enumer.value + (j * size), size);
- HDmemcpy(dt->shared->u.enumer.value + (j * size),
- dt->shared->u.enumer.value + ((j + 1) * size), size);
- HDmemcpy(dt->shared->u.enumer.value + ((j + 1) * size), tbuf, size);
+ H5MM_memcpy(tbuf, (uint8_t *)dt->shared->u.enumer.value + (j * size), size);
+ H5MM_memcpy((uint8_t *)dt->shared->u.enumer.value + (j * size),
+ (uint8_t *)dt->shared->u.enumer.value + ((j + 1) * size), size);
+ H5MM_memcpy((uint8_t *)dt->shared->u.enumer.value + ((j + 1) * size), tbuf, size);
/* Swap map */
if(map) {
@@ -371,7 +371,7 @@ H5T__sort_value(const H5T_t *dt, int *map)
#ifndef NDEBUG
/* I never trust a sort :-) -RPM */
for(i = 0; i < (nmembs - 1); i++)
- HDassert(HDmemcmp(dt->shared->u.enumer.value + (i * size), dt->shared->u.enumer.value + ((i + 1) * size), size) < 0);
+ HDassert(HDmemcmp((uint8_t *)dt->shared->u.enumer.value + (i * size), (uint8_t *)dt->shared->u.enumer.value + ((i + 1) * size), size) < 0);
#endif
} /* end if */
} /* end else */
@@ -457,10 +457,10 @@ H5T__sort_name(const H5T_t *dt, int *map)
dt->shared->u.enumer.name[j+1] = tmp;
/* Swap values */
- HDmemcpy(tbuf, dt->shared->u.enumer.value+j*size, size);
- HDmemcpy(dt->shared->u.enumer.value+j*size,
- dt->shared->u.enumer.value+(j+1)*size, size);
- HDmemcpy(dt->shared->u.enumer.value+(j+1)*size, tbuf, size);
+ H5MM_memcpy(tbuf, (uint8_t *)dt->shared->u.enumer.value + (j * size), size);
+ H5MM_memcpy((uint8_t *)dt->shared->u.enumer.value + (j * size),
+ (uint8_t *)dt->shared->u.enumer.value + ((j + 1) * size), size);
+ H5MM_memcpy((uint8_t *)dt->shared->u.enumer.value + ((j + 1) * size), tbuf, size);
/* Swap map */
if (map) {
diff --git a/src/H5Tnative.c b/src/H5Tnative.c
index c9ad01a..1d203c7 100644
--- a/src/H5Tnative.c
+++ b/src/H5Tnative.c
@@ -126,7 +126,6 @@ static H5T_t *
H5T__get_native_type(H5T_t *dtype, H5T_direction_t direction, size_t *struct_align,
size_t *offset, size_t *comp_size)
{
- H5T_t *dt; /* Datatype to make native */
H5T_t *super_type; /* Super type of VL, array and enum datatypes */
H5T_t *nat_super_type; /* Native form of VL, array & enum super datatype */
H5T_t *new_type = NULL; /* New native datatype */
@@ -218,26 +217,36 @@ H5T__get_native_type(H5T_t *dtype, H5T_direction_t direction, size_t *struct_ali
case H5T_REFERENCE:
{
+ H5T_t *dt; /* Datatype to make native */
size_t align;
size_t ref_size;
- int not_equal;
if(NULL == (ret_value = H5T_copy(dtype, H5T_COPY_TRANSIENT)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot retrieve float type")
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot copy reference type")
- /* Decide if the data type is object or dataset region reference. */
+ /* Decide if the data type is object reference. */
if(NULL == (dt = (H5T_t *)H5I_object(H5T_STD_REF_OBJ_g)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a data type")
- not_equal = H5T_cmp(ret_value, dt, FALSE);
/* Update size, offset and compound alignment for parent. */
- if(!not_equal) {
+ if(0 == H5T_cmp(ret_value, dt, FALSE)) {
align = H5T_HOBJREF_COMP_ALIGN_g;
ref_size = sizeof(hobj_ref_t);
} /* end if */
else {
- align = H5T_HDSETREGREF_COMP_ALIGN_g;
- ref_size = sizeof(hdset_reg_ref_t);
+ /* Decide if the data type is dataset region reference. */
+ if(NULL == (dt = (H5T_t *)H5I_object(H5T_STD_REF_DSETREG_g)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a data type")
+
+ if (0 == H5T_cmp(ret_value, dt, FALSE)) {
+ align = H5T_HDSETREGREF_COMP_ALIGN_g;
+ ref_size = sizeof(hdset_reg_ref_t);
+ } /* end if */
+ else {
+ /* Only pointers to underlying opaque reference types */
+ align = H5T_REF_COMP_ALIGN_g;
+ ref_size = sizeof(H5R_ref_t);
+ } /* end else */
} /* end else */
if(H5T__cmp_offset(comp_size, offset, ref_size, (size_t)1, align, struct_align) < 0)
@@ -369,7 +378,7 @@ H5T__get_native_type(H5T_t *dtype, H5T_direction_t direction, size_t *struct_ali
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot get member name")
if(H5T__get_member_value(dtype, u, tmp_memb_value) < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot get member value")
- HDmemcpy(memb_value, tmp_memb_value, H5T_get_size(super_type));
+ H5MM_memcpy(memb_value, tmp_memb_value, H5T_get_size(super_type));
if(H5T_convert(tpath, super_type_id, nat_super_type_id, (size_t)1, (size_t)0, (size_t)0, memb_value, NULL) < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot get member value")
@@ -515,6 +524,14 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T__get_native_type() */
+/* Disable warning for intentional identical branches here -QAK */
+/*
+ * This pragma only needs to surround the "duplicated branches" in
+ * the code below, but early (4.4.7, at least) gcc only allows
+ * diagnostic pragmas to be toggled outside of functions.
+ */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wduplicated-branches"
/*-------------------------------------------------------------------------
* Function: H5T__get_native_integer
@@ -655,7 +672,16 @@ H5T__get_native_integer(size_t prec, H5T_sign_t sign, H5T_direction_t direction,
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T__get_native_integer() */
+#pragma GCC diagnostic pop
+/* Disable warning for intentional identical branches here -QAK */
+/*
+ * This pragma only needs to surround the "duplicated branches" in
+ * the code below, but early (4.4.7, at least) gcc only allows
+ * diagnostic pragmas to be toggled outside of functions.
+ */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wduplicated-branches"
/*-------------------------------------------------------------------------
* Function: H5T__get_native_float
@@ -780,7 +806,16 @@ H5T__get_native_float(size_t size, H5T_direction_t direction, size_t *struct_ali
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T__get_native_float() */
+#pragma GCC diagnostic pop
+/* Disable warning for intentional identical branches here -QAK */
+/*
+ * This pragma only needs to surround the "duplicated branches" in
+ * the code below, but early (4.4.7, at least) gcc only allows
+ * diagnostic pragmas to be toggled outside of functions.
+ */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wduplicated-branches"
/*-------------------------------------------------------------------------
* Function: H5T__get_native_bitfield
@@ -866,6 +901,7 @@ H5T__get_native_bitfield(size_t prec, H5T_direction_t direction,
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T__get_native_bitfield() */
+#pragma GCC diagnostic pop
/*-------------------------------------------------------------------------
diff --git a/src/H5Toh.c b/src/H5Toh.c
index c5ee994..ab6c09f 100644
--- a/src/H5Toh.c
+++ b/src/H5Toh.c
@@ -44,7 +44,7 @@
/********************/
static htri_t H5O__dtype_isa(const H5O_t *loc);
-static hid_t H5O__dtype_open(const H5G_loc_t *obj_loc, hbool_t app_ref);
+static void *H5O__dtype_open(const H5G_loc_t *obj_loc, H5I_type_t *opened_type);
static void *H5O__dtype_create(H5F_t *f, void *_crt_info, H5G_loc_t *obj_loc);
static H5O_loc_t *H5O__dtype_get_oloc(hid_t obj_id);
@@ -125,28 +125,28 @@ done:
*
*-------------------------------------------------------------------------
*/
-static hid_t
-H5O__dtype_open(const H5G_loc_t *obj_loc, hbool_t app_ref)
+static void *
+H5O__dtype_open(const H5G_loc_t *obj_loc, H5I_type_t *opened_type)
{
- H5T_t *type = NULL; /* Datatype opened */
- hid_t ret_value = H5I_INVALID_HID; /* Return value */
+ H5T_t *type = NULL; /* Datatype opened */
+ void *ret_value = NULL; /* Return value */
FUNC_ENTER_STATIC
HDassert(obj_loc);
+ *opened_type = H5I_DATATYPE;
+
/* Open the datatype */
if(NULL == (type = H5T_open(obj_loc)))
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, FAIL, "unable to open datatype")
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to open datatype")
- /* Register an ID for the datatype */
- if((ret_value = H5I_register(H5I_DATATYPE, type, app_ref)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register datatype")
+ ret_value = (void *)type;
done:
- if(ret_value < 0)
+ if(NULL == ret_value)
if(type && H5T_close(type) < 0)
- HDONE_ERROR(H5E_DATATYPE, H5E_CLOSEERROR, FAIL, "unable to release datatype")
+ HDONE_ERROR(H5E_DATATYPE, H5E_CLOSEERROR, NULL, "unable to release datatype")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O__dtype_open() */
@@ -212,15 +212,19 @@ done:
static H5O_loc_t *
H5O__dtype_get_oloc(hid_t obj_id)
{
- H5T_t *type; /* Datatype opened */
+ H5T_t *type = NULL; /* Datatype opened */
+ H5T_t *dt = NULL;
H5O_loc_t *ret_value = NULL; /* Return value */
FUNC_ENTER_STATIC
/* Get the datatype */
- if(NULL == (type = (H5T_t *)H5I_object(obj_id)))
+ if(NULL == (dt = (H5T_t *)H5I_object(obj_id)))
HGOTO_ERROR(H5E_OHDR, H5E_BADATOM, NULL, "couldn't get object from ID")
+ /* If this is a named datatype, get the VOL driver pointer to the datatype */
+ type = (H5T_t *)H5T_get_actual_type(dt);
+
/* Get the datatype's object header location */
if(NULL == (ret_value = H5T_oloc(type)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "unable to get object location from object")
diff --git a/src/H5Torder.c b/src/H5Torder.c
index 1995a03..62662d6 100644
--- a/src/H5Torder.c
+++ b/src/H5Torder.c
@@ -100,11 +100,11 @@ H5Tget_order(hid_t type_id)
/* Check args */
if(NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
- HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, H5T_ORDER_ERROR, "not a datatype")
+ HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, H5T_ORDER_ERROR, "not a datatype")
/* Get order */
if(H5T_ORDER_ERROR == (ret_value = H5T_get_order(dt)))
- HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, H5T_ORDER_ERROR, "cant't get order for specified datatype")
+ HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, H5T_ORDER_ERROR, "can't get order for specified datatype")
done:
FUNC_LEAVE_API(ret_value)
@@ -210,6 +210,8 @@ H5Tset_order(hid_t type_id, H5T_order_t order)
HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "not a datatype")
if(order < H5T_ORDER_LE || order > H5T_ORDER_NONE || order == H5T_ORDER_MIXED)
HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, "illegal byte order")
+ if(NULL != dt->vol_obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTSET, FAIL, "datatype is already committed")
if(H5T_STATE_TRANSIENT != dt->shared->state)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "datatype is read-only")
diff --git a/src/H5Tpkg.h b/src/H5Tpkg.h
index 04e9451..9784abd 100644
--- a/src/H5Tpkg.h
+++ b/src/H5Tpkg.h
@@ -95,9 +95,14 @@
/* This version also encodes array types more efficiently */
#define H5O_DTYPE_VERSION_3 3
+/* This is the version that adds support for new reference types and prevents
+ * older versions of the library to attempt reading unknown types.
+ */
+#define H5O_DTYPE_VERSION_4 4
+
/* The latest version of the format. Look through the 'encode helper' routine
* and 'size' callback for places to change when updating this. */
-#define H5O_DTYPE_VERSION_LATEST H5O_DTYPE_VERSION_3
+#define H5O_DTYPE_VERSION_LATEST H5O_DTYPE_VERSION_4
/* Flags for visiting datatype */
@@ -175,37 +180,52 @@ struct H5T_path_t {
H5T_cdata_t cdata; /*data for this function */
};
+/* Reference function pointers */
+typedef size_t (*H5T_ref_getsizefunc_t)(H5F_t *src_f, const void *src_buf, size_t src_size, H5F_t *dst_f, hbool_t *dst_copy);
+typedef herr_t (*H5T_ref_readfunc_t)(H5F_t *src_f, const void *src_buf, size_t src_size, H5F_t *dst_f, void *dst_buf, size_t dst_size);
+typedef herr_t (*H5T_ref_writefunc_t)(H5F_t *src_f, const void *src_buf, size_t src_size, H5R_type_t src_type, H5F_t *dst_f, void *dst_buf, size_t dst_size, void *bg_buf);
+
+typedef struct H5T_ref_class_t {
+ H5T_ref_getsizefunc_t getsize; /* get reference size (bytes) */
+ H5T_ref_readfunc_t read; /* read reference into buffer */
+ H5T_ref_writefunc_t write; /* write reference from buffer */
+} H5T_ref_class_t;
+
typedef struct H5T_atomic_t {
- H5T_order_t order; /*byte order */
- size_t prec; /*precision in bits */
- size_t offset; /*bit position of lsb of value */
- H5T_pad_t lsb_pad;/*type of lsb padding */
- H5T_pad_t msb_pad;/*type of msb padding */
+ H5T_order_t order; /* byte order */
+ size_t prec; /* precision in bits */
+ size_t offset; /* bit position of lsb of value */
+ H5T_pad_t lsb_pad; /* type of lsb padding */
+ H5T_pad_t msb_pad; /* type of msb padding */
union {
- struct {
- H5T_sign_t sign; /*type of integer sign */
- } i; /*integer; integer types */
-
- struct {
- size_t sign; /*bit position of sign bit */
- size_t epos; /*position of lsb of exponent */
- size_t esize; /*size of exponent in bits */
- uint64_t ebias; /*exponent bias */
- size_t mpos; /*position of lsb of mantissa */
- size_t msize; /*size of mantissa */
- H5T_norm_t norm; /*normalization */
- H5T_pad_t pad; /*type of padding for internal bits */
- } f; /*floating-point types */
-
- struct {
- H5T_cset_t cset; /*character set */
- H5T_str_t pad; /*space or null padding of extra bytes */
- } s; /*string types */
-
- struct {
- H5R_type_t rtype; /*type of reference stored */
- H5T_loc_t loc; /* Location of data in buffer */
- } r; /*reference types */
+ struct {
+ H5T_sign_t sign; /* type of integer sign */
+ } i; /* integer; integer types */
+
+ struct {
+ size_t sign; /* bit position of sign bit */
+ size_t epos; /* position of lsb of exponent */
+ size_t esize; /* size of exponent in bits */
+ uint64_t ebias; /* exponent bias */
+ size_t mpos; /* position of lsb of mantissa */
+ size_t msize; /* size of mantissa */
+ H5T_norm_t norm; /* normalization */
+ H5T_pad_t pad; /* type of padding for internal bits */
+ } f; /* floating-point types */
+
+ struct {
+ H5T_cset_t cset; /* character set */
+ H5T_str_t pad; /* space or null padding of extra bytes */
+ } s; /* string types */
+
+ struct {
+ H5R_type_t rtype; /* type of reference stored */
+ unsigned version; /* version of encoded reference */
+ hbool_t opaque; /* opaque reference type */
+ H5T_loc_t loc; /* location of data in buffer */
+ H5F_t *f; /* file pointer (if data is on disk) */
+ const H5T_ref_class_t *cls; /* Pointer to ref class callbacks */
+ } r; /* reference types */
} u;
} H5T_atomic_t;
@@ -239,18 +259,10 @@ typedef struct H5T_enum_t {
unsigned nalloc; /*num entries allocated */
unsigned nmembs; /*number of members defined in enum */
H5T_sort_t sorted; /*how are members sorted? */
- uint8_t *value; /*array of values */
+ void *value; /*array of values */
char **name; /*array of symbol names */
} H5T_enum_t;
-/* VL function pointers */
-typedef ssize_t (*H5T_vlen_getlenfunc_t)(const void *vl_addr);
-typedef void * (*H5T_vlen_getptrfunc_t)(void *vl_addr);
-typedef htri_t (*H5T_vlen_isnullfunc_t)(const H5F_t *f, void *vl_addr);
-typedef herr_t (*H5T_vlen_readfunc_t)(H5F_t *f, void *_vl, void *buf, size_t len);
-typedef herr_t (*H5T_vlen_writefunc_t)(H5F_t *f, const H5T_vlen_alloc_info_t *vl_alloc_info, void *_vl, void *buf, void *_bg, size_t seq_len, size_t base_size);
-typedef herr_t (*H5T_vlen_setnullfunc_t)(H5F_t *f, void *_vl, void *_bg);
-
/* VL types */
typedef enum {
H5T_VLEN_BADTYPE = -1, /* invalid VL Type */
@@ -259,20 +271,35 @@ typedef enum {
H5T_VLEN_MAXTYPE /* highest type (Invalid as true type) */
} H5T_vlen_type_t;
+/* VL function pointers */
+typedef herr_t (*H5T_vlen_getlen_func_t)(H5F_t *f, const void *vl_addr, size_t *len);
+typedef void * (*H5T_vlen_getptr_func_t)(void *vl_addr);
+typedef herr_t (*H5T_vlen_isnull_func_t)(const H5F_t *f, void *vl_addr, hbool_t *isnull);
+typedef herr_t (*H5T_vlen_setnull_func_t)(H5F_t *f, void *_vl, void *_bg);
+typedef herr_t (*H5T_vlen_read_func_t)(H5F_t *f, void *_vl, void *buf, size_t len);
+typedef herr_t (*H5T_vlen_write_func_t)(H5F_t *f, const H5T_vlen_alloc_info_t *vl_alloc_info, void *_vl, void *buf, void *_bg, size_t seq_len, size_t base_size);
+typedef herr_t (*H5T_vlen_delete_func_t)(H5F_t *f, const void *_vl);
+
+/* VL datatype callbacks */
+typedef struct H5T_vlen_class_t {
+ H5T_vlen_getlen_func_t getlen; /* Function to get VL sequence size (in element units, not bytes) */
+ H5T_vlen_getptr_func_t getptr; /* Function to get VL sequence pointer */
+ H5T_vlen_isnull_func_t isnull; /* Function to check if VL value is NIL */
+ H5T_vlen_setnull_func_t setnull;/* Function to set a VL value to NIL */
+ H5T_vlen_read_func_t read; /* Function to read VL sequence into buffer */
+ H5T_vlen_write_func_t write; /* Function to write VL sequence from buffer */
+ H5T_vlen_delete_func_t del; /* Function to delete VL sequence */
+} H5T_vlen_class_t;
+
/* A VL datatype */
typedef struct H5T_vlen_t {
H5T_vlen_type_t type; /* Type of VL data in buffer */
H5T_loc_t loc; /* Location of VL data in buffer */
- H5T_cset_t cset; /* For VL string. character set */
- H5T_str_t pad; /* For VL string. space or null padding of
+ H5T_cset_t cset; /* For VL string: character set */
+ H5T_str_t pad; /* For VL string: space or null padding of
* extra bytes */
H5F_t *f; /* File ID (if VL data is on disk) */
- H5T_vlen_getptrfunc_t getptr; /* Function to get VL sequence pointer */
- H5T_vlen_getlenfunc_t getlen; /* Function to get VL sequence size (in element units, not bytes) */
- H5T_vlen_isnullfunc_t isnull; /* Function to check if VL value is NIL */
- H5T_vlen_readfunc_t read; /* Function to read VL sequence into buffer */
- H5T_vlen_writefunc_t write; /* Function to write VL sequence from buffer */
- H5T_vlen_setnullfunc_t setnull; /* Function to set a VL value to NIL */
+ const H5T_vlen_class_t *cls; /* Pointer to VL class callbacks */
} H5T_vlen_t;
/* An opaque datatype */
@@ -320,6 +347,7 @@ struct H5T_t {
H5T_shared_t *shared; /* all other information */
H5O_loc_t oloc; /* Object location, if the type is a named type */
H5G_name_t path; /* group hier. path if the type is a named type */
+ H5VL_object_t *vol_obj; /* pointer to VOL object when working with committed datatypes */
};
/* The master list of soft conversion functions */
@@ -370,6 +398,7 @@ H5_DLLVAR size_t H5T_POINTER_COMP_ALIGN_g;
H5_DLLVAR size_t H5T_HVL_COMP_ALIGN_g;
H5_DLLVAR size_t H5T_HOBJREF_COMP_ALIGN_g;
H5_DLLVAR size_t H5T_HDSETREGREF_COMP_ALIGN_g;
+H5_DLLVAR size_t H5T_REF_COMP_ALIGN_g;
/*
* Alignment information for native types. A value of N indicates that the
@@ -482,6 +511,9 @@ H5_DLL herr_t H5T__conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
H5_DLL herr_t H5T__conv_array(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
size_t nelmts, size_t buf_stride,
size_t bkg_stride, void *buf, void *bkg);
+H5_DLL herr_t H5T__conv_ref(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
+ size_t nelmts, size_t buf_stride,
+ size_t bkg_stride, void *buf, void *bkg);
H5_DLL herr_t H5T__conv_i_i(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
size_t nelmts, size_t buf_stride,
size_t bkg_stride, void *_buf, void *bkg);
@@ -1148,6 +1180,9 @@ H5_DLL H5T_t *H5T__array_create(H5T_t *base, unsigned ndims, const hsize_t dim[/
H5_DLL int H5T__get_array_ndims(const H5T_t *dt);
H5_DLL int H5T__get_array_dims(const H5T_t *dt, hsize_t dims[]);
+/* Reference functions */
+H5_DLL htri_t H5T__ref_set_loc(const H5T_t *dt, H5F_t *f, H5T_loc_t loc);
+
/* Compound functions */
H5_DLL herr_t H5T__insert(H5T_t *parent, const char *name, size_t offset,
const H5T_t *member);
diff --git a/src/H5Tprecis.c b/src/H5Tprecis.c
index 59bac8b..bd28fc2 100644
--- a/src/H5Tprecis.c
+++ b/src/H5Tprecis.c
@@ -154,6 +154,8 @@ H5Tset_precision(hid_t type_id, size_t prec)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
if (H5T_STATE_TRANSIENT!=dt->shared->state)
HGOTO_ERROR(H5E_ARGS, H5E_CANTSET, FAIL, "datatype is read-only")
+ if (NULL != dt->vol_obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTSET, FAIL, "datatype is committed")
if (prec == 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "precision must be positive")
if (H5T_ENUM==dt->shared->type && dt->shared->u.enumer.nmembs>0)
diff --git a/src/H5Tprivate.h b/src/H5Tprivate.h
index 541fd29..8cd2fd1 100644
--- a/src/H5Tprivate.h
+++ b/src/H5Tprivate.h
@@ -30,6 +30,7 @@ typedef struct H5T_t H5T_t;
#include "H5private.h" /* Generic Functions */
#include "H5Gprivate.h" /* Groups */
#include "H5Rprivate.h" /* References */
+#include "H5VLprivate.h" /* VOL Drivers */
/* Macro for size of temporary buffers to contain a single element */
#define H5T_ELEM_BUF_SIZE 256
@@ -51,6 +52,9 @@ typedef struct H5T_t H5T_t;
typedef struct H5T_stats_t H5T_stats_t;
typedef struct H5T_path_t H5T_path_t;
+/* Forward reference of H5S_t */
+struct H5S_t;
+
/* How to copy a datatype */
typedef enum H5T_copy_t {
H5T_COPY_TRANSIENT,
@@ -98,7 +102,7 @@ typedef struct H5T_subset_info_t {
} H5T_subset_info_t;
/* Forward declarations for prototype arguments */
-struct H5O_t;
+struct H5O_shared_t;
/* The native endianness of the platform */
H5_DLLVAR H5T_order_t H5T_native_order_g;
@@ -118,7 +122,7 @@ H5_DLL herr_t H5T_encode(H5T_t *obj, unsigned char *buf, size_t *nalloc);
H5_DLL H5T_t *H5T_decode(size_t buf_size, const unsigned char *buf);
H5_DLL herr_t H5T_debug(const H5T_t *dt, FILE * stream);
H5_DLL struct H5O_loc_t *H5T_oloc(H5T_t *dt);
-H5_DLL H5G_name_t *H5T_nameof(H5T_t *dt);
+H5_DLL H5G_name_t *H5T_nameof(const H5T_t *dt);
H5_DLL htri_t H5T_is_immutable(const H5T_t *dt);
H5_DLL htri_t H5T_is_named(const H5T_t *dt);
H5_DLL herr_t H5T_convert_committed_datatype(H5T_t *dt, H5F_t *f);
@@ -129,7 +133,10 @@ H5_DLL H5T_bkg_t H5T_path_bkg(const H5T_path_t *p);
H5_DLL H5T_subset_info_t *H5T_path_compound_subset(const H5T_path_t *p);
H5_DLL herr_t H5T_convert(H5T_path_t *tpath, hid_t src_id, hid_t dst_id,
size_t nelmts, size_t buf_stride, size_t bkg_stride, void *buf, void *bkg);
-H5_DLL herr_t H5T_vlen_reclaim(void *elem, hid_t type_id, unsigned ndim, const hsize_t *point, void *_op_data);
+H5_DLL herr_t H5T_reclaim(hid_t type_id, struct H5S_t *space, void *buf);
+H5_DLL herr_t H5T_reclaim_cb(void *elem, const H5T_t *dt, unsigned ndim, const hsize_t *point, void *op_data);
+H5_DLL herr_t H5T_ref_reclaim(void *elem, const H5T_t *dt);
+H5_DLL herr_t H5T_vlen_reclaim(void *elem, const H5T_t *dt, H5T_vlen_alloc_info_t *alloc_info);
H5_DLL herr_t H5T_vlen_reclaim_elmt(void *elem, H5T_t *dt);
H5_DLL htri_t H5T_set_loc(H5T_t *dt, H5F_t *f, H5T_loc_t loc);
H5_DLL htri_t H5T_is_sensible(const H5T_t *dt);
@@ -138,6 +145,13 @@ H5_DLL herr_t H5T_set_version(H5F_t *f, H5T_t *dt);
H5_DLL herr_t H5T_patch_file(H5T_t *dt, H5F_t *f);
H5_DLL herr_t H5T_patch_vlen_file(H5T_t *dt, H5F_t *f);
H5_DLL htri_t H5T_is_variable_str(const H5T_t *dt);
+H5_DLL H5T_t *H5T_construct_datatype(H5VL_object_t *dt_obj);
+H5_DLL H5VL_object_t *H5T_get_named_type(const H5T_t *dt);
+H5_DLL H5T_t *H5T_get_actual_type(H5T_t *dt);
+H5_DLL herr_t H5T_save_refresh_state(hid_t tid, struct H5O_shared_t *cached_H5O_shared);
+H5_DLL herr_t H5T_restore_refresh_state(hid_t tid, struct H5O_shared_t *cached_H5O_shared);
+H5_DLL hbool_t H5T_already_vol_managed(const H5T_t *dt);
+H5_DLL htri_t H5T_is_vl_storage(const H5T_t *dt);
/* Reference specific functions */
H5_DLL H5R_type_t H5T_get_ref_type(const H5T_t *dt);
diff --git a/src/H5Tpublic.h b/src/H5Tpublic.h
index fc3e4ee..0ec0c73 100644
--- a/src/H5Tpublic.h
+++ b/src/H5Tpublic.h
@@ -262,8 +262,9 @@ H5_DLLVAR hid_t H5T_IEEE_F64LE_g;
#define H5T_STD_B32LE (H5OPEN H5T_STD_B32LE_g)
#define H5T_STD_B64BE (H5OPEN H5T_STD_B64BE_g)
#define H5T_STD_B64LE (H5OPEN H5T_STD_B64LE_g)
-#define H5T_STD_REF_OBJ (H5OPEN H5T_STD_REF_OBJ_g)
+#define H5T_STD_REF_OBJ (H5OPEN H5T_STD_REF_OBJ_g)
#define H5T_STD_REF_DSETREG (H5OPEN H5T_STD_REF_DSETREG_g)
+#define H5T_STD_REF (H5OPEN H5T_STD_REF_g)
H5_DLLVAR hid_t H5T_STD_I8BE_g;
H5_DLLVAR hid_t H5T_STD_I8LE_g;
H5_DLLVAR hid_t H5T_STD_I16BE_g;
@@ -290,6 +291,7 @@ H5_DLLVAR hid_t H5T_STD_B64BE_g;
H5_DLLVAR hid_t H5T_STD_B64LE_g;
H5_DLLVAR hid_t H5T_STD_REF_OBJ_g;
H5_DLLVAR hid_t H5T_STD_REF_DSETREG_g;
+H5_DLLVAR hid_t H5T_STD_REF_g;
/*
* Types which are particular to Unix.
@@ -591,6 +593,7 @@ H5_DLL H5T_conv_t H5Tfind(hid_t src_id, hid_t dst_id, H5T_cdata_t **pcdata);
H5_DLL htri_t H5Tcompiler_conv(hid_t src_id, hid_t dst_id);
H5_DLL herr_t H5Tconvert(hid_t src_id, hid_t dst_id, size_t nelmts,
void *buf, void *background, hid_t plist_id);
+H5_DLL herr_t H5Treclaim(hid_t type_id, hid_t space_id, hid_t plist_id, void *buf);
/* Symbols defined for compatibility with previous versions of the HDF5 API.
*
diff --git a/src/H5Tref.c b/src/H5Tref.c
new file mode 100644
index 0000000..937dc92
--- /dev/null
+++ b/src/H5Tref.c
@@ -0,0 +1,768 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Module Info: This module contains the functionality for reference
+ * datatypes in the H5T interface.
+ */
+
+#include "H5Tmodule.h" /* This source code file is part of the H5T module */
+#define H5F_FRIEND /*suppress error about including H5Fpkg */
+#define H5R_FRIEND /*suppress error about including H5Rpkg */
+
+#include "H5private.h" /* Generic Functions */
+#include "H5CXprivate.h" /* API Contexts */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Iprivate.h" /* IDs */
+#include "H5Fpkg.h" /* File */
+#include "H5Rpkg.h" /* References */
+#include "H5Tpkg.h" /* Datatypes */
+
+/****************/
+/* Local Macros */
+/****************/
+
+#define H5T_REF_MEM_SIZE (H5R_REF_BUF_SIZE)
+#define H5T_REF_OBJ_MEM_SIZE (H5R_OBJ_REF_BUF_SIZE)
+#define H5T_REF_DSETREG_MEM_SIZE (H5R_DSET_REG_REF_BUF_SIZE)
+
+#define H5T_REF_OBJ_DISK_SIZE(f) (H5F_SIZEOF_ADDR(f))
+#define H5T_REF_DSETREG_DISK_SIZE(f) (H5HG_HEAP_ID_SIZE(f))
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+/* For region compatibility support */
+struct H5Tref_dsetreg {
+ H5VL_token_t token; /* Object token */
+ H5S_t *space; /* Dataspace */
+};
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+static size_t H5T__ref_mem_getsize(H5F_t *src_f, const void *src_buf, size_t src_size, H5F_t *dst_f, hbool_t *dst_copy);
+static herr_t H5T__ref_mem_read(H5F_t *src_f, const void *src_buf, size_t src_size, H5F_t *dst_f, void *dst_buf, size_t dst_size);
+static herr_t H5T__ref_mem_write(H5F_t *src_f, const void *src_buf, size_t src_size, H5R_type_t src_type, H5F_t *dst_f, void *dst_buf, size_t dst_size, void *bg_buf);
+
+static size_t H5T__ref_disk_getsize(H5F_t *src_f, const void *src_buf, size_t src_size, H5F_t *dst_f, hbool_t *dst_copy);
+static herr_t H5T__ref_disk_read(H5F_t *src_f, const void *src_buf, size_t src_size, H5F_t *dst_f, void *dst_buf, size_t dst_size);
+static herr_t H5T__ref_disk_write(H5F_t *src_f, const void *src_buf, size_t src_size, H5R_type_t src_type, H5F_t *dst_f, void *dst_buf, size_t dst_size, void *bg_buf);
+
+/* For compatibility */
+static size_t H5T__ref_obj_disk_getsize(H5F_t *src_f, const void *src_buf, size_t src_size, H5F_t *dst_f, hbool_t *dst_copy);
+static herr_t H5T__ref_obj_disk_read(H5F_t *src_f, const void *src_buf, size_t src_size, H5F_t *dst_f, void *dst_buf, size_t dst_size);
+
+static size_t H5T__ref_dsetreg_disk_getsize(H5F_t *src_f, const void *src_buf, size_t src_size, H5F_t *dst_f, hbool_t *dst_copy);
+static herr_t H5T__ref_dsetreg_disk_read(H5F_t *src_f, const void *src_buf, size_t src_size, H5F_t *dst_f, void *dst_buf, size_t dst_size);
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* Class for reference in memory */
+static const H5T_ref_class_t H5T_ref_mem_g = {
+ H5T__ref_mem_getsize, /* 'getsize' */
+ H5T__ref_mem_read, /* 'read' */
+ H5T__ref_mem_write /* 'write' */
+};
+
+static const H5T_ref_class_t H5T_ref_disk_g = {
+ H5T__ref_disk_getsize, /* 'getsize' */
+ H5T__ref_disk_read, /* 'read' */
+ H5T__ref_disk_write /* 'write' */
+};
+
+static const H5T_ref_class_t H5T_ref_obj_disk_g = {
+ H5T__ref_obj_disk_getsize, /* 'getsize' */
+ H5T__ref_obj_disk_read, /* 'read' */
+ NULL /* 'write' */
+};
+
+static const H5T_ref_class_t H5T_ref_dsetreg_disk_g = {
+ H5T__ref_dsetreg_disk_getsize, /* 'getsize' */
+ H5T__ref_dsetreg_disk_read, /* 'read' */
+ NULL /* 'write' */
+};
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5T__ref_set_loc
+ *
+ * Purpose: Sets the location of a reference datatype to be either on disk
+ * or in memory
+ *
+ * Return:
+ * One of two values on success:
+ * TRUE - If the location of any reference types changed
+ * FALSE - If the location of any reference types is the same
+ * Negative value is returned on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5T__ref_set_loc(const H5T_t *dt, H5F_t *f, H5T_loc_t loc)
+{
+ htri_t ret_value = FALSE; /* Indicate success, but no location change */
+
+ FUNC_ENTER_PACKAGE
+
+ HDassert(dt);
+ /* f is NULL when loc == H5T_LOC_MEMORY */
+ HDassert(loc >= H5T_LOC_BADLOC && loc < H5T_LOC_MAXLOC);
+
+ /* Only change the location if it's different */
+ if(loc == dt->shared->u.atomic.u.r.loc && f == dt->shared->u.atomic.u.r.f)
+ HGOTO_DONE(FALSE)
+
+ switch(loc) {
+ case H5T_LOC_MEMORY: /* Memory based reference datatype */
+ HDassert(NULL == f);
+
+ /* Mark this type as being stored in memory */
+ dt->shared->u.atomic.u.r.loc = H5T_LOC_MEMORY;
+
+ /* Reset file ID (since this reference is in memory) */
+ dt->shared->u.atomic.u.r.f = f; /* f is NULL */
+
+ if(dt->shared->u.atomic.u.r.opaque) {
+ /* Size in memory, disk size is different */
+ dt->shared->size = H5T_REF_MEM_SIZE;
+ dt->shared->u.atomic.prec = 8 * dt->shared->size;
+
+ /* Set up the function pointers to access the reference in memory */
+ dt->shared->u.atomic.u.r.cls = &H5T_ref_mem_g;
+
+ } else if(dt->shared->u.atomic.u.r.rtype == H5R_OBJECT1) {
+ /* Size in memory, disk size is different */
+ dt->shared->size = H5T_REF_OBJ_MEM_SIZE;
+ dt->shared->u.atomic.prec = 8 * dt->shared->size;
+
+ /* Unused for now */
+ dt->shared->u.atomic.u.r.cls = NULL;
+
+ } else if(dt->shared->u.atomic.u.r.rtype == H5R_DATASET_REGION1) {
+ /* Size in memory, disk size is different */
+ dt->shared->size = H5T_REF_DSETREG_MEM_SIZE;
+ dt->shared->u.atomic.prec = 8 * dt->shared->size;
+
+ /* Unused for now */
+ dt->shared->u.atomic.u.r.cls = NULL;
+
+ }
+ break;
+
+ case H5T_LOC_DISK: /* Disk based reference datatype */
+ HDassert(f);
+
+ /* Mark this type as being stored on disk */
+ dt->shared->u.atomic.u.r.loc = H5T_LOC_DISK;
+
+ /* Set file pointer (since this reference is on disk) */
+ dt->shared->u.atomic.u.r.f = f;
+
+ if(dt->shared->u.atomic.u.r.rtype == H5R_OBJECT1) {
+ /* Size on disk, memory size is different */
+ dt->shared->size = H5T_REF_OBJ_DISK_SIZE(f);
+ dt->shared->u.atomic.prec = 8 * dt->shared->size;
+
+ /* Set up the function pointers to access the reference in memory */
+ dt->shared->u.atomic.u.r.cls = &H5T_ref_obj_disk_g;
+
+ } else if(dt->shared->u.atomic.u.r.rtype == H5R_DATASET_REGION1) {
+ /* Size on disk, memory size is different */
+ dt->shared->size = H5T_REF_DSETREG_DISK_SIZE(f);
+ dt->shared->u.atomic.prec = 8 * dt->shared->size;
+
+ /* Set up the function pointers to access the reference in memory */
+ dt->shared->u.atomic.u.r.cls = &H5T_ref_dsetreg_disk_g;
+
+ } else {
+ H5VL_file_cont_info_t cont_info = {H5VL_CONTAINER_INFO_VERSION, 0, 0, 0};
+ size_t ref_encode_size;
+ H5R_ref_priv_t fixed_ref;
+
+ /* Get container info */
+ if(H5F__get_cont_info(f, &cont_info) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "can't get file container info")
+
+ /* Retrieve min encode size (when references have no vlen part) */
+ HDmemset(&fixed_ref, 0, sizeof(fixed_ref));
+ fixed_ref.type = (int8_t)H5R_OBJECT2;
+ fixed_ref.token_size = (uint8_t)cont_info.token_size;
+ if(H5R__encode(NULL, &fixed_ref, NULL, &ref_encode_size, 0) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "can't get encode size")
+
+ /* Size on disk, memory size is different */
+ dt->shared->size = MAX(H5_SIZEOF_UINT32_T +
+ H5R_ENCODE_HEADER_SIZE + cont_info.blob_id_size,
+ ref_encode_size);
+ dt->shared->u.atomic.prec = 8 * dt->shared->size;
+
+ /* Set up the function pointers to access the information on
+ * disk. Region and attribute references are stored identically
+ * on disk, so use the same functions.
+ */
+ dt->shared->u.atomic.u.r.cls = &H5T_ref_disk_g;
+
+ }
+ break;
+
+ case H5T_LOC_BADLOC:
+ /* Allow undefined location. In H5Odtype.c, H5O_dtype_decode sets undefined
+ * location for reference type and leaves it for the caller to decide.
+ */
+ dt->shared->u.atomic.u.r.loc = H5T_LOC_BADLOC;
+
+ /* Reset file pointer */
+ dt->shared->u.atomic.u.r.f = NULL;
+
+ /* Reset the function pointers */
+ dt->shared->u.atomic.u.r.cls = NULL;
+
+ break;
+
+ case H5T_LOC_MAXLOC:
+ /* MAXLOC is invalid */
+ default:
+ HGOTO_ERROR(H5E_DATATYPE, H5E_BADRANGE, FAIL, "invalid reference datatype location")
+ } /* end switch */
+
+ /* Indicate that the location changed */
+ ret_value = TRUE;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T__ref_set_loc() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5T__ref_mem_getsize
+ *
+ * Purpose: Retrieves the size of a memory based reference.
+ *
+ * Return: Non-negative on success/zero on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+static size_t
+H5T__ref_mem_getsize(H5F_t H5_ATTR_UNUSED *src_f, const void *src_buf,
+ size_t H5_ATTR_UNUSED src_size, H5F_t *dst_f, hbool_t *dst_copy)
+{
+ void *vol_obj = NULL;
+ const H5R_ref_priv_t *src_ref = (const H5R_ref_priv_t *)src_buf;
+ unsigned flags = 0;
+ size_t ret_value = 0;
+
+ FUNC_ENTER_STATIC
+
+ HDassert(src_buf);
+ HDassert(src_size == H5T_REF_MEM_SIZE);
+
+ /* Retrieve VOL object */
+ if(NULL == (vol_obj = H5VL_vol_object(src_ref->loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "invalid location identifier")
+
+ /* Retrieve file from VOL object */
+ if(NULL == (src_f = (H5F_t *)H5VL_object_data(vol_obj)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "invalid VOL object")
+
+ /* Set external flag if referenced file is not destination file */
+ flags |= (src_f->shared != dst_f->shared) ? H5R_IS_EXTERNAL : 0;
+
+ /* Force re-calculating encoding size if any flags are set */
+ if(flags || !src_ref->encode_size) {
+ /* Pass the correct encoding version for the selection depending on the
+ * file libver bounds, this is later retrieved in H5S hyper encode */
+ if(src_ref->type == (int8_t)H5R_DATASET_REGION2)
+ H5CX_set_libver_bounds(dst_f);
+
+ /* Determine encoding size */
+ if(H5R__encode(H5F_ACTUAL_NAME(src_f), src_ref, NULL, &ret_value, flags) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTENCODE, 0, "unable to determine encoding size")
+ } else {
+ /* Can do a direct copy and skip blob decoding */
+ if(src_ref->type == (int8_t)H5R_OBJECT2)
+ *dst_copy = TRUE;
+
+ /* Get cached encoding size */
+ ret_value = src_ref->encode_size;
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T__ref_mem_getsize() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5T__ref_mem_read
+ *
+ * Purpose: "Reads" the memory based reference into a buffer
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5T__ref_mem_read(H5F_t H5_ATTR_UNUSED *src_f, const void *src_buf,
+ size_t H5_ATTR_UNUSED src_size, H5F_t *dst_f, void *dst_buf,
+ size_t dst_size)
+{
+ void *vol_obj = NULL;
+ const H5R_ref_priv_t *src_ref = (const H5R_ref_priv_t *)src_buf;
+ unsigned flags = 0;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ HDassert(src_buf);
+ HDassert(src_size == H5T_REF_MEM_SIZE);
+ HDassert(dst_f);
+ HDassert(dst_buf);
+ HDassert(dst_size);
+
+ /* Retrieve VOL object */
+ if(NULL == (vol_obj = H5VL_vol_object(src_ref->loc_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "invalid location identifier")
+
+ /* Retrieve file from VOL object */
+ if(NULL == (src_f = (H5F_t *)H5VL_object_data(vol_obj)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "invalid VOL object")
+
+ /* Set external flag if referenced file is not destination file */
+ flags |= (src_f->shared != dst_f->shared) ? H5R_IS_EXTERNAL : 0;
+
+ /* Pass the correct encoding version for the selection depending on the
+ * file libver bounds, this is later retrieved in H5S hyper encode */
+ if(src_ref->type == (int8_t)H5R_DATASET_REGION2)
+ H5CX_set_libver_bounds(dst_f);
+
+ /* Encode reference */
+ if(H5R__encode(H5F_ACTUAL_NAME(src_f), src_ref, dst_buf, &dst_size, flags) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTENCODE, FAIL, "Cannot encode reference")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T__ref_mem_read() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5T__ref_mem_write
+ *
+ * Purpose: "Writes" the memory reference from a buffer
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5T__ref_mem_write(H5F_t *src_f, const void *src_buf, size_t src_size,
+ H5R_type_t src_type, H5F_t H5_ATTR_UNUSED *dst_f, void *dst_buf,
+ size_t dst_size, void H5_ATTR_UNUSED *bg_buf)
+{
+ hid_t file_id = H5I_INVALID_HID;
+ H5R_ref_priv_t *dst_ref = (H5R_ref_priv_t *)dst_buf;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ HDassert(src_f);
+ HDassert(src_buf);
+ HDassert(src_size);
+ HDassert(dst_buf);
+ HDassert(dst_size == H5T_REF_MEM_SIZE);
+
+ /* Make sure reference buffer is correctly initialized */
+ HDmemset(dst_buf, 0, dst_size);
+
+ switch(src_type) {
+ case H5R_OBJECT1: {
+ size_t token_size = H5F_SIZEOF_ADDR(src_f);
+
+ if(H5R__create_object((const H5VL_token_t *)src_buf, token_size, dst_ref) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCREATE, FAIL, "unable to create object reference")
+ }
+ break;
+ case H5R_DATASET_REGION1: {
+ const struct H5Tref_dsetreg *src_reg = (const struct H5Tref_dsetreg *)src_buf;
+ size_t token_size = H5F_SIZEOF_ADDR(src_f);
+
+ if(H5R__create_region(&src_reg->token, token_size, src_reg->space, dst_ref) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCREATE, FAIL, "unable to create region reference")
+ /* create_region creates its internal copy of the space */
+ if(H5S_close(src_reg->space) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTFREE, FAIL, "Cannot close dataspace")
+ }
+ break;
+ case H5R_DATASET_REGION2:
+ /* Pass the correct encoding version for the selection depending on the
+ * file libver bounds, this is later retrieved in H5S hyper decode */
+ H5CX_set_libver_bounds(src_f);
+ H5_ATTR_FALLTHROUGH
+ case H5R_OBJECT2:
+ case H5R_ATTR:
+ /* Decode reference */
+ if(H5R__decode((const unsigned char *)src_buf, &src_size, dst_ref) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "Cannot decode reference")
+ break;
+ case H5R_BADTYPE:
+ case H5R_MAXTYPE:
+ default:
+ HDassert("unknown reference type" && 0);
+ HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, FAIL, "internal error (unknown reference type)")
+ }
+
+ /* If no filename set, this is not an external reference */
+ if(NULL == H5R_REF_FILENAME(dst_ref)) {
+ /* TODO temporary hack to retrieve file object */
+ if((file_id = H5F__get_file_id(src_f, FALSE)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+
+ /* Attach loc ID to reference and hold reference to it */
+ if(H5R__set_loc_id(dst_ref, file_id, TRUE) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTSET, FAIL, "unable to attach location id to reference")
+ }
+
+done:
+ if((file_id != H5I_INVALID_HID) && (H5I_dec_ref(file_id) < 0))
+ HDONE_ERROR(H5E_REFERENCE, H5E_CANTDEC, FAIL, "unable to decrement refcount on location id")
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T__ref_mem_write() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5T__ref_disk_getsize
+ *
+ * Purpose: Retrieves the length of a disk based reference.
+ *
+ * Return: Non-negative value (cannot fail)
+ *
+ *-------------------------------------------------------------------------
+ */
+static size_t
+H5T__ref_disk_getsize(H5F_t H5_ATTR_UNUSED *src_f, const void *src_buf,
+ size_t src_size, H5F_t H5_ATTR_UNUSED *dst_f, hbool_t *dst_copy)
+{
+ const uint8_t *p = (const uint8_t *)src_buf;
+ unsigned flags;
+ H5R_type_t ref_type;
+ size_t ret_value = 0;
+
+ FUNC_ENTER_STATIC
+
+ HDassert(src_buf);
+
+ /* Set reference type */
+ ref_type = (H5R_type_t)*p++;
+ if(ref_type <= H5R_BADTYPE || ref_type >= H5R_MAXTYPE)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "invalid reference type")
+
+ /* Set flags */
+ flags = (unsigned)*p++;
+
+ if(!(flags & H5R_IS_EXTERNAL) && (ref_type == H5R_OBJECT2)) {
+ /* Can do a direct copy and skip blob decoding */
+ *dst_copy = TRUE;
+
+ ret_value = src_size;
+ } else {
+ /* Retrieve encoded data size */
+ UINT32DECODE(p, ret_value);
+
+ /* Add size of the header */
+ ret_value += H5R_ENCODE_HEADER_SIZE;
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T__ref_disk_getsize() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5T__ref_disk_read
+ *
+ * Purpose: Reads the disk based reference into a buffer
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5T__ref_disk_read(H5F_t *src_f, const void *src_buf, size_t src_size,
+ H5F_t H5_ATTR_UNUSED *dst_f, void *dst_buf, size_t dst_size)
+{
+ H5VL_object_t *vol_obj = NULL; /* Object info */
+ hid_t file_id = H5I_INVALID_HID;
+ const uint8_t *p = (const uint8_t *)src_buf;
+ uint8_t *q = (uint8_t *)dst_buf;
+ size_t buf_size_left = src_size;
+ size_t expected_size = dst_size;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ HDassert(src_f);
+ HDassert(src_buf);
+ HDassert(dst_buf);
+ HDassert(dst_size);
+
+ /* TODO temporary hack to retrieve file object */
+ if((file_id = H5F__get_file_id(src_f, FALSE)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+ if(NULL == (vol_obj = H5VL_vol_object(file_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier")
+
+ /* Copy header manually */
+ HDmemcpy(q, p, H5R_ENCODE_HEADER_SIZE);
+ p += H5R_ENCODE_HEADER_SIZE;
+ q += H5R_ENCODE_HEADER_SIZE;
+ expected_size -= H5R_ENCODE_HEADER_SIZE;
+
+ /* Skip the length of the sequence */
+ p += H5_SIZEOF_UINT32_T;
+ HDassert(buf_size_left > H5_SIZEOF_UINT32_T);
+ buf_size_left -= H5_SIZEOF_UINT32_T;
+
+ /* Retrieve blob */
+ if(H5VL_blob_get(vol_obj, p, q, &dst_size, NULL) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to get blob")
+ if(dst_size != expected_size)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "Expected data size does not match")
+
+done:
+ if((file_id != H5I_INVALID_HID) && (H5I_dec_ref(file_id) < 0))
+ HDONE_ERROR(H5E_DATATYPE, H5E_CANTDEC, FAIL, "unable to decrement refcount on file id")
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T__ref_disk_read() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5T__ref_disk_write
+ *
+ * Purpose: Writes the disk based reference from a buffer
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5T__ref_disk_write(H5F_t H5_ATTR_UNUSED *src_f, const void *src_buf,
+ size_t src_size, H5R_type_t H5_ATTR_UNUSED src_type, H5F_t *dst_f,
+ void *dst_buf, size_t dst_size, void *bg_buf)
+{
+ H5VL_object_t *vol_obj = NULL; /* Object info */
+ hid_t file_id = H5I_INVALID_HID;
+ const uint8_t *p = (const uint8_t *)src_buf;
+ uint8_t *q = (uint8_t *)dst_buf;
+ size_t buf_size_left = dst_size;
+ uint8_t *p_bg = (uint8_t *)bg_buf;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ HDassert(src_buf);
+ HDassert(src_size);
+ HDassert(dst_f);
+ HDassert(dst_buf);
+
+ /* TODO temporary hack to retrieve file object */
+ if((file_id = H5F__get_file_id(dst_f, FALSE)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+ if(NULL == (vol_obj = H5VL_vol_object(file_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier")
+
+ /* TODO Should get rid of bg stuff */
+ if(p_bg) {
+ size_t p_buf_size_left = dst_size;
+
+ /* Skip the length of the reference */
+ p_bg += H5_SIZEOF_UINT32_T;
+ HDassert(p_buf_size_left > H5_SIZEOF_UINT32_T);
+ p_buf_size_left -= H5_SIZEOF_UINT32_T;
+
+ /* Remove blob for old data */
+ if(H5VL_blob_specific(vol_obj, (void *)p_bg, H5VL_BLOB_DELETE) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREMOVE, FAIL, "unable to delete blob")
+ } /* end if */
+
+ /* Copy header manually so that it does not get encoded into the blob */
+ HDmemcpy(q, p, H5R_ENCODE_HEADER_SIZE);
+ p += H5R_ENCODE_HEADER_SIZE;
+ q += H5R_ENCODE_HEADER_SIZE;
+ src_size -= H5R_ENCODE_HEADER_SIZE;
+ buf_size_left -= H5_SIZEOF_UINT32_T;
+
+ /* Set the size */
+ UINT32ENCODE(q, src_size);
+ HDassert(buf_size_left > H5_SIZEOF_UINT32_T);
+ buf_size_left -= H5_SIZEOF_UINT32_T;
+
+ /* Store blob */
+ if(H5VL_blob_put(vol_obj, p, src_size, q, NULL) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "unable to put blob")
+
+done:
+ if((file_id != H5I_INVALID_HID) && (H5I_dec_ref(file_id) < 0))
+ HDONE_ERROR(H5E_DATATYPE, H5E_CANTDEC, FAIL, "unable to decrement refcount on file id")
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T__ref_disk_write() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5T__ref_obj_disk_getsize
+ *
+ * Purpose: Retrieves the length of a disk based reference.
+ *
+ * Return: Non-negative value (cannot fail)
+ *
+ *-------------------------------------------------------------------------
+ */
+static size_t
+H5T__ref_obj_disk_getsize(H5F_t *src_f, const void H5_ATTR_UNUSED *src_buf,
+ size_t H5_ATTR_UNUSED src_size, H5F_t H5_ATTR_UNUSED *dst_f,
+ hbool_t H5_ATTR_UNUSED *dst_copy)
+{
+ size_t ret_value = 0;
+
+ FUNC_ENTER_STATIC_NOERR
+
+ HDassert(src_f);
+ HDassert(src_buf);
+ HDassert(src_size == H5T_REF_OBJ_DISK_SIZE(src_f));
+
+ ret_value = H5T_REF_OBJ_DISK_SIZE(src_f);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T__ref_obj_disk_getsize() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5T__ref_obj_disk_read
+ *
+ * Purpose: Reads the disk based reference into a buffer
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5T__ref_obj_disk_read(H5F_t *src_f, const void *src_buf, size_t src_size,
+ H5F_t H5_ATTR_UNUSED *dst_f, void *dst_buf, size_t H5_ATTR_UNUSED dst_size)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ HDassert(src_f);
+ HDassert(src_buf);
+ HDassert(src_size == H5T_REF_OBJ_DISK_SIZE(src_f));
+ HDassert(dst_buf);
+ HDassert(dst_size == H5F_SIZEOF_ADDR(src_f));
+
+ /* Get object address */
+ if(H5R__decode_token_obj_compat((const unsigned char *)src_buf, &src_size,
+ dst_buf, H5F_SIZEOF_ADDR(src_f)) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "unable to get object address")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T__ref_obj_disk_read() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5T__ref_dsetreg_disk_getsize
+ *
+ * Purpose: Retrieves the length of a disk based reference.
+ *
+ * Return: Non-negative value (cannot fail)
+ *
+ *-------------------------------------------------------------------------
+ */
+static size_t
+H5T__ref_dsetreg_disk_getsize(H5F_t H5_ATTR_UNUSED *f,
+ const void H5_ATTR_UNUSED *buf, size_t H5_ATTR_UNUSED buf_size,
+ H5F_t H5_ATTR_UNUSED *dst_f, hbool_t H5_ATTR_UNUSED *dst_copy)
+{
+ size_t ret_value = sizeof(struct H5Tref_dsetreg);
+
+ FUNC_ENTER_STATIC_NOERR
+
+ HDassert(buf);
+ HDassert(buf_size == H5T_REF_DSETREG_DISK_SIZE(f));
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T__ref_dsetreg_disk_getsize() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5T__ref_dsetreg_disk_read
+ *
+ * Purpose: Reads the disk based reference into a buffer
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5T__ref_dsetreg_disk_read(H5F_t *src_f, const void *src_buf, size_t src_size,
+ H5F_t H5_ATTR_UNUSED *dst_f, void *dst_buf, size_t H5_ATTR_UNUSED dst_size)
+{
+ struct H5Tref_dsetreg *dst_reg = (struct H5Tref_dsetreg *)dst_buf;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ HDassert(src_f);
+ HDassert(src_buf);
+ HDassert(src_size == H5T_REF_DSETREG_DISK_SIZE(src_f));
+ HDassert(dst_buf);
+ HDassert(dst_size == sizeof(struct H5Tref_dsetreg));
+
+ /* Retrieve object address and space */
+ if(H5R__decode_token_region_compat(src_f, (const unsigned char *)src_buf,
+ &src_size, &dst_reg->token, H5F_SIZEOF_ADDR(src_f), &dst_reg->space) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "unable to get object address")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T__ref_dsetreg_disk_read() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5T_ref_reclaim
+ *
+ * Purpose: Internal routine to free reference datatypes
+ *
+ * Return: Non-negative on success / Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5T_ref_reclaim(void *elem, const H5T_t *dt)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* Sanity checks */
+ HDassert(elem);
+ HDassert(dt && (dt->shared->type == H5T_REFERENCE));
+
+ if(dt->shared->u.atomic.u.r.opaque
+ && (H5R__destroy((H5R_ref_priv_t *)elem) < 0))
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTFREE, FAIL, "cannot free reference")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T_ref_reclaim() */
diff --git a/src/H5Tvlen.c b/src/H5Tvlen.c
index 467847f..0253b01 100644
--- a/src/H5Tvlen.c
+++ b/src/H5Tvlen.c
@@ -16,41 +16,119 @@
* datatypes in the H5T interface.
*/
-#include "H5Tmodule.h" /* This source code file is part of the H5T module */
-
+/****************/
+/* Module Setup */
+/****************/
-#include "H5private.h" /* Generic Functions */
-#include "H5CXprivate.h" /* API Contexts */
-#include "H5Dprivate.h" /* Dataset functions */
-#include "H5Eprivate.h" /* Error handling */
-#include "H5HGprivate.h" /* Global Heaps */
-#include "H5Iprivate.h" /* IDs */
-#include "H5MMprivate.h" /* Memory management */
-#include "H5Pprivate.h" /* Property lists */
-#include "H5Tpkg.h" /* Datatypes */
-
-/* Local functions */
-static herr_t H5T_vlen_reclaim_recurse(void *elem, const H5T_t *dt, H5MM_free_t free_func, void *free_info);
-static ssize_t H5T_vlen_seq_mem_getlen(const void *_vl);
-static void * H5T_vlen_seq_mem_getptr(void *_vl);
-static htri_t H5T_vlen_seq_mem_isnull(const H5F_t *f, void *_vl);
-static herr_t H5T_vlen_seq_mem_read(H5F_t *f, void *_vl, void *_buf, size_t len);
-static herr_t H5T_vlen_seq_mem_write(H5F_t *f, const H5T_vlen_alloc_info_t *vl_alloc_info, void *_vl, void *_buf, void *_bg, size_t seq_len, size_t base_size);
-static herr_t H5T_vlen_seq_mem_setnull(H5F_t *f, void *_vl, void *_bg);
-static ssize_t H5T_vlen_str_mem_getlen(const void *_vl);
-static void * H5T_vlen_str_mem_getptr(void *_vl);
-static htri_t H5T_vlen_str_mem_isnull(const H5F_t *f, void *_vl);
-static herr_t H5T_vlen_str_mem_read(H5F_t *f, void *_vl, void *_buf, size_t len);
-static herr_t H5T_vlen_str_mem_write(H5F_t *f, const H5T_vlen_alloc_info_t *vl_alloc_info, void *_vl, void *_buf, void *_bg, size_t seq_len, size_t base_size);
-static herr_t H5T_vlen_str_mem_setnull(H5F_t *f, void *_vl, void *_bg);
-static ssize_t H5T_vlen_disk_getlen(const void *_vl);
-static void * H5T_vlen_disk_getptr(void *_vl);
-static htri_t H5T_vlen_disk_isnull(const H5F_t *f, void *_vl);
-static herr_t H5T_vlen_disk_read(H5F_t *f, void *_vl, void *_buf, size_t len);
-static herr_t H5T_vlen_disk_write(H5F_t *f, const H5T_vlen_alloc_info_t *vl_alloc_info, void *_vl, void *_buf, void *_bg, size_t seq_len, size_t base_size);
-static herr_t H5T_vlen_disk_setnull(H5F_t *f, void *_vl, void *_bg);
-
-/* Local variables */
+#include "H5Tmodule.h" /* This source code file is part of the H5T module */
+#define H5F_FRIEND /*suppress error about including H5Fpkg */
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5CXprivate.h" /* API Contexts */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fpkg.h" /* File */
+#include "H5Iprivate.h" /* IDs */
+#include "H5MMprivate.h" /* Memory management */
+#include "H5Tpkg.h" /* Datatypes */
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+/* Memory-based VL sequence callbacks */
+static herr_t H5T__vlen_mem_seq_getlen(H5F_t *f, const void *_vl, size_t *len);
+static void * H5T__vlen_mem_seq_getptr(void *_vl);
+static herr_t H5T__vlen_mem_seq_isnull(const H5F_t *f, void *_vl, hbool_t *isnull);
+static herr_t H5T__vlen_mem_seq_setnull(H5F_t *f, void *_vl, void *_bg);
+static herr_t H5T__vlen_mem_seq_read(H5F_t *f, void *_vl, void *_buf, size_t len);
+static herr_t H5T__vlen_mem_seq_write(H5F_t *f, const H5T_vlen_alloc_info_t *vl_alloc_info, void *_vl, void *_buf, void *_bg, size_t seq_len, size_t base_size);
+
+/* Memory-based VL string callbacks */
+static herr_t H5T__vlen_mem_str_getlen(H5F_t *f, const void *_vl, size_t *len);
+static void * H5T__vlen_mem_str_getptr(void *_vl);
+static herr_t H5T__vlen_mem_str_isnull(const H5F_t *f, void *_vl, hbool_t *isnull);
+static herr_t H5T__vlen_mem_str_setnull(H5F_t *f, void *_vl, void *_bg);
+static herr_t H5T__vlen_mem_str_read(H5F_t *f, void *_vl, void *_buf, size_t len);
+static herr_t H5T__vlen_mem_str_write(H5F_t *f, const H5T_vlen_alloc_info_t *vl_alloc_info, void *_vl, void *_buf, void *_bg, size_t seq_len, size_t base_size);
+
+/* Disk-based VL sequence (and string) callbacks */
+static herr_t H5T__vlen_disk_getlen(H5F_t *f, const void *_vl, size_t *len);
+static herr_t H5T__vlen_disk_isnull(const H5F_t *f, void *_vl, hbool_t *isnull);
+static herr_t H5T__vlen_disk_setnull(H5F_t *f, void *_vl, void *_bg);
+static herr_t H5T__vlen_disk_read(H5F_t *f, void *_vl, void *_buf, size_t len);
+static herr_t H5T__vlen_disk_write(H5F_t *f, const H5T_vlen_alloc_info_t *vl_alloc_info, void *_vl, void *_buf, void *_bg, size_t seq_len, size_t base_size);
+static herr_t H5T__vlen_disk_delete(H5F_t *f, const void *_vl);
+
+
+/*********************/
+/* Public Variables */
+/*********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* Class for VL sequences in memory */
+static const H5T_vlen_class_t H5T_vlen_mem_seq_g = {
+ H5T__vlen_mem_seq_getlen, /* 'getlen' */
+ H5T__vlen_mem_seq_getptr, /* 'getptr' */
+ H5T__vlen_mem_seq_isnull, /* 'isnull' */
+ H5T__vlen_mem_seq_setnull, /* 'setnull' */
+ H5T__vlen_mem_seq_read, /* 'read' */
+ H5T__vlen_mem_seq_write, /* 'write' */
+ NULL /* 'delete' */
+};
+
+/* Class for VL strings in memory */
+static const H5T_vlen_class_t H5T_vlen_mem_str_g = {
+ H5T__vlen_mem_str_getlen, /* 'getlen' */
+ H5T__vlen_mem_str_getptr, /* 'getptr' */
+ H5T__vlen_mem_str_isnull, /* 'isnull' */
+ H5T__vlen_mem_str_setnull, /* 'setnull' */
+ H5T__vlen_mem_str_read, /* 'read' */
+ H5T__vlen_mem_str_write, /* 'write' */
+ NULL /* 'delete' */
+};
+
+/* Class for both VL strings and sequences in file */
+static const H5T_vlen_class_t H5T_vlen_disk_g = {
+ H5T__vlen_disk_getlen, /* 'getlen' */
+ NULL, /* 'getptr' */
+ H5T__vlen_disk_isnull, /* 'isnull' */
+ H5T__vlen_disk_setnull, /* 'setnull' */
+ H5T__vlen_disk_read, /* 'read' */
+ H5T__vlen_disk_write, /* 'write' */
+ H5T__vlen_disk_delete /* 'delete' */
+};
@@ -194,32 +272,21 @@ H5T__vlen_set_loc(const H5T_t *dt, H5F_t *f, H5T_loc_t loc)
dt->shared->u.vlen.loc = H5T_LOC_MEMORY;
if(dt->shared->u.vlen.type == H5T_VLEN_SEQUENCE) {
- /* size in memory, disk size is different */
+ /* Size in memory, disk size is different */
dt->shared->size = sizeof(hvl_t);
/* Set up the function pointers to access the VL sequence in memory */
- dt->shared->u.vlen.getlen = H5T_vlen_seq_mem_getlen;
- dt->shared->u.vlen.getptr = H5T_vlen_seq_mem_getptr;
- dt->shared->u.vlen.isnull = H5T_vlen_seq_mem_isnull;
- dt->shared->u.vlen.read = H5T_vlen_seq_mem_read;
- dt->shared->u.vlen.write = H5T_vlen_seq_mem_write;
- dt->shared->u.vlen.setnull = H5T_vlen_seq_mem_setnull;
- }
+ dt->shared->u.vlen.cls = &H5T_vlen_mem_seq_g;
+ } /* end if */
else if(dt->shared->u.vlen.type == H5T_VLEN_STRING) {
- /* size in memory, disk size is different */
+ /* Size in memory, disk size is different */
dt->shared->size = sizeof(char *);
/* Set up the function pointers to access the VL string in memory */
- dt->shared->u.vlen.getlen = H5T_vlen_str_mem_getlen;
- dt->shared->u.vlen.getptr = H5T_vlen_str_mem_getptr;
- dt->shared->u.vlen.isnull = H5T_vlen_str_mem_isnull;
- dt->shared->u.vlen.read = H5T_vlen_str_mem_read;
- dt->shared->u.vlen.write = H5T_vlen_str_mem_write;
- dt->shared->u.vlen.setnull = H5T_vlen_str_mem_setnull;
- }
- else {
+ dt->shared->u.vlen.cls = &H5T_vlen_mem_str_g;
+ } /* end else-if */
+ else
HDassert(0 && "Invalid VL type");
- }
/* Reset file ID (since this VL is in memory) */
dt->shared->u.vlen.f = NULL;
@@ -234,18 +301,13 @@ H5T__vlen_set_loc(const H5T_t *dt, H5F_t *f, H5T_loc_t loc)
/*
* Size of element on disk is 4 bytes for the length, plus the size
* of an address in this file, plus 4 bytes for the size of a heap
- * ID. Memory size is different
+ * ID. Memory size is different.
*/
dt->shared->size = 4 + (size_t)H5F_SIZEOF_ADDR(f) + 4;
/* Set up the function pointers to access the VL information on disk */
/* VL sequences and VL strings are stored identically on disk, so use the same functions */
- dt->shared->u.vlen.getlen = H5T_vlen_disk_getlen;
- dt->shared->u.vlen.getptr = H5T_vlen_disk_getptr;
- dt->shared->u.vlen.isnull = H5T_vlen_disk_isnull;
- dt->shared->u.vlen.read = H5T_vlen_disk_read;
- dt->shared->u.vlen.write = H5T_vlen_disk_write;
- dt->shared->u.vlen.setnull = H5T_vlen_disk_setnull;
+ dt->shared->u.vlen.cls = &H5T_vlen_disk_g;
/* Set file ID (since this VL is on disk) */
dt->shared->u.vlen.f = f;
@@ -255,6 +317,13 @@ H5T__vlen_set_loc(const H5T_t *dt, H5F_t *f, H5T_loc_t loc)
/* Allow undefined location. In H5Odtype.c, H5O_dtype_decode sets undefined
* location for VL type and leaves it for the caller to decide.
*/
+ dt->shared->u.vlen.loc = H5T_LOC_BADLOC;
+
+ /* Reset the function pointers to access the VL information */
+ dt->shared->u.vlen.cls = NULL;
+
+ /* Reset file pointer */
+ dt->shared->u.vlen.f = NULL;
break;
case H5T_LOC_MAXLOC:
@@ -269,11 +338,11 @@ H5T__vlen_set_loc(const H5T_t *dt, H5F_t *f, H5T_loc_t loc)
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5T__vlen_set_loc() */
+} /* end H5T__vlen_set_loc() */
/*-------------------------------------------------------------------------
- * Function: H5T_vlen_seq_mem_getlen
+ * Function: H5T__vlen_mem_seq_getlen
*
* Purpose: Retrieves the length of a memory based VL element.
*
@@ -284,33 +353,35 @@ done:
*
*-------------------------------------------------------------------------
*/
-static ssize_t
-H5T_vlen_seq_mem_getlen(const void *_vl)
+static herr_t
+H5T__vlen_mem_seq_getlen(H5F_t H5_ATTR_UNUSED *f, const void *_vl, size_t *len)
{
#ifdef H5_NO_ALIGNMENT_RESTRICTIONS
- const hvl_t *vl=(const hvl_t *)_vl; /* Pointer to the user's hvl_t information */
+ const hvl_t *vl = (const hvl_t *)_vl; /* Pointer to the user's hvl_t information */
#else
hvl_t vl; /* User's hvl_t information */
#endif
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
- /* check parameters, return result */
-#ifdef H5_NO_ALIGNMENT_RESTRICTIONS
- HDassert(vl);
+ /* Check parameter */
+ HDassert(_vl);
+ HDassert(len);
- FUNC_LEAVE_NOAPI((ssize_t)vl->len)
+#ifdef H5_NO_ALIGNMENT_RESTRICTIONS
+ *len = vl->len;
#else
- HDassert(_vl);
- HDmemcpy(&vl, _vl, sizeof(hvl_t));
+ H5MM_memcpy(&vl, _vl, sizeof(hvl_t));
- FUNC_LEAVE_NOAPI((ssize_t)vl.len)
+ *len = vl.len;
#endif
-} /* end H5T_vlen_seq_mem_getlen() */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5T__vlen_mem_seq_getlen() */
/*-------------------------------------------------------------------------
- * Function: H5T_vlen_seq_mem_getptr
+ * Function: H5T__vlen_mem_seq_getptr
*
* Purpose: Retrieves the pointer for a memory based VL element.
*
@@ -322,15 +393,15 @@ H5T_vlen_seq_mem_getlen(const void *_vl)
*-------------------------------------------------------------------------
*/
static void *
-H5T_vlen_seq_mem_getptr(void *_vl)
+H5T__vlen_mem_seq_getptr(void *_vl)
{
#ifdef H5_NO_ALIGNMENT_RESTRICTIONS
- const hvl_t *vl=(const hvl_t *)_vl; /* Pointer to the user's hvl_t information */
+ const hvl_t *vl = (const hvl_t *)_vl; /* Pointer to the user's hvl_t information */
#else
hvl_t vl; /* User's hvl_t information */
#endif
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
/* check parameters, return result */
#ifdef H5_NO_ALIGNMENT_RESTRICTIONS
@@ -339,52 +410,86 @@ H5T_vlen_seq_mem_getptr(void *_vl)
FUNC_LEAVE_NOAPI(vl->p)
#else
HDassert(_vl);
- HDmemcpy(&vl, _vl, sizeof(hvl_t));
+ H5MM_memcpy(&vl, _vl, sizeof(hvl_t));
FUNC_LEAVE_NOAPI(vl.p)
#endif
-} /* end H5T_vlen_seq_mem_getptr() */
+} /* end H5T__vlen_mem_seq_getptr() */
/*-------------------------------------------------------------------------
- * Function: H5T_vlen_seq_mem_isnull
+ * Function: H5T__vlen_mem_seq_isnull
*
* Purpose: Checks if a memory sequence is the "null" sequence
*
- * Return: TRUE/FALSE on success/Negative on failure
+ * Return: Non-negative on success / Negative on failure
*
* Programmer: Quincey Koziol
* Saturday, November 8, 2003
*
*-------------------------------------------------------------------------
*/
-static htri_t
-H5T_vlen_seq_mem_isnull(const H5F_t H5_ATTR_UNUSED *f, void *_vl)
+static herr_t
+H5T__vlen_mem_seq_isnull(const H5F_t H5_ATTR_UNUSED *f, void *_vl, hbool_t *isnull)
{
#ifdef H5_NO_ALIGNMENT_RESTRICTIONS
- const hvl_t *vl=(const hvl_t *)_vl; /* Pointer to the user's hvl_t information */
+ const hvl_t *vl = (const hvl_t *)_vl; /* Pointer to the user's hvl_t information */
#else
hvl_t vl; /* User's hvl_t information */
#endif
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
- /* check parameters, return result */
-#ifdef H5_NO_ALIGNMENT_RESTRICTIONS
- HDassert(vl);
+ /* Check parameters */
+ HDassert(_vl);
- FUNC_LEAVE_NOAPI((vl->len==0 || vl->p==NULL) ? TRUE : FALSE)
+#ifdef H5_NO_ALIGNMENT_RESTRICTIONS
+ *isnull = ((vl->len == 0 || vl->p == NULL) ? TRUE : FALSE);
#else
- HDassert(_vl);
- HDmemcpy(&vl, _vl, sizeof(hvl_t));
+ H5MM_memcpy(&vl, _vl, sizeof(hvl_t));
- FUNC_LEAVE_NOAPI((vl.len==0 || vl.p==NULL) ? TRUE : FALSE)
+ *isnull = ((vl.len == 0 || vl.p == NULL) ? TRUE : FALSE);
#endif
-} /* end H5T_vlen_seq_mem_isnull() */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5T__vlen_mem_seq_isnull() */
/*-------------------------------------------------------------------------
- * Function: H5T_vlen_seq_mem_read
+ * Function: H5T__vlen_mem_seq_setnull
+ *
+ * Purpose: Sets a VL info object in memory to the "nil" value
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Saturday, November 8, 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5T__vlen_mem_seq_setnull(H5F_t H5_ATTR_UNUSED *f, void *_vl, void H5_ATTR_UNUSED *_bg)
+{
+ hvl_t vl; /* Temporary hvl_t to use during operation */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* check parameters */
+ HDassert(_vl);
+
+ /* Set the "nil" hvl_t */
+ vl.len = 0;
+ vl.p = NULL;
+
+ /* Set pointer in user's buffer with memcpy, to avoid alignment issues */
+ H5MM_memcpy(_vl, &vl, sizeof(hvl_t));
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5T__vlen_mem_seq_setnull() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5T__vlen_mem_seq_read
*
* Purpose: "Reads" the memory based VL sequence into a buffer
*
@@ -396,36 +501,36 @@ H5T_vlen_seq_mem_isnull(const H5F_t H5_ATTR_UNUSED *f, void *_vl)
*-------------------------------------------------------------------------
*/
static herr_t
-H5T_vlen_seq_mem_read(H5F_t H5_ATTR_UNUSED *f, void *_vl, void *buf, size_t len)
+H5T__vlen_mem_seq_read(H5F_t H5_ATTR_UNUSED *f, void *_vl, void *buf, size_t len)
{
#ifdef H5_NO_ALIGNMENT_RESTRICTIONS
- const hvl_t *vl=(const hvl_t *)_vl; /* Pointer to the user's hvl_t information */
+ const hvl_t *vl = (const hvl_t *)_vl; /* Pointer to the user's hvl_t information */
#else
hvl_t vl; /* User's hvl_t information */
#endif
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
/* check parameters, copy data */
HDassert(buf);
#ifdef H5_NO_ALIGNMENT_RESTRICTIONS
HDassert(vl && vl->p);
- HDmemcpy(buf,vl->p,len);
+ H5MM_memcpy(buf, vl->p, len);
#else
HDassert(_vl);
- HDmemcpy(&vl, _vl, sizeof(hvl_t));
+ H5MM_memcpy(&vl, _vl, sizeof(hvl_t));
HDassert(vl.p);
- HDmemcpy(buf,vl.p,len);
+ H5MM_memcpy(buf, vl.p, len);
#endif
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5T_vlen_seq_mem_read() */
+} /* end H5T__vlen_mem_seq_read() */
/*-------------------------------------------------------------------------
- * Function: H5T_vlen_seq_mem_write
+ * Function: H5T__vlen_mem_seq_write
*
* Purpose: "Writes" the memory based VL sequence from a buffer
*
@@ -437,185 +542,178 @@ H5T_vlen_seq_mem_read(H5F_t H5_ATTR_UNUSED *f, void *_vl, void *buf, size_t len)
*-------------------------------------------------------------------------
*/
static herr_t
-H5T_vlen_seq_mem_write(H5F_t H5_ATTR_UNUSED *f, const H5T_vlen_alloc_info_t *vl_alloc_info, void *_vl, void *buf, void H5_ATTR_UNUSED *_bg, size_t seq_len, size_t base_size)
+H5T__vlen_mem_seq_write(H5F_t H5_ATTR_UNUSED *f, const H5T_vlen_alloc_info_t *vl_alloc_info, void *_vl, void *buf, void H5_ATTR_UNUSED *_bg, size_t seq_len, size_t base_size)
{
hvl_t vl; /* Temporary hvl_t to use during operation */
- size_t len;
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
/* check parameters */
HDassert(_vl);
HDassert(buf);
- if(seq_len!=0) {
- len=seq_len*base_size;
+ if(seq_len) {
+ size_t len = seq_len * base_size; /* Sequence size */
/* Use the user's memory allocation routine is one is defined */
- if(vl_alloc_info->alloc_func!=NULL) {
- if(NULL==(vl.p=(vl_alloc_info->alloc_func)(len,vl_alloc_info->alloc_info)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for VL data")
+ if(vl_alloc_info->alloc_func != NULL) {
+ if(NULL == (vl.p = (vl_alloc_info->alloc_func)(len, vl_alloc_info->alloc_info)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "application memory allocation routine failed for VL data")
} /* end if */
- else { /* Default to system malloc */
+ else /* Default to system malloc */
if(NULL == (vl.p = HDmalloc(len)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for VL data")
- } /* end else */
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "memory allocation failed for VL data")
/* Copy the data into the newly allocated buffer */
- HDmemcpy(vl.p,buf,len);
-
+ H5MM_memcpy(vl.p, buf, len);
} /* end if */
else
- vl.p=NULL;
+ vl.p = NULL;
/* Set the sequence length */
- vl.len=seq_len;
+ vl.len = seq_len;
/* Set pointer in user's buffer with memcpy, to avoid alignment issues */
- HDmemcpy(_vl,&vl,sizeof(hvl_t));
+ H5MM_memcpy(_vl, &vl, sizeof(hvl_t));
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5T_vlen_seq_mem_write() */
+} /* end H5T__vlen_mem_seq_write() */
/*-------------------------------------------------------------------------
- * Function: H5T_vlen_seq_mem_setnull
+ * Function: H5T__vlen_mem_str_getlen
*
- * Purpose: Sets a VL info object in memory to the "nil" value
+ * Purpose: Retrieves the length of a memory based VL string.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
- * Saturday, November 8, 2003
+ * Wednesday, June 2, 1999
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5T_vlen_seq_mem_setnull(H5F_t H5_ATTR_UNUSED *f, void *_vl, void H5_ATTR_UNUSED *_bg)
+H5T__vlen_mem_str_getlen(H5F_t H5_ATTR_UNUSED *f, const void *_vl, size_t *len)
{
- hvl_t vl; /* Temporary hvl_t to use during operation */
+#ifdef H5_NO_ALIGNMENT_RESTRICTIONS
+ const char *s = *(const char * const *)_vl; /* Pointer to the user's string information */
+#else
+ const char *s = NULL; /* Pointer to the user's string information */
+#endif
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
/* check parameters */
HDassert(_vl);
- /* Set the "nil" hvl_t */
- vl.len=0;
- vl.p=NULL;
+#ifndef H5_NO_ALIGNMENT_RESTRICTIONS
+ H5MM_memcpy(&s, _vl, sizeof(char *));
+#endif
- /* Set pointer in user's buffer with memcpy, to avoid alignment issues */
- HDmemcpy(_vl,&vl,sizeof(hvl_t));
+ *len = HDstrlen(s);
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5T_vlen_seq_mem_setnull() */
+} /* end H5T__vlen_mem_str_getlen() */
/*-------------------------------------------------------------------------
- * Function: H5T_vlen_str_mem_getlen
+ * Function: H5T__vlen_mem_str_getptr
*
- * Purpose: Retrieves the length of a memory based VL string.
+ * Purpose: Retrieves the pointer for a memory based VL string.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-NULL on success/NULL on failure
*
* Programmer: Quincey Koziol
- * Wednesday, June 2, 1999
+ * Saturday, June 12, 2004
*
*-------------------------------------------------------------------------
*/
-static ssize_t
-H5T_vlen_str_mem_getlen(const void *_vl)
+static void *
+H5T__vlen_mem_str_getptr(void *_vl)
{
#ifdef H5_NO_ALIGNMENT_RESTRICTIONS
- const char *s=*(const char * const *)_vl; /* Pointer to the user's string information */
+ char *s = *(char **)_vl; /* Pointer to the user's string information */
#else
- const char *s; /* Pointer to the user's string information */
+ char *s = NULL; /* Pointer to the user's string information */
#endif
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
/* check parameters */
#ifdef H5_NO_ALIGNMENT_RESTRICTIONS
HDassert(s);
#else
HDassert(_vl);
- HDmemcpy(&s, _vl, sizeof(char *));
+ H5MM_memcpy(&s, _vl, sizeof(char *));
#endif
- FUNC_LEAVE_NOAPI((ssize_t)HDstrlen(s))
-} /* end H5T_vlen_str_mem_getlen() */
+ FUNC_LEAVE_NOAPI(s)
+} /* end H5T__vlen_mem_str_getptr() */
/*-------------------------------------------------------------------------
- * Function: H5T_vlen_str_mem_getptr
+ * Function: H5T__vlen_mem_str_isnull
*
- * Purpose: Retrieves the pointer for a memory based VL string.
+ * Purpose: Checks if a memory string is a NULL pointer
*
- * Return: Non-NULL on success/NULL on failure
+ * Return: Non-negative on success / Negative on failure
*
* Programmer: Quincey Koziol
- * Saturday, June 12, 2004
+ * Saturday, November 8, 2003
*
*-------------------------------------------------------------------------
*/
-static void *
-H5T_vlen_str_mem_getptr(void *_vl)
+static herr_t
+H5T__vlen_mem_str_isnull(const H5F_t H5_ATTR_UNUSED *f, void *_vl, hbool_t *isnull)
{
#ifdef H5_NO_ALIGNMENT_RESTRICTIONS
- char *s=*(char **)_vl; /* Pointer to the user's string information */
+ char *s = *(char **)_vl; /* Pointer to the user's string information */
#else
- char *s; /* Pointer to the user's string information */
+ char *s = NULL; /* Pointer to the user's string information */
#endif
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
- /* check parameters */
-#ifdef H5_NO_ALIGNMENT_RESTRICTIONS
- HDassert(s);
-#else
- HDassert(_vl);
- HDmemcpy(&s, _vl, sizeof(char *));
+#ifndef H5_NO_ALIGNMENT_RESTRICTIONS
+ H5MM_memcpy(&s, _vl, sizeof(char *));
#endif
- FUNC_LEAVE_NOAPI(s)
-} /* end H5T_vlen_str_mem_getptr() */
+ *isnull = (s == NULL ? TRUE : FALSE);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5T__vlen_mem_str_isnull() */
/*-------------------------------------------------------------------------
- * Function: H5T_vlen_str_mem_isnull
+ * Function: H5T__vlen_mem_str_setnull
*
- * Purpose: Checks if a memory string is a NULL pointer
+ * Purpose: Sets a VL info object in memory to the "null" value
*
- * Return: TRUE/FALSE on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
* Saturday, November 8, 2003
*
*-------------------------------------------------------------------------
*/
-static htri_t
-H5T_vlen_str_mem_isnull(const H5F_t H5_ATTR_UNUSED *f, void *_vl)
+static herr_t
+H5T__vlen_mem_str_setnull(H5F_t H5_ATTR_UNUSED *f, void *_vl, void H5_ATTR_UNUSED *_bg)
{
-#ifdef H5_NO_ALIGNMENT_RESTRICTIONS
- char *s=*(char **)_vl; /* Pointer to the user's string information */
-#else
- char *s; /* Pointer to the user's string information */
-#endif
+ char *t = NULL; /* Pointer to temporary buffer allocated */
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
-#ifndef H5_NO_ALIGNMENT_RESTRICTIONS
- HDmemcpy(&s, _vl, sizeof(char *));
-#endif
+ /* Set pointer in user's buffer with memcpy, to avoid alignment issues */
+ H5MM_memcpy(_vl, &t, sizeof(char *));
- FUNC_LEAVE_NOAPI(s==NULL ? TRUE : FALSE)
-} /* end H5T_vlen_str_mem_isnull() */
+ FUNC_LEAVE_NOAPI(SUCCEED) /*lint !e429 The pointer in 't' has been copied */
+} /* end H5T__vlen_mem_str_setnull() */
/*-------------------------------------------------------------------------
- * Function: H5T_vlen_str_mem_read
+ * Function: H5T__vlen_mem_str_read
*
* Purpose: "Reads" the memory based VL string into a buffer
*
@@ -627,35 +725,35 @@ H5T_vlen_str_mem_isnull(const H5F_t H5_ATTR_UNUSED *f, void *_vl)
*-------------------------------------------------------------------------
*/
static herr_t
-H5T_vlen_str_mem_read(H5F_t H5_ATTR_UNUSED *f, void *_vl, void *buf, size_t len)
+H5T__vlen_mem_str_read(H5F_t H5_ATTR_UNUSED *f, void *_vl, void *buf, size_t len)
{
#ifdef H5_NO_ALIGNMENT_RESTRICTIONS
- char *s=*(char **)_vl; /* Pointer to the user's string information */
+ char *s = *(char **)_vl; /* Pointer to the user's string information */
#else
char *s; /* Pointer to the user's string information */
#endif
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
- if(len>0) {
+ if(len > 0) {
/* check parameters */
HDassert(buf);
#ifdef H5_NO_ALIGNMENT_RESTRICTIONS
HDassert(s);
#else
HDassert(_vl);
- HDmemcpy(&s, _vl, sizeof(char *));
+ H5MM_memcpy(&s, _vl, sizeof(char *));
#endif
- HDmemcpy(buf,s,len);
+ H5MM_memcpy(buf, s, len);
} /* end if */
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5T_vlen_str_mem_read() */
+} /* end H5T__vlen_mem_str_read() */
/*-------------------------------------------------------------------------
- * Function: H5T_vlen_str_mem_write
+ * Function: H5T__vlen_mem_str_write
*
* Purpose: "Writes" the memory based VL string from a buffer
*
@@ -667,154 +765,171 @@ H5T_vlen_str_mem_read(H5F_t H5_ATTR_UNUSED *f, void *_vl, void *buf, size_t len)
*-------------------------------------------------------------------------
*/
static herr_t
-H5T_vlen_str_mem_write(H5F_t H5_ATTR_UNUSED *f, const H5T_vlen_alloc_info_t *vl_alloc_info,
+H5T__vlen_mem_str_write(H5F_t H5_ATTR_UNUSED *f, const H5T_vlen_alloc_info_t *vl_alloc_info,
void *_vl, void *buf, void H5_ATTR_UNUSED *_bg, size_t seq_len, size_t base_size)
{
char *t; /* Pointer to temporary buffer allocated */
size_t len; /* Maximum length of the string to copy */
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
/* check parameters */
HDassert(buf);
/* Use the user's memory allocation routine if one is defined */
- if(vl_alloc_info->alloc_func!=NULL) {
- if(NULL==(t = (char *)(vl_alloc_info->alloc_func)((seq_len+1)*base_size,vl_alloc_info->alloc_info)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for VL data")
- } /* end if */
- else { /* Default to system malloc */
+ if(vl_alloc_info->alloc_func != NULL) {
+ if(NULL == (t = (char *)(vl_alloc_info->alloc_func)((seq_len + 1) * base_size, vl_alloc_info->alloc_info)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "application memory allocation routine failed for VL data")
+ } /* end if */
+ else /* Default to system malloc */
if(NULL == (t = (char *)HDmalloc((seq_len + 1) * base_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for VL data")
- } /* end else */
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "memory allocation failed for VL data")
- len=(seq_len*base_size);
- HDmemcpy(t,buf,len);
- t[len]='\0';
+ /* 'write' the string into the buffer, with memcpy() */
+ len = (seq_len * base_size);
+ H5MM_memcpy(t, buf, len);
+ t[len] = '\0';
/* Set pointer in user's buffer with memcpy, to avoid alignment issues */
- HDmemcpy(_vl,&t,sizeof(char *));
+ H5MM_memcpy(_vl, &t, sizeof(char *));
done:
FUNC_LEAVE_NOAPI(ret_value) /*lint !e429 The pointer in 't' has been copied */
-} /* end H5T_vlen_str_mem_write() */
+} /* end H5T__vlen_mem_str_write() */
/*-------------------------------------------------------------------------
- * Function: H5T_vlen_str_mem_setnull
+ * Function: H5T__vlen_disk_getlen
*
- * Purpose: Sets a VL info object in memory to the "null" value
+ * Purpose: Retrieves the length of a disk based VL element.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
- * Saturday, November 8, 2003
+ * Wednesday, June 2, 1999
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5T_vlen_str_mem_setnull(H5F_t H5_ATTR_UNUSED *f, void *_vl, void H5_ATTR_UNUSED *_bg)
+H5T__vlen_disk_getlen(H5F_t H5_ATTR_UNUSED *f, const void *_vl, size_t *seq_len)
{
- char *t=NULL; /* Pointer to temporary buffer allocated */
+ const uint8_t *vl = (const uint8_t *)_vl; /* Pointer to the user's hvl_t information */
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC_NOERR
- /* Set pointer in user's buffer with memcpy, to avoid alignment issues */
- HDmemcpy(_vl,&t,sizeof(char *));
+ /* Check parameters */
+ HDassert(vl);
+ HDassert(seq_len);
- FUNC_LEAVE_NOAPI(SUCCEED) /*lint !e429 The pointer in 't' has been copied */
-} /* end H5T_vlen_str_mem_setnull() */
+ /* Get length of sequence (different from blob size) */
+ UINT32DECODE(vl, *seq_len);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5T__vlen_disk_getlen() */
/*-------------------------------------------------------------------------
- * Function: H5T_vlen_disk_getlen
+ * Function: H5T__vlen_disk_isnull
*
- * Purpose: Retrieves the length of a disk based VL element.
+ * Purpose: Checks if a disk VL info object is the "nil" object
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success / Negative on failure
*
* Programmer: Quincey Koziol
- * Wednesday, June 2, 1999
+ * Saturday, November 8, 2003
*
*-------------------------------------------------------------------------
*/
-static ssize_t
-H5T_vlen_disk_getlen(const void *_vl)
+static herr_t
+H5T__vlen_disk_isnull(const H5F_t *f, void *_vl, hbool_t *isnull)
{
- const uint8_t *vl=(const uint8_t *)_vl; /* Pointer to the disk VL information */
- size_t seq_len = 0; /* Sequence length */
+ H5VL_object_t *vol_obj = NULL;/* Object info */
+ hid_t file_id = H5I_INVALID_HID;
+ uint8_t *vl = (uint8_t *)_vl; /* Pointer to the user's hvl_t information */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC
- /* check parameters */
+ /* Check parameters */
+ HDassert(f);
HDassert(vl);
+ HDassert(isnull);
- UINT32DECODE(vl, seq_len);
-
- FUNC_LEAVE_NOAPI((ssize_t)seq_len)
-} /* end H5T_vlen_disk_getlen() */
+ /* Skip the sequence's length */
+ vl += 4;
-
-/*-------------------------------------------------------------------------
- * Function: H5T_vlen_disk_getptr
- *
- * Purpose: Retrieves the pointer to a disk based VL element.
- *
- * Return: Non-NULL on success/NULL on failure
- *
- * Programmer: Quincey Koziol
- * Saturday, June 12, 2004
- *
- *-------------------------------------------------------------------------
- */
-static void *
-H5T_vlen_disk_getptr(void H5_ATTR_UNUSED *vl)
-{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ /* TODO temporary hack to retrieve file object */
+ if((file_id = H5F__get_file_id((H5F_t *)f, FALSE)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+ if(NULL == (vol_obj = H5VL_vol_object(file_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier")
- /* check parameters */
- HDassert(vl);
+ /* Check if blob ID is "nil" */
+ if(H5VL_blob_specific(vol_obj, vl, H5VL_BLOB_ISNULL, isnull) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to check if a blob ID is 'nil'")
- FUNC_LEAVE_NOAPI(NULL)
-} /* end H5T_vlen_disk_getptr() */
+done:
+ if((file_id != H5I_INVALID_HID) && (H5I_dec_ref(file_id) < 0))
+ HDONE_ERROR(H5E_DATATYPE, H5E_CANTDEC, FAIL, "unable to decrement refcount on file id")
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T__vlen_disk_isnull() */
/*-------------------------------------------------------------------------
- * Function: H5T_vlen_disk_isnull
+ * Function: H5T__vlen_disk_setnull
*
- * Purpose: Checks if a disk VL info object is the "nil" object
+ * Purpose: Sets a VL info object on disk to the "nil" value
*
- * Return: TRUE/FALSE on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
* Saturday, November 8, 2003
*
*-------------------------------------------------------------------------
*/
-static htri_t
-H5T_vlen_disk_isnull(const H5F_t *f, void *_vl)
+static herr_t
+H5T__vlen_disk_setnull(H5F_t *f, void *_vl, void *bg)
{
- uint8_t *vl = (uint8_t *)_vl; /* Pointer to the disk VL information */
- haddr_t addr; /* Sequence's heap address */
+ H5VL_object_t *vol_obj = NULL;/* Object info */
+ hid_t file_id = H5I_INVALID_HID;
+ uint8_t *vl = (uint8_t *)_vl; /* Pointer to the user's hvl_t information */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ FUNC_ENTER_STATIC
/* check parameters */
+ HDassert(f);
HDassert(vl);
- /* Skip the sequence's length */
- vl += 4;
+ /* Free heap object for old data */
+ if(bg != NULL)
+ /* Delete sequence in destination location */
+ if(H5T__vlen_disk_delete(f, bg) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREMOVE, FAIL, "unable to remove background heap object")
- /* Get the heap address */
- H5F_addr_decode(f, (const uint8_t **)&vl, &addr);
+ /* Set the length of the sequence */
+ UINT32ENCODE(vl, 0);
+
+ /* TODO temporary hack to retrieve file object */
+ if((file_id = H5F__get_file_id(f, FALSE)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+ if(NULL == (vol_obj = H5VL_vol_object(file_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier")
+
+ /* Set blob ID to "nil" */
+ if(H5VL_blob_specific(vol_obj, vl, H5VL_BLOB_SETNULL) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "unable to set a blob ID to 'nil'")
- FUNC_LEAVE_NOAPI(addr == 0 ? TRUE : FALSE)
-} /* end H5T_vlen_disk_isnull() */
+done:
+ if((file_id != H5I_INVALID_HID) && (H5I_dec_ref(file_id) < 0))
+ HDONE_ERROR(H5E_DATATYPE, H5E_CANTDEC, FAIL, "unable to decrement refcount on file id")
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T__vlen_disk_setnull() */
/*-------------------------------------------------------------------------
- * Function: H5T_vlen_disk_read
+ * Function: H5T__vlen_disk_read
*
* Purpose: Reads the disk based VL element into a buffer
*
@@ -826,40 +941,42 @@ H5T_vlen_disk_isnull(const H5F_t *f, void *_vl)
*-------------------------------------------------------------------------
*/
static herr_t
-H5T_vlen_disk_read(H5F_t *f, void *_vl, void *buf, size_t H5_ATTR_UNUSED len)
+H5T__vlen_disk_read(H5F_t *f, void *_vl, void *buf, size_t H5_ATTR_UNUSED len)
{
- uint8_t *vl=(uint8_t *)_vl; /* Pointer to the user's hvl_t information */
- H5HG_t hobjid;
- herr_t ret_value=SUCCEED; /* Return value */
+ H5VL_object_t *vol_obj = NULL;/* Object info */
+ hid_t file_id = H5I_INVALID_HID;
+ const uint8_t *vl = (const uint8_t *)_vl; /* Pointer to the user's hvl_t information */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
- /* check parameters */
+ /* Check parameters */
+ HDassert(f);
HDassert(vl);
HDassert(buf);
- HDassert(f);
/* Skip the length of the sequence */
vl += 4;
- /* Get the heap information */
- H5F_addr_decode(f, (const uint8_t **)&vl, &(hobjid.addr));
- UINT32DECODE(vl, hobjid.idx);
+ /* TODO temporary hack to retrieve file object */
+ if((file_id = H5F__get_file_id(f, FALSE)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+ if(NULL == (vol_obj = H5VL_vol_object(file_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier")
- /* Check if this sequence actually has any data */
- if(hobjid.addr > 0) {
- /* Read the VL information from disk */
- if(NULL == H5HG_read(f, &hobjid, buf, NULL))
- HGOTO_ERROR(H5E_DATATYPE, H5E_READERROR, FAIL, "Unable to read VL information")
- }
+ /* Retrieve blob */
+ if(H5VL_blob_get(vol_obj, vl, buf, NULL, NULL) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to get blob")
done:
+ if((file_id != H5I_INVALID_HID) && (H5I_dec_ref(file_id) < 0))
+ HDONE_ERROR(H5E_DATATYPE, H5E_CANTDEC, FAIL, "unable to decrement refcount on file id")
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5T_vlen_disk_read() */
+} /* end H5T__vlen_disk_read() */
/*-------------------------------------------------------------------------
- * Function: H5T_vlen_disk_write
+ * Function: H5T__vlen_disk_write
*
* Purpose: Writes the disk based VL element from a buffer
*
@@ -871,146 +988,129 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5T_vlen_disk_write(H5F_t *f, const H5T_vlen_alloc_info_t H5_ATTR_UNUSED *vl_alloc_info,
+H5T__vlen_disk_write(H5F_t *f, const H5T_vlen_alloc_info_t H5_ATTR_UNUSED *vl_alloc_info,
void *_vl, void *buf, void *_bg, size_t seq_len, size_t base_size)
{
- uint8_t *vl = (uint8_t *)_vl; /*Pointer to the user's hvl_t information*/
- uint8_t *bg = (uint8_t *)_bg; /*Pointer to the old data hvl_t */
- H5HG_t hobjid; /* New VL sequence's heap ID */
- size_t len; /* Size of new sequence on disk (in bytes) */
- herr_t ret_value = SUCCEED; /* Return value */
+ H5VL_object_t *vol_obj = NULL; /* Object info */
+ hid_t file_id = H5I_INVALID_HID;
+ uint8_t *vl = (uint8_t *)_vl; /* Pointer to the user's hvl_t information */
+ const uint8_t *bg = (const uint8_t *)_bg; /* Pointer to the old data hvl_t */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
/* check parameters */
HDassert(vl);
HDassert(seq_len == 0 || buf);
HDassert(f);
- /* Free heap object for old data. */
- if(bg!=NULL) {
- H5HG_t bg_hobjid; /* "Background" VL info sequence's ID info */
-
- /* Skip the length of the sequence and heap object ID from background data. */
- bg += 4;
-
- /* Get heap information */
- H5F_addr_decode(f, (const uint8_t **)&bg, &(bg_hobjid.addr));
- UINT32DECODE(bg, bg_hobjid.idx);
-
- /* Free heap object for old data */
- if(bg_hobjid.addr > 0) {
- /* Free heap object */
- if(H5HG_remove(f, &bg_hobjid) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_WRITEERROR, FAIL, "Unable to remove heap object")
- }
- } /* end if */
+ /* Free heap object for old data, if non-NULL */
+ if(bg != NULL)
+ if(H5T__vlen_disk_delete(f, bg) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREMOVE, FAIL, "unable to remove background heap object")
/* Set the length of the sequence */
UINT32ENCODE(vl, seq_len);
- /* Write the VL information to disk (allocates space also) */
- len = (seq_len*base_size);
- if(H5HG_insert(f, len, buf, &hobjid) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_WRITEERROR, FAIL, "Unable to write VL information")
+ /* TODO temporary hack to retrieve file object */
+ if((file_id = H5F__get_file_id(f, FALSE)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+ if(NULL == (vol_obj = H5VL_vol_object(file_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier")
- /* Encode the heap information */
- H5F_addr_encode(f, &vl, hobjid.addr);
- UINT32ENCODE(vl, hobjid.idx);
+ /* Store blob */
+ if(H5VL_blob_put(vol_obj, buf, (seq_len * base_size), vl, NULL) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "unable to put blob")
done:
+ if((file_id != H5I_INVALID_HID) && (H5I_dec_ref(file_id) < 0))
+ HDONE_ERROR(H5E_DATATYPE, H5E_CANTDEC, FAIL, "unable to decrement refcount on file id")
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5T_vlen_disk_write() */
+} /* end H5T__vlen_disk_write() */
/*-------------------------------------------------------------------------
- * Function: H5T_vlen_disk_setnull
+ * Function: H5T__vlen_disk_delete
*
- * Purpose: Sets a VL info object on disk to the "nil" value
+ * Purpose: Deletes a disk-based VL element
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success / Negative on failure
*
* Programmer: Quincey Koziol
- * Saturday, November 8, 2003
+ * Friday, August 15, 2019
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5T_vlen_disk_setnull(H5F_t *f, void *_vl, void *_bg)
+H5T__vlen_disk_delete(H5F_t *f, const void *_vl)
{
- uint8_t *vl = (uint8_t *)_vl; /*Pointer to the user's hvl_t information*/
- uint8_t *bg = (uint8_t *)_bg; /*Pointer to the old data hvl_t */
- uint32_t seq_len = 0; /* Sequence length */
- herr_t ret_value = SUCCEED; /* Return value */
+ const uint8_t *vl = (const uint8_t *)_vl; /* Pointer to the user's hvl_t information */
+ hid_t file_id = H5I_INVALID_HID;
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
- /* check parameters */
+ /* Check parameters */
HDassert(f);
- HDassert(vl);
- /* Free heap object for old data. */
- if(bg != NULL) {
- H5HG_t bg_hobjid; /* "Background" VL info sequence's ID info */
+ /* Free heap object for old data */
+ if(vl != NULL) {
+ size_t seq_len; /* VL sequence's length */
- /* Skip the length of the sequence and heap object ID from background data. */
- bg += 4;
+ /* Get length of sequence */
+ UINT32DECODE(vl, seq_len);
- /* Get heap information */
- H5F_addr_decode(f, (const uint8_t **)&bg, &(bg_hobjid.addr));
- UINT32DECODE(bg, bg_hobjid.idx);
+ /* Delete object, if length > 0 */
+ if(seq_len > 0) {
+ H5VL_object_t *vol_obj = NULL; /* Object info */
- /* Free heap object for old data */
- if(bg_hobjid.addr > 0) {
- /* Free heap object */
- if(H5HG_remove(f, &bg_hobjid) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_WRITEERROR, FAIL, "Unable to remove heap object")
- } /* end if */
- } /* end if */
+ /* TODO temporary hack to retrieve file object */
+ if((file_id = H5F__get_file_id(f, FALSE)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+ if(NULL == (vol_obj = H5VL_vol_object(file_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier")
- /* Set the length of the sequence */
- UINT32ENCODE(vl, seq_len);
-
- /* Encode the "nil" heap pointer information */
- H5F_addr_encode(f, &vl, (haddr_t)0);
- UINT32ENCODE(vl, 0);
+ if(H5VL_blob_specific(vol_obj, (void *)vl, H5VL_BLOB_DELETE) < 0) /* Casting away 'const' OK -QAK */
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREMOVE, FAIL, "unable to delete blob")
+ }
+ } /* end if */
done:
+ if((file_id != H5I_INVALID_HID) && (H5I_dec_ref(file_id) < 0))
+ HDONE_ERROR(H5E_DATATYPE, H5E_CANTDEC, FAIL, "unable to decrement refcount on file id")
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5T_vlen_disk_setnull() */
+} /* end H5T__vlen_disk_delete() */
-/*--------------------------------------------------------------------------
- NAME
- H5T_vlen_reclaim_recurse
- PURPOSE
- Internal recursive routine to free VL datatypes
- USAGE
- herr_t H5T_vlen_reclaim_recurse(elem,dt)
- void *elem; IN/OUT: Pointer to the dataset element
- H5T_t *dt; IN: Datatype of dataset element
-
- RETURNS
- SUCCEED/FAIL
- DESCRIPTION
- Frees any dynamic memory used by VL datatypes in the current dataset
- element. Performs a recursive depth-first traversal of all compound
- datatypes to free all VL datatype information allocated by any field.
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
-static herr_t
-H5T_vlen_reclaim_recurse(void *elem, const H5T_t *dt, H5MM_free_t free_func, void *free_info)
+/*-------------------------------------------------------------------------
+ * Function: H5T_vlen_reclaim
+ *
+ * Purpose: Internal recursive routine to free VL datatypes
+ *
+ * Return: Non-negative on success / Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Friday, August 15, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5T_vlen_reclaim(void *elem, const H5T_t *dt, H5T_vlen_alloc_info_t *alloc_info)
{
unsigned u; /* Local index variable */
+ H5MM_free_t free_func; /* Free function */
+ void *free_info; /* Free info */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_NOAPI(FAIL)
+ /* Sanity checks */
HDassert(elem);
HDassert(dt);
+ HDassert(alloc_info);
+
+ free_func = alloc_info->free_func;
+ free_info = alloc_info->free_info;
/* Check the datatype of this element */
switch(dt->shared->type) {
@@ -1022,8 +1122,8 @@ H5T_vlen_reclaim_recurse(void *elem, const H5T_t *dt, H5MM_free_t free_func, voi
/* Calculate the offset member and recurse on it */
for(u = 0; u < dt->shared->u.array.nelem; u++) {
off = ((uint8_t *)elem) + u * (dt->shared->parent->shared->size);
- if(H5T_vlen_reclaim_recurse(off, dt->shared->parent, free_func, free_info) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "Unable to free array element")
+ if(H5T_reclaim_cb(off, dt->shared->parent, 0, NULL, alloc_info) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "unable to free array element")
} /* end for */
} /* end if */
break;
@@ -1037,8 +1137,8 @@ H5T_vlen_reclaim_recurse(void *elem, const H5T_t *dt, H5MM_free_t free_func, voi
/* Calculate the offset member and recurse on it */
off = ((uint8_t *)elem) + dt->shared->u.compnd.memb[u].offset;
- if(H5T_vlen_reclaim_recurse(off, dt->shared->u.compnd.memb[u].type, free_func, free_info) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "Unable to free compound field")
+ if(H5T_reclaim_cb(off, dt->shared->u.compnd.memb[u].type, 0, NULL, alloc_info) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "unable to free compound field")
} /* end if */
} /* end for */
break;
@@ -1057,8 +1157,8 @@ H5T_vlen_reclaim_recurse(void *elem, const H5T_t *dt, H5MM_free_t free_func, voi
/* Calculate the offset of each array element and recurse on it */
while(vl->len > 0) {
off = ((uint8_t *)vl->p) + (vl->len - 1) * dt->shared->parent->shared->size;
- if(H5T_vlen_reclaim_recurse(off, dt->shared->parent, free_func, free_info) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "Unable to free VL element")
+ if(H5T_reclaim_cb(off, dt->shared->parent, 0, NULL, alloc_info) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "unable to free VL element")
vl->len--;
} /* end while */
} /* end if */
@@ -1087,11 +1187,11 @@ H5T_vlen_reclaim_recurse(void *elem, const H5T_t *dt, H5MM_free_t free_func, voi
case H5T_STRING:
case H5T_BITFIELD:
case H5T_OPAQUE:
- case H5T_REFERENCE:
case H5T_ENUM:
break;
/* Should never have these values */
+ case H5T_REFERENCE:
case H5T_NO_CLASS:
case H5T_NCLASSES:
default:
@@ -1102,66 +1202,15 @@ H5T_vlen_reclaim_recurse(void *elem, const H5T_t *dt, H5MM_free_t free_func, voi
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5T_vlen_reclaim_recurse() */
-
-
-/*--------------------------------------------------------------------------
- NAME
- H5T_vlen_reclaim
- PURPOSE
- Default method to reclaim any VL data for a buffer element
- USAGE
- herr_t H5T_vlen_reclaim(elem,type_id,ndim,point,op_data)
- void *elem; IN/OUT: Pointer to the dataset element
- hid_t type_id; IN: Datatype of dataset element
- unsigned ndim; IN: Number of dimensions in dataspace
- hsize_t *point; IN: Coordinate location of element in dataspace
- void *op_data IN: Operator data
-
- RETURNS
- SUCCEED/FAIL
- DESCRIPTION
- Frees any dynamic memory used by VL datatypes in the current dataset
- element. Recursively descends compound datatypes to free all VL datatype
- information allocated by any field.
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
-herr_t
-H5T_vlen_reclaim(void *elem, hid_t type_id, unsigned H5_ATTR_UNUSED ndim,
- const hsize_t H5_ATTR_UNUSED *point, void *op_data)
-{
- H5T_vlen_alloc_info_t *vl_alloc_info = (H5T_vlen_alloc_info_t *)op_data; /* VL allocation info from iterator */
- H5T_t *dt;
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(FAIL)
-
- HDassert(elem);
- HDassert(vl_alloc_info);
- HDassert(H5I_DATATYPE == H5I_get_type(type_id));
-
- /* Check args */
- if(NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
-
- /* Pull the free function and free info pointer out of the op_data and call the recurse datatype free function */
- if(H5T_vlen_reclaim_recurse(elem, dt, vl_alloc_info->free_func, vl_alloc_info->free_info) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "can't reclaim vlen elements")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5T_vlen_reclaim() */
+} /* end H5T_vlen_reclaim() */
/*-------------------------------------------------------------------------
* Function: H5T_vlen_reclaim_elmt
*
* Purpose: Alternative method to reclaim any VL data for a buffer element.
- *
- * Use this function when the datatype is already available, but
+ *
+ * Use this function when the datatype is already available, but
* the allocation info is needed from the context before jumping
* into recursion.
*
@@ -1188,10 +1237,9 @@ H5T_vlen_reclaim_elmt(void *elem, H5T_t *dt)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to retrieve VL allocation info")
/* Recurse on buffer to free dynamic fields */
- if(H5T_vlen_reclaim_recurse(elem, dt, vl_alloc_info.free_func, vl_alloc_info.free_info) < 0)
+ if(H5T_vlen_reclaim(elem, dt, &vl_alloc_info) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "can't reclaim vlen elements")
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5T_vlen_reclaim_elmt */
-
+} /* H5T_vlen_reclaim_elmt() */
diff --git a/src/H5VL.c b/src/H5VL.c
new file mode 100644
index 0000000..5c62f6f
--- /dev/null
+++ b/src/H5VL.c
@@ -0,0 +1,660 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Purpose: The Virtual Object Layer as described in documentation.
+ * The pupose is to provide an abstraction on how to access the
+ * underlying HDF5 container, whether in a local file with
+ * a specific file format, or remotely on other machines, etc...
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#include "H5VLmodule.h" /* This source code file is part of the H5VL module */
+
+
+/***********/
+/* Headers */
+/***********/
+
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Iprivate.h" /* IDs */
+#include "H5Pprivate.h" /* Property lists */
+#include "H5VLpkg.h" /* Virtual Object Layer */
+
+/* VOL connectors */
+#include "H5VLnative.h" /* Native VOL connector */
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLregister_connector
+ *
+ * Purpose: Registers a new VOL connector as a member of the virtual object
+ * layer class.
+ *
+ * VIPL_ID is a VOL initialization property list which must be
+ * created with H5Pcreate(H5P_VOL_INITIALIZE) (or H5P_DEFAULT).
+ *
+ * Return: Success: A VOL connector ID which is good until the
+ * library is closed or the connector is
+ * unregistered.
+ *
+ * Failure: H5I_INVALID_HID
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5VLregister_connector(const H5VL_class_t *cls, hid_t vipl_id)
+{
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
+
+ FUNC_ENTER_API(H5I_INVALID_HID)
+ H5TRACE2("i", "*xi", cls, vipl_id);
+
+ /* Check arguments */
+ if (!cls)
+ HGOTO_ERROR(H5E_ARGS, H5E_UNINITIALIZED, H5I_INVALID_HID, "VOL connector class pointer cannot be NULL")
+ if (!cls->name)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "VOL connector class name cannot be the NULL pointer")
+ if (0 == HDstrlen(cls->name))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "VOL connector class name cannot be the empty string")
+ if (cls->info_cls.copy && !cls->info_cls.free)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "VOL connector must provide free callback for VOL info objects when a copy callback is provided")
+ if (cls->wrap_cls.get_wrap_ctx && !cls->wrap_cls.free_wrap_ctx)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "VOL connector must provide free callback for object wrapping contexts when a get callback is provided")
+
+ /* Check VOL initialization property list */
+ if(H5P_DEFAULT == vipl_id)
+ vipl_id = H5P_VOL_INITIALIZE_DEFAULT;
+ else
+ if(TRUE != H5P_isa_class(vipl_id, H5P_VOL_INITIALIZE))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a VOL initialize property list")
+
+ /* Register connector */
+ if((ret_value = H5VL__register_connector(cls, TRUE, vipl_id)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VOL connector")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5VLregister_connector() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLregister_connector_by_name
+ *
+ * Purpose: Registers a new VOL connector as a member of the virtual object
+ * layer class.
+ *
+ * VIPL_ID is a VOL initialization property list which must be
+ * created with H5Pcreate(H5P_VOL_INITIALIZE) (or H5P_DEFAULT).
+ *
+ * Return: Success: A VOL connector ID which is good until the
+ * library is closed or the connector is
+ * unregistered.
+ *
+ * Failure: H5I_INVALID_HID
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5VLregister_connector_by_name(const char *name, hid_t vipl_id)
+{
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
+
+ FUNC_ENTER_API(H5I_INVALID_HID)
+ H5TRACE2("i", "*si", name, vipl_id);
+
+ /* Check arguments */
+ if (!name)
+ HGOTO_ERROR(H5E_ARGS, H5E_UNINITIALIZED, H5I_INVALID_HID, "null VOL connector name is disallowed")
+ if (0 == HDstrlen(name))
+ HGOTO_ERROR(H5E_ARGS, H5E_UNINITIALIZED, H5I_INVALID_HID, "zero-length VOL connector name is disallowed")
+
+ /* Check VOL initialization property list */
+ if(H5P_DEFAULT == vipl_id)
+ vipl_id = H5P_VOL_INITIALIZE_DEFAULT;
+ else
+ if(TRUE != H5P_isa_class(vipl_id, H5P_VOL_INITIALIZE))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a VOL initialize property list")
+
+ /* Register connector */
+ if((ret_value = H5VL__register_connector_by_name(name, TRUE, vipl_id)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VOL connector")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5VLregister_connector_by_name() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLregister_connector_by_value
+ *
+ * Purpose: Registers a new VOL connector as a member of the virtual object
+ * layer class.
+ *
+ * VIPL_ID is a VOL initialization property list which must be
+ * created with H5Pcreate(H5P_VOL_INITIALIZE) (or H5P_DEFAULT).
+ *
+ * Return: Success: A VOL connector ID which is good until the
+ * library is closed or the connector is
+ * unregistered.
+ *
+ * Failure: H5I_INVALID_HID
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5VLregister_connector_by_value(H5VL_class_value_t value, hid_t vipl_id)
+{
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
+
+ FUNC_ENTER_API(H5I_INVALID_HID)
+ H5TRACE2("i", "VCi", value, vipl_id);
+
+ /* Check arguments */
+ if(value < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_UNINITIALIZED, H5I_INVALID_HID, "negative VOL connector value is disallowed")
+
+ /* Check VOL initialization property list */
+ if(H5P_DEFAULT == vipl_id)
+ vipl_id = H5P_VOL_INITIALIZE_DEFAULT;
+ else
+ if(TRUE != H5P_isa_class(vipl_id, H5P_VOL_INITIALIZE))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a VOL initialize property list")
+
+ /* Register connector */
+ if((ret_value = H5VL__register_connector_by_value(value, TRUE, vipl_id)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VOL connector")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5VLregister_connector_by_value() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLis_connector_registered
+ *
+ * Purpose: Tests whether a VOL class has been registered or not
+ *
+ * Return: >0 if a VOL connector with that name has been registered
+ * 0 if a VOL connector with that name has NOT been registered
+ * <0 on errors
+ *
+ * Programmer: Dana Robinson
+ * June 17, 2017
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5VLis_connector_registered(const char *name)
+{
+ htri_t ret_value = FALSE; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE1("t", "*s", name);
+
+ /* Check if connector with this name is registered */
+ if((ret_value = H5VL__is_connector_registered(name)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't check for VOL")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5VLis_connector_registered() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLget_connector_id
+ *
+ * Purpose: Retrieves the ID for a registered VOL connector.
+ *
+ * Return: A valid VOL connector ID if a connector by that name has
+ * been registered. This ID will need to be closed using
+ * H5VLclose().
+ *
+ * H5I_INVALID_HID on error or if a VOL connector of that
+ * name has not been registered.
+ *
+ * Programmer: Dana Robinson
+ * June 17, 2017
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5VLget_connector_id(const char *name)
+{
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
+
+ FUNC_ENTER_API(H5I_INVALID_HID)
+ H5TRACE1("i", "*s", name);
+
+ /* Get connector ID with this name */
+ if((ret_value = H5VL__get_connector_id(name, TRUE)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, H5I_INVALID_HID, "can't get VOL id")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5VLget_connector_id() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLget_connector_name
+ *
+ * Purpose: Returns the connector name for the VOL associated with the
+ * object or file ID.
+ *
+ * This works like other calls where the caller must provide a
+ * buffer of the appropriate size for the library to fill in.
+ * i.e., passing in a NULL pointer for NAME will return the
+ * required size of the buffer.
+ *
+ * Return: Success: The length of the connector name
+ *
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+ssize_t
+H5VLget_connector_name(hid_t obj_id, char *name/*out*/, size_t size)
+{
+ ssize_t ret_value = -1;
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE3("Zs", "ixz", obj_id, name, size);
+
+ /* Call internal routine */
+ if((ret_value = H5VL__get_connector_name(obj_id, name, size)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "Can't get connector name")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5VLget_connector_name() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLclose
+ *
+ * Purpose: Closes a VOL connector ID. This in no way affects
+ * file access property lists which have been defined to use
+ * this VOL connector or files which are already opened under with
+ * this connector.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLclose(hid_t vol_id)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE1("e", "i", vol_id);
+
+ /* Check args */
+ if(NULL == H5I_object_verify(vol_id, H5I_VOL))
+ HGOTO_ERROR(H5E_VOL, H5E_BADTYPE, FAIL, "not a VOL connector")
+
+ /* Decrement the ref count on the ID, possibly releasing the VOL connector */
+ if(H5I_dec_app_ref(vol_id) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTDEC, FAIL, "unable to close VOL connector ID")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5VLclose() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLunregister_connector
+ *
+ * Purpose: Removes a VOL connector ID from the library. This in no way affects
+ * file access property lists which have been defined to use
+ * this VOL connector or files which are already opened under with
+ * this connector.
+ *
+ * The native VOL connector cannot be unregistered and attempts
+ * to do so are considered an error.
+ *
+ * Return: Success: Non-negative
+ *
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLunregister_connector(hid_t vol_id)
+{
+ hid_t native_id = H5I_INVALID_HID;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE1("e", "i", vol_id);
+
+ /* Check arguments */
+ if(NULL == H5I_object_verify(vol_id, H5I_VOL))
+ HGOTO_ERROR(H5E_VOL, H5E_BADTYPE, FAIL, "not a VOL connector ID")
+
+ /* For the time being, we disallow unregistering the native VOL connector */
+ if(H5I_INVALID_HID == (native_id = H5VL__get_connector_id(H5VL_NATIVE_NAME, FALSE)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "unable to find the native VOL connector ID")
+ if(vol_id == native_id)
+ HGOTO_ERROR(H5E_VOL, H5E_BADVALUE, FAIL, "unregistering the native VOL connector is not allowed")
+
+ /* The H5VL_class_t struct will be freed by this function */
+ if(H5I_dec_app_ref(vol_id) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTDEC, FAIL, "unable to unregister VOL connector")
+
+done:
+ if(native_id != H5I_INVALID_HID)
+ if(H5I_dec_ref(native_id) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTDEC, FAIL, "unable to decrement count on native_id")
+
+ FUNC_LEAVE_API(ret_value)
+} /* end H5VLunregister_connector() */
+
+
+/*---------------------------------------------------------------------------
+ * Function: H5VLcmp_connector_cls
+ *
+ * Purpose: Compares two connector classes (based on their value field)
+ *
+ * Note: This routine is _only_ for HDF5 VOL connector authors! It is
+ * _not_ part of the public API for HDF5 application developers.
+ *
+ * Return: Success: Non-negative, *cmp set to a value like strcmp
+ *
+ * Failure: Negative, *cmp unset
+ *
+ *---------------------------------------------------------------------------
+ */
+herr_t
+H5VLcmp_connector_cls(int *cmp, hid_t connector_id1, hid_t connector_id2)
+{
+ H5VL_class_t *cls1, *cls2; /* connectors for IDs */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE3("e", "*Isii", cmp, connector_id1, connector_id2);
+
+ /* Check args and get class pointers */
+ if(NULL == (cls1 = (H5VL_class_t *)H5I_object_verify(connector_id1, H5I_VOL)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a VOL connector ID")
+ if(NULL == (cls2 = (H5VL_class_t *)H5I_object_verify(connector_id2, H5I_VOL)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a VOL connector ID")
+
+ /* Compare the two VOL connector classes */
+ if(H5VL_cmp_connector_cls(cmp, cls1, cls2) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCOMPARE, FAIL, "can't compare connector classes")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* H5VLcmp_connector_cls() */
+
+
+/*---------------------------------------------------------------------------
+ * Function: H5VLwrap_register
+ *
+ * Purpose: Wrap an internal object with a "wrap context" and register an
+ * hid_t for the resulting object.
+ *
+ * Note: This routine is mainly targeted toward wrapping objects for
+ * iteration routine callbacks (i.e. the callbacks from H5Aiterate*,
+ * H5Literate* / H5Lvisit*, and H5Ovisit* ).
+ *
+ * Return: Success: Non-negative hid_t for the object.
+ * Failure: Negative (H5I_INVALID_HID)
+ *
+ *---------------------------------------------------------------------------
+ */
+hid_t
+H5VLwrap_register(void *obj, H5I_type_t type)
+{
+ hid_t ret_value; /* Return value */
+
+ /* Use FUNC_ENTER_API_NOINIT here, so the API context doesn't get reset */
+ FUNC_ENTER_API_NOINIT
+ H5TRACE2("i", "*xIt", obj, type);
+
+ /* Check args */
+ if(type <= H5I_BADID || type >= H5I_NTYPES)
+ HGOTO_ERROR(H5E_VOL, H5E_BADRANGE, H5I_INVALID_HID, "invalid type number")
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_VOL, H5E_BADVALUE, H5I_INVALID_HID, "obj is NULL")
+
+ /* Wrap the object and register an ID for it */
+ if((ret_value = H5VL_wrap_register(type, obj, TRUE)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to wrap object")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* H5VLwrap_register() */
+
+
+/*---------------------------------------------------------------------------
+ * Function: H5VLobject
+ *
+ * Purpose: Retrieve the object pointer associated with an hid_t for a.
+ * VOL object.
+ *
+ * Note: This routine is mainly targeted toward unwrapping objects for
+ * testing.
+ *
+ * Return: Success: Object pointer
+ * Failure: NULL
+ *
+ *---------------------------------------------------------------------------
+ */
+void *
+H5VLobject(hid_t id)
+{
+ void *ret_value; /* Return value */
+
+ FUNC_ENTER_API(NULL)
+ H5TRACE1("*x", "i", id);
+
+ /* Retrieve the object pointer for the ID */
+ if(NULL == (ret_value = H5VL_object(id)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, NULL, "unable to retrieve object")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* H5VLobject() */
+
+
+/*---------------------------------------------------------------------------
+ * Function: H5VLretrieve_lib_state
+ *
+ * Purpose: Retrieves a copy of the internal state of the HDF5 library,
+ * so that it can be restored later.
+ *
+ * Note: This routine is _only_ for HDF5 VOL connector authors! It is
+ * _not_ part of the public API for HDF5 application developers.
+ *
+ * Return: Success: Non-negative, *state set
+ * Failure: Negative, *state unset
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, January 10, 2019
+ *
+ *---------------------------------------------------------------------------
+ */
+herr_t
+H5VLretrieve_lib_state(void **state)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ /* Must use this, to avoid modifying the API context stack in FUNC_ENTER */
+ FUNC_ENTER_API_NOINIT
+ H5TRACE1("e", "**x", state);
+
+ /* Check args */
+ if(NULL == state)
+ HGOTO_ERROR(H5E_VOL, H5E_BADVALUE, FAIL, "invalid state pointer")
+
+ /* Retrieve the library state */
+ if(H5VL_retrieve_lib_state(state) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't retrieve library state")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* H5VLretrieve_lib_state() */
+
+
+/*---------------------------------------------------------------------------
+ * Function: H5VLrestore_lib_state
+ *
+ * Purpose: Restores the internal state of the HDF5 library.
+ *
+ * Note: This routine is _only_ for HDF5 VOL connector authors! It is
+ * _not_ part of the public API for HDF5 application developers.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, January 10, 2019
+ *
+ *---------------------------------------------------------------------------
+ */
+herr_t
+H5VLrestore_lib_state(const void *state)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ /* Must use this, to avoid modifying the API context stack in FUNC_ENTER */
+ FUNC_ENTER_API_NOINIT
+ H5TRACE1("e", "*x", state);
+
+ /* Check args */
+ if(NULL == state)
+ HGOTO_ERROR(H5E_VOL, H5E_BADVALUE, FAIL, "invalid state pointer")
+
+ /* Restore the library state */
+ if(H5VL_restore_lib_state(state) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't restore library state")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* H5VLrestore_lib_state() */
+
+
+/*---------------------------------------------------------------------------
+ * Function: H5VLreset_lib_state
+ *
+ * Purpose: Resets the internal state of the HDF5 library, undoing the
+ * affects of H5VLrestore_lib_state.
+ *
+ * Note: This routine is _only_ for HDF5 VOL connector authors! It is
+ * _not_ part of the public API for HDF5 application developers.
+ *
+ * Note: This routine must be called as a "pair" with
+ * H5VLrestore_lib_state. It can be called before / after /
+ * independently of H5VLfree_lib_state.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Saturday, February 23, 2019
+ *
+ *---------------------------------------------------------------------------
+ */
+herr_t
+H5VLreset_lib_state(void)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ /* Must use this, to avoid modifying the API context stack in FUNC_ENTER */
+ FUNC_ENTER_API_NOINIT
+ H5TRACE0("e","");
+
+ /* Reset the library state */
+ if(H5VL_reset_lib_state() < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTRESET, FAIL, "can't reset library state")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* H5VLreset_lib_state() */
+
+
+/*---------------------------------------------------------------------------
+ * Function: H5VLfree_lib_state
+ *
+ * Purpose: Free a retrieved library state.
+ *
+ * Note: This routine is _only_ for HDF5 VOL connector authors! It is
+ * _not_ part of the public API for HDF5 application developers.
+ *
+ * Note: This routine must be called as a "pair" with
+ * H5VLretrieve_lib_state.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, January 10, 2019
+ *
+ *---------------------------------------------------------------------------
+ */
+herr_t
+H5VLfree_lib_state(void *state)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE1("e", "*x", state);
+
+ /* Check args */
+ if(NULL == state)
+ HGOTO_ERROR(H5E_VOL, H5E_BADVALUE, FAIL, "invalid state pointer")
+
+ /* Free the library state */
+ if(H5VL_free_lib_state(state) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "can't free library state")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* H5VLfree_lib_state() */
+
diff --git a/src/H5VLcallback.c b/src/H5VLcallback.c
new file mode 100644
index 0000000..e486fde
--- /dev/null
+++ b/src/H5VLcallback.c
@@ -0,0 +1,7024 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Purpose: The Virtual Object Layer as described in documentation.
+ * The pupose is to provide an abstraction on how to access the
+ * underlying HDF5 container, whether in a local file with
+ * a specific file format, or remotely on other machines, etc...
+ */
+
+
+/****************/
+/* Module Setup */
+/****************/
+
+#include "H5VLmodule.h" /* This source code file is part of the H5VL module */
+
+
+/***********/
+/* Headers */
+/***********/
+
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fprivate.h" /* File access */
+#include "H5Iprivate.h" /* IDs */
+#include "H5MMprivate.h" /* Memory management */
+#include "H5Pprivate.h" /* Property lists */
+#include "H5VLpkg.h" /* Virtual Object Layer */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+static void *H5VL__attr_create(void *obj, const H5VL_loc_params_t *loc_params,
+ const H5VL_class_t *cls, const char *name, hid_t type_id, hid_t space_id,
+ hid_t acpl_id, hid_t aapl_id, hid_t dxpl_id, void **req);
+static void *H5VL__attr_open(void *obj, const H5VL_loc_params_t *loc_params,
+ const H5VL_class_t *cls, const char *name, hid_t aapl_id, hid_t dxpl_id,
+ void **req);
+static herr_t H5VL__attr_read(void *obj, const H5VL_class_t *cls, hid_t mem_type_id,
+ void *buf, hid_t dxpl_id, void **req);
+static herr_t H5VL__attr_write(void *obj, const H5VL_class_t *cls, hid_t mem_type_id,
+ const void *buf, hid_t dxpl_id, void **req);
+static herr_t H5VL__attr_get(void *obj, const H5VL_class_t *cls, H5VL_attr_get_t get_type,
+ hid_t dxpl_id, void **req, va_list arguments);
+static herr_t H5VL__attr_specific(void *obj, const H5VL_loc_params_t *loc_params,
+ const H5VL_class_t *cls, H5VL_attr_specific_t specific_type, hid_t dxpl_id,
+ void **req, va_list arguments);
+static herr_t H5VL__attr_optional(void *obj, const H5VL_class_t *cls, hid_t dxpl_id,
+ void **req, va_list arguments);
+static herr_t H5VL__attr_close(void *obj, const H5VL_class_t *cls, hid_t dxpl_id,
+ void **req);
+static void *H5VL__dataset_create(void *obj, const H5VL_loc_params_t *loc_params,
+ const H5VL_class_t *cls, const char *name, hid_t lcpl_id, hid_t type_id,
+ hid_t space_id, 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 plist_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 plist_id,
+ const void *buf, void **req);
+static herr_t H5VL__dataset_get(void *obj, const H5VL_class_t *cls, H5VL_dataset_get_t get_type,
+ hid_t dxpl_id, void **req, va_list arguments);
+static herr_t H5VL__dataset_specific(void *obj, const H5VL_class_t *cls,
+ H5VL_dataset_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments);
+static herr_t H5VL__dataset_optional(void *obj, const H5VL_class_t *cls,
+ hid_t dxpl_id, void **req, va_list arguments);
+static herr_t H5VL__dataset_close(void *obj, const H5VL_class_t *cls, hid_t dxpl_id,
+ void **req);
+static void * H5VL__file_create(const H5VL_class_t *cls, const char *name,
+ unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t dxpl_id, void **req);
+static void * H5VL__file_open(const H5VL_class_t *cls, const char *name,
+ unsigned flags, hid_t fapl_id, hid_t dxpl_id, void **req);
+static herr_t H5VL__file_get(void *obj, const H5VL_class_t *cls, H5VL_file_get_t get_type,
+ hid_t dxpl_id, void **req, va_list arguments);
+static herr_t H5VL__file_specific(void *obj, const H5VL_class_t *cls, H5VL_file_specific_t specific_type,
+ hid_t dxpl_id, void **req, va_list arguments);
+static herr_t H5VL__file_optional(void *obj, const H5VL_class_t *cls, hid_t dxpl_id,
+ void **req, va_list arguments);
+static herr_t H5VL__file_close(void *obj, const H5VL_class_t *cls, hid_t dxpl_id,
+ void **req);
+static void *H5VL__group_create(void *obj, const H5VL_loc_params_t *loc_params,
+ const H5VL_class_t *cls, const char *name, hid_t lcpl_id, hid_t gcpl_id,
+ hid_t gapl_id, hid_t dxpl_id, void **req);
+static void *H5VL__group_open(void *obj, const H5VL_loc_params_t *loc_params,
+ const H5VL_class_t *cls, const char *name, hid_t gapl_id, hid_t dxpl_id,
+ void **req);
+static herr_t H5VL__group_get(void *obj, const H5VL_class_t *cls, H5VL_group_get_t get_type,
+ hid_t dxpl_id, void **req, va_list arguments);
+static herr_t H5VL__group_specific(void *obj, const H5VL_class_t *cls, H5VL_group_specific_t specific_type,
+ hid_t dxpl_id, void **req, va_list arguments);
+static herr_t H5VL__group_optional(void *obj, const H5VL_class_t *cls, hid_t dxpl_id,
+ void **req, va_list arguments);
+static herr_t H5VL__group_close(void *obj, const H5VL_class_t *cls,
+ hid_t dxpl_id, void **req);
+static herr_t H5VL__link_create(H5VL_link_create_type_t create_type, void *obj,
+ const H5VL_loc_params_t *loc_params, const H5VL_class_t *cls, hid_t lcpl_id,
+ hid_t lapl_id, hid_t dxpl_id, void **req, va_list arguments);
+static herr_t H5VL__link_copy(void *src_obj, const H5VL_loc_params_t *loc_params1,
+ void *dst_obj, const H5VL_loc_params_t *loc_params2, const H5VL_class_t *cls,
+ hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id, void **req);
+static herr_t H5VL__link_move(void *src_obj, const H5VL_loc_params_t *loc_params1,
+ void *dst_obj, const H5VL_loc_params_t *loc_params2, const H5VL_class_t *cls,
+ hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id, void **req);
+static herr_t H5VL__link_get(void *obj, const H5VL_loc_params_t *loc_params,
+ const H5VL_class_t *cls, H5VL_link_get_t get_type, hid_t dxpl_id,
+ void **req, va_list arguments);
+static herr_t H5VL__link_specific(void *obj, const H5VL_loc_params_t *loc_params,
+ const H5VL_class_t *cls, H5VL_link_specific_t specific_type, hid_t dxpl_id,
+ void **req, va_list arguments);
+static herr_t H5VL__link_optional(void *obj, const H5VL_class_t *cls, hid_t dxpl_id,
+ void **req, va_list arguments);
+static void *H5VL__object_open(void *obj, const H5VL_loc_params_t *params, const H5VL_class_t *cls,
+ H5I_type_t *opened_type, hid_t dxpl_id, void **req);
+static herr_t H5VL__object_copy(void *src_obj, const H5VL_loc_params_t *src_loc_params,
+ const char *src_name, void *dst_obj, const H5VL_loc_params_t *dst_loc_params,
+ const char *dst_name, const H5VL_class_t *cls, hid_t ocpypl_id,
+ hid_t lcpl_id, hid_t dxpl_id, void **req);
+static herr_t H5VL__object_get(void *obj, const H5VL_loc_params_t *loc_params,
+ const H5VL_class_t *cls, H5VL_object_get_t get_type, hid_t dxpl_id,
+ void **req, va_list arguments);
+static herr_t H5VL__object_specific(void *obj, const H5VL_loc_params_t *loc_params,
+ const H5VL_class_t *cls, H5VL_object_specific_t specific_type, hid_t dxpl_id,
+ void **req, va_list arguments);
+static herr_t H5VL__object_optional(void *obj, const H5VL_class_t *cls, hid_t dxpl_id,
+ void **req, va_list arguments);
+static void * H5VL__datatype_commit(void *obj, const H5VL_loc_params_t *loc_params,
+ const H5VL_class_t *cls, const char *name, hid_t type_id, hid_t lcpl_id,
+ hid_t tcpl_id, hid_t tapl_id, hid_t dxpl_id, void **req);
+static void *H5VL__datatype_open(void *obj, const H5VL_loc_params_t *loc_params,
+ const H5VL_class_t *cls, const char *name, hid_t tapl_id, hid_t dxpl_id,
+ void **req);
+static herr_t H5VL__datatype_get(void *obj, const H5VL_class_t *cls,
+ H5VL_datatype_get_t get_type, hid_t dxpl_id, void **req, va_list arguments);
+static herr_t H5VL__datatype_specific(void *obj, const H5VL_class_t *cls,
+ H5VL_datatype_specific_t specific_type, hid_t dxpl_id, void **req,
+ va_list arguments);
+static herr_t H5VL__datatype_optional(void *obj, const H5VL_class_t *cls,
+ hid_t dxpl_id, void **req, va_list arguments);
+static herr_t H5VL__datatype_close(void *obj, const H5VL_class_t *cls, hid_t dxpl_id,
+ void **req);
+static herr_t H5VL__request_wait(void *req, const H5VL_class_t *cls,
+ uint64_t timeout, H5ES_status_t *status);
+static herr_t H5VL__request_notify(void *req, const H5VL_class_t *cls,
+ H5VL_request_notify_t cb, void *ctx);
+static herr_t H5VL__request_cancel(void *req, const H5VL_class_t *cls);
+static herr_t H5VL__request_specific(void *req, const H5VL_class_t *cls,
+ H5VL_request_specific_t specific_type, va_list arguments);
+static herr_t H5VL__request_optional(void *req, const H5VL_class_t *cls,
+ va_list arguments);
+static herr_t H5VL__request_free(void *req, const H5VL_class_t *cls);
+static herr_t H5VL__blob_put(void *obj, const H5VL_class_t *cls,
+ const void *buf, size_t size, void *blob_id, void *ctx);
+static herr_t H5VL__blob_get(void *obj, const H5VL_class_t *cls,
+ const void *blob_id, void *buf, size_t *size, void *ctx);
+static herr_t H5VL__blob_specific(void *obj, const H5VL_class_t *cls,
+ void *blob_id, H5VL_blob_specific_t specific_type, va_list arguments);
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLinitialize
+ *
+ * Purpose: Calls the connector-specific callback to initialize the connector.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLinitialize(hid_t connector_id, hid_t vipl_id)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE2("e", "ii", connector_id, vipl_id);
+
+ /* Check args */
+ 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")
+
+ /* Invoke class' callback, if there is one */
+ if(cls->initialize && cls->initialize(vipl_id) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCLOSEOBJ, FAIL, "VOL connector did not initialize")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLinitialize() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLterminate
+ *
+ * Purpose: Calls the connector-specific callback to terminate the connector.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLterminate(hid_t connector_id)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE1("e", "i", connector_id);
+
+ /* Check args */
+ 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")
+
+ /* Invoke class' callback, if there is one */
+ if(cls->terminate && cls->terminate() < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCLOSEOBJ, FAIL, "VOL connector did not terminate cleanly")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLterminate() */
+
+
+/*---------------------------------------------------------------------------
+ * Function: H5VLget_cap_flags
+ *
+ * Purpose: Retrieves the capability flag for a connector
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *---------------------------------------------------------------------------
+ */
+herr_t
+H5VLget_cap_flags(hid_t connector_id, unsigned *cap_flags)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE2("e", "i*Iu", connector_id, cap_flags);
+
+ /* Check args */
+ 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")
+
+ /* Retrieve capability flags */
+ if(cap_flags)
+ *cap_flags = cls->cap_flags;
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* H5VLget_cap_flags */
+
+
+/*---------------------------------------------------------------------------
+ * Function: H5VLget_value
+ *
+ * Purpose: Retrieves the 'value' for a connector
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *---------------------------------------------------------------------------
+ */
+herr_t
+H5VLget_value(hid_t connector_id, H5VL_class_value_t *value)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE2("e", "i*VC", connector_id, value);
+
+ /* Check args */
+ 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")
+
+ /* Retrieve connector value */
+ if(value)
+ *value = cls->value;
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* H5VLget_value */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_copy_connector_info
+ *
+ * Purpose: Copy the VOL info for a connector
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_copy_connector_info(const H5VL_class_t *connector, void **dst_info,
+ const void *src_info)
+{
+ void *new_connector_info = NULL; /* Copy of connector info */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(connector);
+
+ /* Check for actual source info */
+ if(src_info) {
+ /* Allow the connector to copy or do it ourselves */
+ if(connector->info_cls.copy) {
+ if(NULL == (new_connector_info = (connector->info_cls.copy)(src_info)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCOPY, FAIL, "connector info copy callback failed")
+ } /* end if */
+ else if(connector->info_cls.size > 0) {
+ if(NULL == (new_connector_info = H5MM_malloc(connector->info_cls.size)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTALLOC, FAIL, "connector info allocation failed")
+ H5MM_memcpy(new_connector_info, src_info, connector->info_cls.size);
+ } /* end else-if */
+ else
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "no way to copy connector info")
+ } /* end if */
+
+ /* Set the connector info for the copy */
+ *dst_info = new_connector_info;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_copy_connector_info() */
+
+
+/*---------------------------------------------------------------------------
+ * Function: H5VLcopy_connector_info
+ *
+ * Purpose: Copies a VOL connector's info object
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *---------------------------------------------------------------------------
+ */
+herr_t
+H5VLcopy_connector_info(hid_t connector_id, void **dst_vol_info, void *src_vol_info)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE3("e", "i**x*x", connector_id, dst_vol_info, src_vol_info);
+
+ /* Check args and get class pointer */
+ 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")
+
+ /* Copy the VOL connector's info object */
+ if(H5VL_copy_connector_info(cls, dst_vol_info, src_vol_info) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCOPY, FAIL, "unable to copy VOL connector info object")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* H5VLcopy_connector_info() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_cmp_connector_info
+ *
+ * Purpose: Compare VOL info for a connector. Sets *cmp_value to
+ * positive if INFO1 is greater than INFO2, negative if
+ * INFO2 is greater than INFO1 and zero if INFO1 and
+ * INFO2 are equal.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_cmp_connector_info(const H5VL_class_t *connector, int *cmp_value,
+ const void *info1, const void *info2)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(connector);
+ HDassert(cmp_value);
+
+ /* Take care of cases where one or both pointers is NULL */
+ if(info1 == NULL && info2 != NULL) {
+ *cmp_value = -1;
+ HGOTO_DONE(SUCCEED);
+ } /* end if */
+ if(info1 != NULL && info2 == NULL) {
+ *cmp_value = 1;
+ HGOTO_DONE(SUCCEED);
+ } /* end if */
+ if(info1 == NULL && info2 == NULL) {
+ *cmp_value = 0;
+ HGOTO_DONE(SUCCEED);
+ } /* end if */
+
+ /* Use the class's info comparison routine to compare the info objects,
+ * if there is a a callback, otherwise just compare the info objects as
+ * memory buffers
+ */
+ if(connector->info_cls.cmp) {
+ if((connector->info_cls.cmp)(cmp_value, info1, info2) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCOMPARE, FAIL, "can't compare connector info")
+ } /* end if */
+ else {
+ HDassert(connector->info_cls.size > 0);
+ *cmp_value = HDmemcmp(info1, info2, connector->info_cls.size);
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_cmp_connector_info() */
+
+
+/*---------------------------------------------------------------------------
+ * Function: H5VLcmp_connector_info
+ *
+ * Purpose: Compares two connector info objects
+ *
+ * Note: Both info objects must be from the same VOL connector class
+ *
+ * Return: Success: Non-negative, with *cmp set to positive if
+ * info1 is greater than info2, negative if info2
+ * is greater than info1 and zero if info1 and info2
+ * are equal.
+ * Failure: Negative
+ *
+ *---------------------------------------------------------------------------
+ */
+herr_t
+H5VLcmp_connector_info(int *cmp, hid_t connector_id, const void *info1, const void *info2)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE4("e", "*Isi*x*x", cmp, connector_id, info1, info2);
+
+ /* Check args and get class pointer */
+ 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")
+
+ /* Compare the two VOL connector info objects */
+ if(cmp)
+ H5VL_cmp_connector_info(cls, cmp, info1, info2);
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* H5VLcmp_connector_info() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_free_connector_info
+ *
+ * Purpose: Free VOL info for a connector
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_free_connector_info(hid_t connector_id, void *info)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check */
+ HDassert(connector_id > 0);
+
+ /* Check args and get class pointer */
+ if(NULL == (cls = (H5VL_class_t *)H5I_object_verify(connector_id, H5I_VOL)))
+ HGOTO_ERROR(H5E_VOL, H5E_BADTYPE, FAIL, "not a VOL connector ID")
+
+ /* Only free info object, if it's non-NULL */
+ if(info) {
+ /* Allow the connector to free info or do it ourselves */
+ if(cls->info_cls.free) {
+ if((cls->info_cls.free)(info) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "connector info free request failed")
+ } /* end if */
+ else
+ H5MM_xfree(info);
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_free_connector_info() */
+
+
+/*---------------------------------------------------------------------------
+ * Function: H5VLfree_connector_info
+ *
+ * Purpose: Free VOL connector info object
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *---------------------------------------------------------------------------
+ */
+herr_t
+H5VLfree_connector_info(hid_t connector_id, void *info)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE2("e", "i*x", connector_id, info);
+
+ /* Free the VOL connector info object */
+ if(H5VL_free_connector_info(connector_id, info) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "unable to release VOL connector info object")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* H5VLfree_connector_info() */
+
+
+/*---------------------------------------------------------------------------
+ * Function: H5VLconnector_info_to_str
+ *
+ * Purpose: Serialize a connector's info into a string
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *---------------------------------------------------------------------------
+ */
+herr_t
+H5VLconnector_info_to_str(const void *info, hid_t connector_id, char **str)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE3("e", "*xi**s", info, connector_id, str);
+
+ /* Only serialize info object, if it's non-NULL */
+ if(info) {
+ H5VL_class_t *cls; /* VOL connector's class struct */
+
+ /* Check args and get class pointer */
+ 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")
+
+ /* Allow the connector to serialize info */
+ if(cls->info_cls.to_str) {
+ if((cls->info_cls.to_str)(info, str) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSERIALIZE, FAIL, "can't serialize connector info")
+ } /* end if */
+ else
+ *str = NULL;
+ } /* end if */
+ else
+ *str = NULL;
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* H5VLconnector_info_to_str() */
+
+
+/*---------------------------------------------------------------------------
+ * Function: H5VLconnector_str_to_info
+ *
+ * Purpose: Deserialize a string into a connector's info
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *---------------------------------------------------------------------------
+ */
+herr_t
+H5VLconnector_str_to_info(const char *str, hid_t connector_id, void **info)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE3("e", "*si**x", str, connector_id, info);
+
+ /* Call internal routine */
+ if(H5VL__connector_str_to_info(str, connector_id, info) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTDECODE, FAIL, "can't deserialize connector info")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* H5VLconnector_str_to_info() */
+
+
+/*---------------------------------------------------------------------------
+ * Function: H5VLget_object
+ *
+ * Purpose: Retrieves an underlying object.
+ *
+ * Return: Success: Non-NULL
+ * Failure: NULL
+ *
+ *---------------------------------------------------------------------------
+ */
+void *
+H5VLget_object(void *obj, hid_t connector_id)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE2("*x", "*xi", obj, connector_id);
+
+ /* Check args */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid object")
+ if(NULL == (cls = (H5VL_class_t *)H5I_object_verify(connector_id, H5I_VOL)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a VOL connector ID")
+
+ /* Check for 'get_object' callback in connector */
+ if(cls->wrap_cls.get_object)
+ ret_value = (cls->wrap_cls.get_object)(obj);
+ else
+ ret_value = obj;
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* H5VLget_object */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_get_wrap_ctx
+ *
+ * Purpose: Retrieve the VOL object wrapping context for a connector
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_get_wrap_ctx(const H5VL_class_t *connector, void *obj, void **wrap_ctx)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(connector);
+ HDassert(obj);
+ HDassert(wrap_ctx);
+
+ /* Allow the connector to copy or do it ourselves */
+ if(connector->wrap_cls.get_wrap_ctx) {
+ /* Sanity check */
+ HDassert(connector->wrap_cls.free_wrap_ctx);
+
+ /* Invoke connector's callback */
+ if((connector->wrap_cls.get_wrap_ctx)(obj, wrap_ctx) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "connector wrap context callback failed")
+ } /* end if */
+ else
+ *wrap_ctx = NULL;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_get_wrap_ctx() */
+
+
+/*---------------------------------------------------------------------------
+ * Function: H5VLget_wrap_ctx
+ *
+ * Purpose: Get a VOL connector's object wrapping context
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *---------------------------------------------------------------------------
+ */
+herr_t
+H5VLget_wrap_ctx(void *obj, hid_t connector_id, void **wrap_ctx)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE3("e", "*xi**x", obj, connector_id, wrap_ctx);
+
+ /* Check args and get class pointer */
+ 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")
+
+ /* Get the VOL connector's object wrapper */
+ if(H5VL_get_wrap_ctx(cls, obj, wrap_ctx) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "unable to retrieve VOL connector object wrap context")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* H5VLget_wrap_ctx() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_wrap_object
+ *
+ * Purpose: Wrap an object with connector
+ *
+ * Return: Success: Non-NULL
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VL_wrap_object(const H5VL_class_t *connector, void *wrap_ctx, void *obj,
+ H5I_type_t obj_type)
+{
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_NOAPI(NULL)
+
+ /* Sanity checks */
+ HDassert(connector);
+ HDassert(obj);
+
+ /* Only wrap object if there's a wrap context */
+ if(wrap_ctx) {
+ /* Ask the connector to wrap the object */
+ if(NULL == (ret_value = (connector->wrap_cls.wrap_object)(obj, obj_type, wrap_ctx)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, NULL, "can't wrap object")
+ } /* end if */
+ else
+ ret_value = obj;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_wrap_object() */
+
+
+/*---------------------------------------------------------------------------
+ * Function: H5VLwrap_object
+ *
+ * Purpose: Asks a connector to wrap an underlying object.
+ *
+ * Return: Success: Non-NULL
+ * Failure: NULL
+ *
+ *---------------------------------------------------------------------------
+ */
+void *
+H5VLwrap_object(void *obj, H5I_type_t obj_type, hid_t connector_id, void *wrap_ctx)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE4("*x", "*xIti*x", obj, obj_type, connector_id, wrap_ctx);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid object")
+ if(NULL == (cls = (H5VL_class_t *)H5I_object_verify(connector_id, H5I_VOL)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a VOL connector ID")
+
+ /* Wrap the object */
+ if(NULL == (ret_value = H5VL_wrap_object(cls, wrap_ctx, obj, obj_type)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, NULL, "unable to wrap object")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* H5VLwrap_object */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_unwrap_object
+ *
+ * Purpose: Unwrap an object from connector
+ *
+ * Return: Success: Non-NULL
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VL_unwrap_object(const H5VL_class_t *connector, void *obj)
+{
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_NOAPI(NULL)
+
+ /* Sanity checks */
+ HDassert(connector);
+ HDassert(obj);
+
+ /* Only unwrap object if there's an unwrap callback */
+ if(connector->wrap_cls.wrap_object) {
+ /* Ask the connector to unwrap the object */
+ if(NULL == (ret_value = (connector->wrap_cls.unwrap_object)(obj)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, NULL, "can't unwrap object")
+ } /* end if */
+ else
+ ret_value = obj;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_unwrap_object() */
+
+
+/*---------------------------------------------------------------------------
+ * Function: H5VLunwrap_object
+ *
+ * Purpose: Unwrap an object from connector
+ *
+ * Return: Success: Non-NULL
+ * Failure: NULL
+ *
+ *---------------------------------------------------------------------------
+ */
+void *
+H5VLunwrap_object(void *obj, hid_t connector_id)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE2("*x", "*xi", obj, connector_id);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid object")
+ if(NULL == (cls = (H5VL_class_t *)H5I_object_verify(connector_id, H5I_VOL)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a VOL connector ID")
+
+ /* Unwrap the object */
+ if(NULL == (ret_value = H5VL_unwrap_object(cls, obj)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, NULL, "unable to unwrap object")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* H5VLunwrap_object */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_free_wrap_ctx
+ *
+ * Purpose: Free object wrapping context for a connector
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_free_wrap_ctx(const H5VL_class_t *connector, void *wrap_ctx)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(connector);
+
+ /* Only free wrap context, if it's non-NULL */
+ if(wrap_ctx) {
+ /* Free the connector's object wrapping context */
+ if((connector->wrap_cls.free_wrap_ctx)(wrap_ctx) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "connector wrap context free request failed")
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_free_wrap_ctx() */
+
+
+/*---------------------------------------------------------------------------
+ * Function: H5VLfree_wrap_ctx
+ *
+ * Purpose: Release a VOL connector's object wrapping context
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *---------------------------------------------------------------------------
+ */
+herr_t
+H5VLfree_wrap_ctx(void *wrap_ctx, hid_t connector_id)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE2("e", "*xi", wrap_ctx, connector_id);
+
+ /* Check args and get class pointer */
+ 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")
+
+ /* Release the VOL connector's object wrapper */
+ if(H5VL_free_wrap_ctx(cls, wrap_ctx) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "unable to release VOL connector object wrap context")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* H5VLfree_wrap_ctx() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__attr_create
+ *
+ * Purpose: Creates an attribute through the VOL
+ *
+ * Return: Success: Pointer to the new attribute
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5VL__attr_create(void *obj, const H5VL_loc_params_t *loc_params, const H5VL_class_t *cls,
+ const char *name, hid_t type_id, hid_t space_id, hid_t acpl_id,
+ hid_t aapl_id, hid_t dxpl_id, void **req)
+{
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->attr_cls.create)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, NULL, "VOL connector has no 'attr create' method")
+
+ /* Call the corresponding VOL callback */
+ if(NULL == (ret_value = (cls->attr_cls.create)(obj, loc_params, name, type_id, space_id, acpl_id, aapl_id, dxpl_id, req)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCREATE, NULL, "attribute create failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__attr_create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_attr_create
+ *
+ * Purpose: Creates an attribute through the VOL
+ *
+ * Return: Success: Pointer to the new attribute
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VL_attr_create(const H5VL_object_t *vol_obj, const H5VL_loc_params_t *loc_params,
+ const char *name, hid_t type_id, hid_t space_id, hid_t acpl_id,
+ hid_t aapl_id, hid_t dxpl_id, void **req)
+{
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_NOAPI(NULL)
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, NULL, "can't set VOL wrapper info")
+ vol_wrapper_set = TRUE;
+
+ /* Call the corresponding internal VOL routine */
+ if(NULL == (ret_value = H5VL__attr_create(vol_obj->data, loc_params, vol_obj->connector->cls, name, type_id, space_id, acpl_id, aapl_id, dxpl_id, req)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCREATE, NULL, "attribute create failed")
+
+done:
+ /* Reset object wrapping info in API context */
+ if(vol_wrapper_set && H5VL_reset_vol_wrapper() < 0)
+ HDONE_ERROR(H5E_VOL, H5E_CANTRESET, NULL, "can't reset VOL wrapper info")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_attr_create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLattr_create
+ *
+ * Purpose: Creates an attribute
+ *
+ * Return: Success: Pointer to the new attribute
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VLattr_create(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id,
+ const char *name, hid_t type_id, hid_t space_id, hid_t acpl_id,
+ hid_t aapl_id, hid_t dxpl_id, void **req)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE10("*x", "*x*xi*siiiii**x", obj, loc_params, connector_id, name,
+ type_id, space_id, acpl_id, aapl_id, dxpl_id, req);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid object")
+ if(NULL == (cls = (H5VL_class_t *)H5I_object_verify(connector_id, H5I_VOL)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a VOL connector ID")
+
+ /* Call the corresponding internal VOL routine */
+ if(NULL == (ret_value = H5VL__attr_create(obj, loc_params, cls, name, type_id, space_id, acpl_id, aapl_id, dxpl_id, req)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCREATE, NULL, "unable to create attribute")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLattr_create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__attr_open
+ *
+ * Purpose: Opens an attribute through the VOL
+ *
+ * Return: Success: Pointer to the attribute
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5VL__attr_open(void *obj, const H5VL_loc_params_t *loc_params, const H5VL_class_t *cls, const char *name,
+ hid_t aapl_id, hid_t dxpl_id, void **req)
+{
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->attr_cls.open)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, NULL, "VOL connector has no 'attr open' method")
+
+ /* Call the corresponding VOL open callback */
+ if(NULL == (ret_value = (cls->attr_cls.open)(obj, loc_params, name, aapl_id, dxpl_id, req)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPENOBJ, NULL, "attribute open failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__attr_open() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_attr_open
+ *
+ * Purpose: Opens an attribute through the VOL
+ *
+ * Return: Success: Pointer to the attribute
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VL_attr_open(const H5VL_object_t *vol_obj, const H5VL_loc_params_t *loc_params,
+ const char *name, hid_t aapl_id, hid_t dxpl_id, void **req)
+{
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_NOAPI(NULL)
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, NULL, "can't set VOL wrapper info")
+ vol_wrapper_set = TRUE;
+
+ /* Call the corresponding internal VOL routine */
+ if(NULL == (ret_value = H5VL__attr_open(vol_obj->data, loc_params, vol_obj->connector->cls, name, aapl_id, dxpl_id, req)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPENOBJ, NULL, "attribute open failed")
+
+done:
+ /* Reset object wrapping info in API context */
+ if(vol_wrapper_set && H5VL_reset_vol_wrapper() < 0)
+ HDONE_ERROR(H5E_VOL, H5E_CANTRESET, NULL, "can't reset VOL wrapper info")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_attr_open() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLattr_open
+ *
+ * Purpose: Opens an attribute
+ *
+ * Return: Success: Pointer to the attribute
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VLattr_open(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id,
+ const char *name, hid_t aapl_id, hid_t dxpl_id, void **req)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE7("*x", "*x*xi*sii**x", obj, loc_params, connector_id, name, aapl_id,
+ dxpl_id, req);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid object")
+ if(NULL == (cls = (H5VL_class_t *)H5I_object_verify(connector_id, H5I_VOL)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a VOL connector ID")
+
+ /* Call the corresponding internal VOL routine */
+ if(NULL == (ret_value = H5VL__attr_open(obj, loc_params, cls, name, aapl_id, dxpl_id, req)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPENOBJ, NULL, "unable to open attribute")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLattr_open() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__attr_read
+ *
+ * Purpose: Reads data from attr through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__attr_read(void *obj, const H5VL_class_t *cls, hid_t mem_type_id, void *buf,
+ hid_t dxpl_id, void **req)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->attr_cls.read)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'attr read' method")
+
+ /* Call the corresponding VOL callback */
+ if((cls->attr_cls.read)(obj, mem_type_id, buf, dxpl_id, req) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_READERROR, FAIL, "attribute read failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__attr_read() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_attr_read
+ *
+ * Purpose: Reads data from attr through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_attr_read(const H5VL_object_t *vol_obj, hid_t mem_type_id, void *buf,
+ hid_t dxpl_id, void **req)
+{
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 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__attr_read(vol_obj->data, vol_obj->connector->cls, mem_type_id, buf, dxpl_id, req) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_READERROR, FAIL, "attribute 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_attr_read() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLattr_read
+ *
+ * Purpose: Reads data from an attribute
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLattr_read(void *obj, hid_t connector_id, hid_t mem_type_id, void *buf, hid_t dxpl_id, void **req)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE6("e", "*xii*xi**x", obj, connector_id, mem_type_id, buf, dxpl_id, req);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object")
+ 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__attr_read(obj, cls, mem_type_id, buf, dxpl_id, req) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_READERROR, FAIL, "unable to read attribute")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLattr_read() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__attr_write
+ *
+ * Purpose: Writes data to attr through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__attr_write(void *obj, const H5VL_class_t *cls, hid_t mem_type_id, const void *buf,
+ hid_t dxpl_id, void **req)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->attr_cls.write)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'attr write' method")
+
+ /* Call the corresponding VOL callback */
+ if((cls->attr_cls.write)(obj, mem_type_id, buf, dxpl_id, req) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_WRITEERROR, FAIL, "write failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__attr_write() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_attr_write
+ *
+ * Purpose: Writes data to attr through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_attr_write(const H5VL_object_t *vol_obj, hid_t mem_type_id, const void *buf,
+ hid_t dxpl_id, void **req)
+{
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 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__attr_write(vol_obj->data, vol_obj->connector->cls, mem_type_id, buf, dxpl_id, req) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_WRITEERROR, FAIL, "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_attr_write() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLattr_write
+ *
+ * Purpose: Writes data to an attribute
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLattr_write(void *obj, hid_t connector_id, hid_t mem_type_id, const void *buf,
+ hid_t dxpl_id, void **req)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE6("e", "*xii*xi**x", obj, connector_id, mem_type_id, buf, dxpl_id, req);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object")
+ 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__attr_write(obj, cls, mem_type_id, buf, dxpl_id, req) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_WRITEERROR, FAIL, "unable to write attribute")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLattr_write() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__attr_get
+ *
+ * Purpose: Get specific information about the attribute through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__attr_get(void *obj, const H5VL_class_t *cls, H5VL_attr_get_t get_type,
+ hid_t dxpl_id, void **req, va_list arguments)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->attr_cls.get)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'attr get' method")
+
+ /* Call the corresponding VOL callback */
+ if((cls->attr_cls.get)(obj, get_type, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "attribute get failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__attr_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_attr_get
+ *
+ * Purpose: Get specific information about the attribute through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_attr_get(const H5VL_object_t *vol_obj, H5VL_attr_get_t get_type,
+ hid_t dxpl_id, void **req, ...)
+{
+ va_list arguments; /* Argument list passed from the API call */
+ hbool_t arg_started = FALSE; /* Whether the va_list has been started */
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL wrapper info")
+ vol_wrapper_set = TRUE;
+
+ /* Call the corresponding internal VOL routine */
+ HDva_start(arguments, req);
+ arg_started = TRUE;
+ if(H5VL__attr_get(vol_obj->data, vol_obj->connector->cls, get_type, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "attribute get failed")
+
+done:
+ /* End access to the va_list, if we started it */
+ if(arg_started)
+ HDva_end(arguments);
+
+ /* 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_attr_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLattr_get
+ *
+ * Purpose: Gets information about the attribute
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLattr_get(void *obj, hid_t connector_id, H5VL_attr_get_t get_type, hid_t dxpl_id,
+ void **req, va_list arguments)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE6("e", "*xiVai**xx", obj, connector_id, get_type, dxpl_id, req,
+ arguments);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object")
+ 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__attr_get(obj, cls, get_type, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "unable to get attribute information")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLattr_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__attr_specific
+ *
+ * Purpose: Specific operation on attributes through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__attr_specific(void *obj, const H5VL_loc_params_t *loc_params, const H5VL_class_t *cls,
+ H5VL_attr_specific_t specific_type, hid_t dxpl_id, void **req,
+ va_list arguments)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->attr_cls.specific)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'attr specific' method")
+
+ /* Call the corresponding VOL callback */
+ if((ret_value = (cls->attr_cls.specific)(obj, loc_params, specific_type, dxpl_id, req, arguments)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute attribute specific callback")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__attr_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_attr_specific
+ *
+ * Purpose: Specific operation on attributes through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_attr_specific(const H5VL_object_t *vol_obj, const H5VL_loc_params_t *loc_params,
+ H5VL_attr_specific_t specific_type, hid_t dxpl_id, void **req, ...)
+{
+ va_list arguments; /* Argument list passed from the API call */
+ hbool_t arg_started = FALSE; /* Whether the va_list has been started */
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL wrapper info")
+ vol_wrapper_set = TRUE;
+
+ /* Call the corresponding internal VOL routine */
+ HDva_start(arguments, req);
+ arg_started = TRUE;
+ if((ret_value = H5VL__attr_specific(vol_obj->data, loc_params, vol_obj->connector->cls, specific_type, dxpl_id, req, arguments)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute attribute specific callback")
+
+done:
+ /* End access to the va_list, if we started it */
+ if(arg_started)
+ HDva_end(arguments);
+
+ /* 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_attr_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLattr_specific
+ *
+ * Purpose: Performs a connector-specific operation on an attribute
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLattr_specific(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id,
+ H5VL_attr_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE7("e", "*x*xiVbi**xx", obj, loc_params, connector_id, specific_type,
+ dxpl_id, req, arguments);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object")
+ 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((ret_value = H5VL__attr_specific(obj, loc_params, cls, specific_type, dxpl_id, req, arguments)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute attribute specific callback")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLattr_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__attr_optional
+ *
+ * Purpose: Optional operation specific to connectors.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__attr_optional(void *obj, const H5VL_class_t *cls, hid_t dxpl_id,
+ void **req, va_list arguments)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->attr_cls.optional)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'attr optional' method")
+
+ /* Call the corresponding VOL callback */
+ if((ret_value = (cls->attr_cls.optional)(obj, dxpl_id, req, arguments)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute attribute optional callback")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__attr_optional() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_attr_optional
+ *
+ * Purpose: Optional operation specific to connectors.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_attr_optional(const H5VL_object_t *vol_obj, hid_t dxpl_id, void **req, ...)
+{
+ va_list arguments; /* Argument list passed from the API call */
+ hbool_t arg_started = FALSE; /* Whether the va_list has been started */
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL wrapper info")
+ vol_wrapper_set = TRUE;
+
+ /* Call the corresponding internal VOL routine */
+ HDva_start(arguments, req);
+ arg_started = TRUE;
+ if((ret_value = H5VL__attr_optional(vol_obj->data, vol_obj->connector->cls, dxpl_id, req, arguments)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute attribute optional callback")
+
+done:
+ /* End access to the va_list, if we started it */
+ if(arg_started)
+ HDva_end(arguments);
+
+ /* 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_attr_optional() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLattr_optional
+ *
+ * Purpose: Performs an optional connector-specific operation on an attribute
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLattr_optional(void *obj, hid_t connector_id, hid_t dxpl_id, void **req, va_list arguments)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE5("e", "*xii**xx", obj, connector_id, dxpl_id, req, arguments);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object")
+ 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((ret_value = H5VL__attr_optional(obj, cls, dxpl_id, req, arguments)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute attribute optional callback")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLattr_optional() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__attr_close
+ *
+ * Purpose: Closes an attribute through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__attr_close(void *obj, const H5VL_class_t *cls, hid_t dxpl_id, void **req)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->attr_cls.close)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'attr close' method")
+
+ /* Call the corresponding VOL callback */
+ if((cls->attr_cls.close)(obj, dxpl_id, req) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCLOSEOBJ, FAIL, "attribute close failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__attr_close() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_attr_close
+ *
+ * Purpose: Closes an attribute through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_attr_close(const H5VL_object_t *vol_obj, hid_t dxpl_id, void **req)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check */
+ HDassert(vol_obj);
+
+ /* Call the corresponding internal VOL routine */
+ if(H5VL__attr_close(vol_obj->data, vol_obj->connector->cls, dxpl_id, req) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCLOSEOBJ, FAIL, "attribute close failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_attr_close() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLattr_close
+ *
+ * Purpose: Closes an attribute
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLattr_close(void *obj, hid_t connector_id, hid_t dxpl_id, void **req)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE4("e", "*xii**x", obj, connector_id, dxpl_id, req);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object")
+ 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__attr_close(obj, cls, dxpl_id, req) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCLOSEOBJ, FAIL, "unable to close attribute")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLattr_close() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__dataset_create
+ *
+ * Purpose: Creates a dataset through the VOL
+ *
+ * Return: Success: Pointer to new dataset
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5VL__dataset_create(void *obj, const H5VL_loc_params_t *loc_params, const H5VL_class_t *cls,
+ const char *name, hid_t lcpl_id, hid_t type_id, hid_t space_id,
+ hid_t dcpl_id, hid_t dapl_id, hid_t dxpl_id, void **req)
+{
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->dataset_cls.create)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, NULL, "VOL connector has no 'dataset create' method")
+
+ /* Call the corresponding VOL callback */
+ if(NULL == (ret_value = (cls->dataset_cls.create)(obj, loc_params, name, lcpl_id, type_id, space_id, dcpl_id, dapl_id, dxpl_id, req)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCREATE, NULL, "dataset create failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__dataset_create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_dataset_create
+ *
+ * Purpose: Creates a dataset through the VOL
+ *
+ * Return: Success: Pointer to new dataset
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VL_dataset_create(const H5VL_object_t *vol_obj, const H5VL_loc_params_t *loc_params,
+ const char *name, hid_t lcpl_id, hid_t type_id, hid_t space_id,
+ hid_t dcpl_id, hid_t dapl_id, hid_t dxpl_id, void **req)
+{
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_NOAPI(NULL)
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, NULL, "can't set VOL wrapper info")
+ vol_wrapper_set = TRUE;
+
+ /* Call the corresponding internal VOL routine */
+ if(NULL == (ret_value = H5VL__dataset_create(vol_obj->data, loc_params, vol_obj->connector->cls, name, lcpl_id, type_id, space_id, dcpl_id, dapl_id, dxpl_id, req)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCREATE, NULL, "dataset create failed")
+
+done:
+ /* Reset object wrapping info in API context */
+ if(vol_wrapper_set && H5VL_reset_vol_wrapper() < 0)
+ HDONE_ERROR(H5E_VOL, H5E_CANTRESET, NULL, "can't reset VOL wrapper info")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_dataset_create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLdataset_create
+ *
+ * Purpose: Creates a dataset
+ *
+ * Return: Success: Pointer to the new dataset
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VLdataset_create(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id,
+ const char *name, hid_t lcpl_id, hid_t type_id, hid_t space_id,
+ hid_t dcpl_id, hid_t dapl_id, hid_t dxpl_id, void **req)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE11("*x", "*x*xi*siiiiii**x", obj, loc_params, connector_id, name,
+ lcpl_id, type_id, space_id, dcpl_id, dapl_id, dxpl_id, req);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid object")
+ if(NULL == (cls = (H5VL_class_t *)H5I_object_verify(connector_id, H5I_VOL)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a VOL connector ID")
+
+ /* Call the corresponding internal VOL routine */
+ if(NULL == (ret_value = H5VL__dataset_create(obj, loc_params, cls, name, lcpl_id, type_id, space_id, dcpl_id, dapl_id, dxpl_id, req)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCREATE, NULL, "unable to create dataset")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLdataset_create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__dataset_open
+ *
+ * Purpose: Opens a dataset through the VOL
+ *
+ * Return: Success: Pointer to dataset
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+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)
+{
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->dataset_cls.open)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, NULL, "VOL connector has no 'dataset open' method")
+
+ /* Call the corresponding VOL callback */
+ if(NULL == (ret_value = (cls->dataset_cls.open)(obj, loc_params, name, dapl_id, dxpl_id, req)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPENOBJ, NULL, "dataset open failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__dataset_open() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_dataset_open
+ *
+ * Purpose: Opens a dataset through the VOL
+ *
+ * Return: Success: Pointer to dataset
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+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)
+{
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_NOAPI(NULL)
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, NULL, "can't set VOL wrapper info")
+ vol_wrapper_set = TRUE;
+
+ /* Call the corresponding internal VOL routine */
+ if(NULL == (ret_value = H5VL__dataset_open(vol_obj->data, loc_params, vol_obj->connector->cls, name, dapl_id, dxpl_id, req)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPENOBJ, NULL, "dataset open failed")
+
+done:
+ /* Reset object wrapping info in API context */
+ if(vol_wrapper_set && H5VL_reset_vol_wrapper() < 0)
+ HDONE_ERROR(H5E_VOL, H5E_CANTRESET, NULL, "can't reset VOL wrapper info")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_dataset_open() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLdataset_open
+ *
+ * Purpose: Opens a dataset
+ *
+ * Return: Success: Pointer to the new dataset
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+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)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE7("*x", "*x*xi*sii**x", obj, loc_params, connector_id, name, dapl_id,
+ dxpl_id, req);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid object")
+ if(NULL == (cls = (H5VL_class_t *)H5I_object_verify(connector_id, H5I_VOL)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a VOL connector ID")
+
+ /* Call the corresponding internal VOL routine */
+ if(NULL == (ret_value = H5VL__dataset_open(obj, loc_params, cls, name, dapl_id, dxpl_id, req)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPENOBJ, NULL, "unable to open dataset")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLdataset_open() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__dataset_read
+ *
+ * Purpose: Reads data from dataset through the VOL
+*
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+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 plist_id, void *buf,
+ void **req)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->dataset_cls.read)
+ 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, plist_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
+ *
+ * Purpose: Reads data from dataset through the VOL
+*
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+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 plist_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 */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 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(vol_obj->data, vol_obj->connector->cls, mem_type_id, mem_space_id, file_space_id, plist_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() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLdataset_read
+ *
+ * Purpose: Reads data from a dataset
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+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 plist_id, void *buf, void **req)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE8("e", "*xiiiii*x**x", obj, connector_id, mem_type_id, mem_space_id,
+ file_space_id, plist_id, buf, req);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object")
+ 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, plist_id, buf, req) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "unable to read dataset")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLdataset_read() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__dataset_write
+ *
+ * Purpose: Writes data from dataset through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+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 plist_id, const void *buf,
+ void **req)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->dataset_cls.write)
+ 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, plist_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
+ *
+ * Purpose: Writes data from dataset through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+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 plist_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 */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 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(vol_obj->data, vol_obj->connector->cls, mem_type_id, mem_space_id, file_space_id, plist_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() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLdataset_write
+ *
+ * Purpose: Writes data to a dataset
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+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 plist_id, const void *buf, void **req)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE8("e", "*xiiiii*x**x", obj, connector_id, mem_type_id, mem_space_id,
+ file_space_id, plist_id, buf, req);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object")
+ 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, plist_id, buf, req) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "unable to write dataset")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLdataset_write() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__dataset_get
+ *
+ * Purpose: Get specific information about the dataset through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__dataset_get(void *obj, const H5VL_class_t *cls, H5VL_dataset_get_t get_type,
+ hid_t dxpl_id, void **req, va_list arguments)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->dataset_cls.get)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'dataset get' method")
+
+ /* Call the corresponding VOL callback */
+ if((cls->dataset_cls.get)(obj, get_type, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "dataset get failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__dataset_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_dataset_get
+ *
+ * Purpose: Get specific information about the dataset through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_dataset_get(const H5VL_object_t *vol_obj, H5VL_dataset_get_t get_type,
+ hid_t dxpl_id, void **req, ...)
+{
+ va_list arguments; /* Argument list passed from the API call */
+ hbool_t arg_started = FALSE; /* Whether the va_list has been started */
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL wrapper info")
+ vol_wrapper_set = TRUE;
+
+ /* Call the corresponding internal VOL routine */
+ HDva_start(arguments, req);
+ arg_started = TRUE;
+ if(H5VL__dataset_get(vol_obj->data, vol_obj->connector->cls, get_type, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "dataset get failed")
+
+done:
+ /* End access to the va_list, if we started it */
+ if(arg_started)
+ HDva_end(arguments);
+
+ /* 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_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLdataset_get
+ *
+ * Purpose: Gets information about a dataset
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLdataset_get(void *obj, hid_t connector_id, H5VL_dataset_get_t get_type,
+ hid_t dxpl_id, void **req, va_list arguments)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE6("e", "*xiVci**xx", obj, connector_id, get_type, dxpl_id, req,
+ arguments);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object")
+ 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_get(obj, cls, get_type, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "unable to execute dataset get callback")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLdataset_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__dataset_specific
+ *
+ * Purpose: Specific operation on datasets through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__dataset_specific(void *obj, const H5VL_class_t *cls, H5VL_dataset_specific_t specific_type,
+ hid_t dxpl_id, void **req, va_list arguments)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->dataset_cls.specific)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'dataset specific' method")
+
+ /* Call the corresponding VOL callback */
+ if((cls->dataset_cls.specific)(obj, specific_type, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute dataset specific callback")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__dataset_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_dataset_specific
+ *
+ * Purpose: Specific operation on datasets through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_dataset_specific(const H5VL_object_t *vol_obj, H5VL_dataset_specific_t specific_type,
+ hid_t dxpl_id, void **req, ...)
+{
+ va_list arguments; /* Argument list passed from the API call */
+ hbool_t arg_started = FALSE; /* Whether the va_list has been started */
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL wrapper info")
+ vol_wrapper_set = TRUE;
+
+ /* Call the corresponding internal VOL routine */
+ HDva_start(arguments, req);
+ arg_started = TRUE;
+ if(H5VL__dataset_specific(vol_obj->data, vol_obj->connector->cls, specific_type, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute dataset specific callback")
+
+done:
+ /* End access to the va_list, if we started it */
+ if(arg_started)
+ HDva_end(arguments);
+
+ /* 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_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLdataset_specific
+ *
+ * Purpose: Performs a connector-specific operation on a dataset
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLdataset_specific(void *obj, hid_t connector_id, H5VL_dataset_specific_t specific_type,
+ hid_t dxpl_id, void **req, va_list arguments)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE6("e", "*xiVdi**xx", obj, connector_id, specific_type, dxpl_id, req,
+ arguments);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object")
+ 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_specific(obj, cls, specific_type, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute dataset specific callback")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLdataset_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__dataset_optional
+ *
+ * Purpose: Optional operation specific to connectors.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__dataset_optional(void *obj, const H5VL_class_t *cls, hid_t dxpl_id,
+ void **req, va_list arguments)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->dataset_cls.optional)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'dataset optional' method")
+
+ /* Call the corresponding VOL callback */
+ if((cls->dataset_cls.optional)(obj, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute dataset optional callback")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__dataset_optional() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_dataset_optional
+ *
+ * Purpose: Optional operation specific to connectors.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_dataset_optional(const H5VL_object_t *vol_obj, hid_t dxpl_id,
+ void **req, ...)
+{
+ va_list arguments; /* Argument list passed from the API call */
+ hbool_t arg_started = FALSE; /* Whether the va_list has been started */
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Call the corresponding VOL callback */
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL wrapper info")
+ vol_wrapper_set = TRUE;
+
+ /* Call the corresponding internal VOL routine */
+ HDva_start(arguments, req);
+ arg_started = TRUE;
+ if(H5VL__dataset_optional(vol_obj->data, vol_obj->connector->cls, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute dataset optional callback")
+
+done:
+ /* End access to the va_list, if we started it */
+ if(arg_started)
+ HDva_end(arguments);
+
+ /* 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_optional() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLdataset_optional
+ *
+ * Purpose: Performs an optional connector-specific operation on a dataset
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLdataset_optional(void *obj, hid_t connector_id, hid_t dxpl_id, void **req,
+ va_list arguments)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE5("e", "*xii**xx", obj, connector_id, dxpl_id, req, arguments);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object")
+ 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_optional(obj, cls, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute dataset optional callback")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLdataset_optional() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__dataset_close
+ *
+ * Purpose: Closes a dataset through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__dataset_close(void *obj, const H5VL_class_t *cls, hid_t dxpl_id, void **req)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity check */
+ HDassert(obj);
+ HDassert(cls);
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->dataset_cls.close)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'dataset close' method")
+
+ /* Call the corresponding VOL callback */
+ if((cls->dataset_cls.close)(obj, dxpl_id, req) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCLOSEOBJ, FAIL, "dataset close failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__dataset_close() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_dataset_close
+ *
+ * Purpose: Closes a dataset through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_dataset_close(const H5VL_object_t *vol_obj, hid_t dxpl_id, void **req)
+{
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check */
+ HDassert(vol_obj);
+ HDassert(vol_obj->data);
+ HDassert(vol_obj->connector);
+ HDassert(vol_obj->connector->cls);
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 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_close(vol_obj->data, vol_obj->connector->cls, dxpl_id, req) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCLOSEOBJ, FAIL, "dataset close 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_close() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLdataset_close
+ *
+ * Purpose: Closes a dataset
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLdataset_close(void *obj, hid_t connector_id, hid_t dxpl_id, void **req)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE4("e", "*xii**x", obj, connector_id, dxpl_id, req);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object")
+ 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_close(obj, cls, dxpl_id, req) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCLOSEOBJ, FAIL, "unable to close dataset")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLdataset_close() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__file_create
+ *
+ * Purpose: Creates a file through the VOL
+ *
+ * Note: Does not have a 'static' version of the routine, since there's
+ * no objects in the container before this operation completes.
+ *
+ * Return: Success: Pointer to new file
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5VL__file_create(const H5VL_class_t *cls, const char *name,
+ unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t dxpl_id, void **req)
+{
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->file_cls.create)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, NULL, "VOL connector has no 'file create' method")
+
+ /* Call the corresponding VOL callback */
+ if(NULL == (ret_value = (cls->file_cls.create)(name, flags, fcpl_id, fapl_id, dxpl_id, req)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCREATE, NULL, "file create failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__file_create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_file_create
+ *
+ * Purpose: Creates a file through the VOL
+ *
+ * Note: Does not have a 'static' version of the routine, since there's
+ * no objects in the container before this operation completes.
+ *
+ * Return: Success: Pointer to new file
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VL_file_create(const H5VL_connector_prop_t *connector_prop, const char *name,
+ unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t dxpl_id, void **req)
+{
+ H5VL_class_t *cls; /* VOL Class structure for callback info */
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_NOAPI(NULL)
+
+ /* Get the connector's class */
+ if(NULL == (cls = (H5VL_class_t *)H5I_object_verify(connector_prop->connector_id, H5I_VOL)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a VOL connector ID")
+
+ /* Call the corresponding internal VOL routine */
+ if(NULL == (ret_value = H5VL__file_create(cls, name, flags, fcpl_id, fapl_id, dxpl_id, req)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCREATE, NULL, "file create failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_file_create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLfile_create
+ *
+ * Purpose: Creates a file
+ *
+ * Return: Success: Pointer to the new file
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VLfile_create(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id,
+ hid_t dxpl_id, void **req)
+{
+ H5P_genplist_t *plist; /* Property list pointer */
+ H5VL_connector_prop_t connector_prop; /* Property for VOL connector ID & info */
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE6("*x", "*sIuiii**x", name, flags, fcpl_id, fapl_id, dxpl_id, req);
+
+ /* Get the VOL info from the fapl */
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list")
+ if(H5P_peek(plist, H5F_ACS_VOL_CONN_NAME, &connector_prop) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get VOL connector info")
+
+ /* Get class pointer */
+ if(NULL == (cls = (H5VL_class_t *)H5I_object_verify(connector_prop.connector_id, H5I_VOL)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a VOL connector ID")
+
+ /* Call the corresponding internal VOL routine */
+ if(NULL == (ret_value = H5VL__file_create(cls, name, flags, fcpl_id, fapl_id, dxpl_id, req)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCREATE, NULL, "unable to create file")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLfile_create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__file_open
+ *
+ * Purpose: Opens a file through the VOL.
+ *
+ * Return: Success: Pointer to file.
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5VL__file_open(const H5VL_class_t *cls, const char *name, unsigned flags,
+ hid_t fapl_id, hid_t dxpl_id, void **req)
+{
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->file_cls.open)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, NULL, "VOL connector has no 'file open' method")
+
+ /* Call the corresponding VOL callback */
+ if(NULL == (ret_value = (cls->file_cls.open)(name, flags, fapl_id, dxpl_id, req)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPENOBJ, NULL, "open failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__file_open() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_file_open
+ *
+ * Purpose: Opens a file through the VOL.
+ *
+ * Note: Does not have a 'static' version of the routine, since there's
+ * no objects in the container before this operation completes.
+ *
+ * Return: Success: Pointer to file.
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VL_file_open(const H5VL_connector_prop_t *connector_prop, const char *name,
+ unsigned flags, hid_t fapl_id, hid_t dxpl_id, void **req)
+{
+ H5VL_class_t *cls; /* VOL Class structure for callback info */
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_NOAPI(NULL)
+
+ /* Get the connector's class */
+ if(NULL == (cls = (H5VL_class_t *)H5I_object_verify(connector_prop->connector_id, H5I_VOL)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a VOL connector ID")
+
+ /* Call the corresponding internal VOL routine */
+ if(NULL == (ret_value = H5VL__file_open(cls, name, flags, fapl_id, dxpl_id, req)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPENOBJ, NULL, "open failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_file_open() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLfile_open
+ *
+ * Purpose: Opens a file
+ *
+ * Return: Success: Pointer to the file
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VLfile_open(const char *name, unsigned flags, hid_t fapl_id, hid_t dxpl_id,
+ void **req)
+{
+ H5P_genplist_t *plist; /* Property list pointer */
+ H5VL_connector_prop_t connector_prop; /* Property for VOL connector ID & info */
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE5("*x", "*sIuii**x", name, flags, fapl_id, dxpl_id, req);
+
+ /* Get the VOL info from the fapl */
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list")
+ if(H5P_peek(plist, H5F_ACS_VOL_CONN_NAME, &connector_prop) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get VOL connector info")
+
+ /* Get class pointer */
+ if(NULL == (cls = (H5VL_class_t *)H5I_object_verify(connector_prop.connector_id, H5I_VOL)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a VOL connector ID")
+
+ /* Call the corresponding internal VOL routine */
+ if(NULL == (ret_value = H5VL__file_open(cls, name, flags, fapl_id, dxpl_id, req)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPENOBJ, NULL, "unable to open file")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLfile_open() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__file_get
+ *
+ * Purpose: Get specific information about the file through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__file_get(void *obj, const H5VL_class_t *cls, H5VL_file_get_t get_type,
+ hid_t dxpl_id, void **req, va_list arguments)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->file_cls.get)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'file get' method")
+
+ /* Call the corresponding VOL callback */
+ if((cls->file_cls.get)(obj, get_type, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "file get failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__file_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_file_get
+ *
+ * Purpose: Get specific information about the file through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_file_get(const H5VL_object_t *vol_obj, H5VL_file_get_t get_type,
+ hid_t dxpl_id, void **req, ...)
+{
+ va_list arguments; /* Argument list passed from the API call */
+ hbool_t arg_started = FALSE; /* Whether the va_list has been started */
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL wrapper info")
+ vol_wrapper_set = TRUE;
+
+ /* Call the corresponding internal VOL routine */
+ HDva_start(arguments, req);
+ arg_started = TRUE;
+ if(H5VL__file_get(vol_obj->data, vol_obj->connector->cls, get_type, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "file get failed")
+
+done:
+ /* End access to the va_list, if we started it */
+ if(arg_started)
+ HDva_end(arguments);
+
+ /* 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_file_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLfile_get
+ *
+ * Purpose: Gets information about the file
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLfile_get(void *obj, hid_t connector_id, H5VL_file_get_t get_type,
+ hid_t dxpl_id, void **req, va_list arguments)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE6("e", "*xiVgi**xx", obj, connector_id, get_type, dxpl_id, req,
+ arguments);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object")
+ 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__file_get(obj, cls, get_type, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "unable to execute file get callback")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLfile_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__file_specific
+ *
+ * Purpose: Perform File specific operations through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__file_specific(void *obj, const H5VL_class_t *cls, H5VL_file_specific_t specific_type,
+ hid_t dxpl_id, void **req, va_list arguments)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->file_cls.specific)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'file specific' method")
+
+ /* Call the corresponding VOL callback */
+ if((cls->file_cls.specific)(obj, specific_type, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "file specific failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__file_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_file_specific
+ *
+ * Purpose: Perform File specific operations through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_file_specific(const H5VL_object_t *vol_obj, H5VL_file_specific_t specific_type,
+ hid_t dxpl_id, void **req, ...)
+{
+ const H5VL_class_t *cls; /* VOL connector's class struct */
+ va_list arguments; /* Argument list passed from the API call */
+ hbool_t arg_started = FALSE; /* Whether the va_list has been started */
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Start access to the varargs, so they are available in all situations below */
+ HDva_start(arguments, req);
+ arg_started = TRUE;
+
+ /* Special treatment of file access check */
+ if(specific_type == H5VL_FILE_IS_ACCESSIBLE || specific_type == H5VL_FILE_DELETE) {
+ H5P_genplist_t *plist; /* Property list pointer */
+ H5VL_connector_prop_t connector_prop; /* Property for VOL connector ID & info */
+ va_list tmp_args; /* argument list passed from the API call */
+ hid_t fapl_id; /* File access property list for accessing the file */
+
+ /* Get the file access property list to access the file */
+ HDva_copy(tmp_args, arguments);
+ fapl_id = HDva_arg(tmp_args, hid_t);
+ HDva_end(tmp_args);
+
+ /* Get the VOL info from the FAPL */
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id)))
+ HGOTO_ERROR(H5E_VOL, H5E_BADTYPE, FAIL, "not a file access property list")
+ if(H5P_peek(plist, H5F_ACS_VOL_CONN_NAME, &connector_prop) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't get VOL connector info")
+
+ /* Get class pointer */
+ if(NULL == (cls = (H5VL_class_t *)H5I_object_verify(connector_prop.connector_id, H5I_VOL)))
+ HGOTO_ERROR(H5E_VOL, H5E_BADTYPE, FAIL, "not a VOL connector ID")
+ } /* end if */
+ /* Set wrapper info in API context, for all other operations */
+ else {
+ /* Sanity check */
+ HDassert(vol_obj);
+
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL wrapper info")
+ vol_wrapper_set = TRUE;
+
+ /* Set the VOL connector class pointer */
+ cls = vol_obj->connector->cls;
+ } /* end else */
+
+ /* Call the corresponding internal VOL routine */
+ if(H5VL__file_specific(vol_obj ? vol_obj->data : NULL, cls, specific_type, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "file specific failed")
+
+done:
+ /* End access to the va_list, if we started it */
+ if(arg_started)
+ HDva_end(arguments);
+
+ /* 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_file_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLfile_specific
+ *
+ * Purpose: Performs a connector-specific operation on a file
+ *
+ * Note: The 'obj' parameter is allowed to be NULL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLfile_specific(void *obj, hid_t connector_id, H5VL_file_specific_t specific_type,
+ hid_t dxpl_id, void **req, va_list arguments)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE6("e", "*xiVhi**xx", obj, connector_id, specific_type, dxpl_id, req,
+ arguments);
+
+ /* Check args and get class pointer */
+ 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__file_specific(obj, cls, specific_type, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute file specific callback")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLfile_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__file_optional
+ *
+ * Purpose: Perform a connector specific operation
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__file_optional(void *obj, const H5VL_class_t *cls, hid_t dxpl_id,
+ void **req, va_list arguments)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->file_cls.optional)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'file optional' method")
+
+ /* Call the corresponding VOL callback */
+ if((cls->file_cls.optional)(obj, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "file optional failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__file_optional() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_file_optional
+ *
+ * Purpose: Perform a connector specific operation
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_file_optional(const H5VL_object_t *vol_obj, hid_t dxpl_id, void **req, ...)
+{
+ va_list arguments; /* Argument list passed from the API call */
+ hbool_t arg_started = FALSE; /* Whether the va_list has been started */
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL wrapper info")
+ vol_wrapper_set = TRUE;
+
+ /* Call the corresponding internal VOL routine */
+ HDva_start(arguments, req);
+ arg_started = TRUE;
+ if(H5VL__file_optional(vol_obj->data, vol_obj->connector->cls, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "file optional failed")
+
+done:
+ /* End access to the va_list, if we started it */
+ if(arg_started)
+ HDva_end(arguments);
+
+ /* 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_file_optional() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLfile_optional
+ *
+ * Purpose: Performs an optional connector-specific operation on a file
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLfile_optional(void *obj, hid_t connector_id, hid_t dxpl_id, void **req,
+ va_list arguments)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE5("e", "*xii**xx", obj, connector_id, dxpl_id, req, arguments);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object")
+ 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__file_optional(obj, cls, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute file optional callback")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLfile_optional() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__file_close
+ *
+ * Purpose: Closes a file through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__file_close(void *obj, const H5VL_class_t *cls, hid_t dxpl_id, void **req)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity check */
+ HDassert(obj);
+ HDassert(cls);
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->file_cls.close)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'file close' method")
+
+ /* Call the corresponding VOL callback */
+ if((cls->file_cls.close)(obj, dxpl_id, req) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCLOSEFILE, FAIL, "file close failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__file_close() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_file_close
+ *
+ * Purpose: Closes a file through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_file_close(const H5VL_object_t *vol_obj, hid_t dxpl_id, void **req)
+{
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 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__file_close(vol_obj->data, vol_obj->connector->cls, dxpl_id, req) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCLOSEFILE, FAIL, "file close 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_file_close() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLfile_close
+ *
+ * Purpose: Closes a file
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLfile_close(void *obj, hid_t connector_id, hid_t dxpl_id, void **req)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE4("e", "*xii**x", obj, connector_id, dxpl_id, req);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object")
+ 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__file_close(obj, cls, dxpl_id, req) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCLOSEFILE, FAIL, "unable to close file")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLfile_close() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__group_create
+ *
+ * Purpose: Creates a group through the VOL
+ *
+ * Return: Success: Pointer to new group
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5VL__group_create(void *obj, const H5VL_loc_params_t *loc_params, const H5VL_class_t *cls,
+ const char *name, hid_t lcpl_id, hid_t gcpl_id, hid_t gapl_id,
+ hid_t dxpl_id, void **req)
+{
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->group_cls.create)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, NULL, "VOL connector has no 'group create' method")
+
+ /* Call the corresponding VOL callback */
+ if(NULL == (ret_value = (cls->group_cls.create)(obj, loc_params, name, lcpl_id, gcpl_id, gapl_id, dxpl_id, req)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCREATE, NULL, "group create failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__group_create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_group_create
+ *
+ * Purpose: Creates a group through the VOL
+ *
+ * Return: Success: Pointer to new group
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VL_group_create(const H5VL_object_t *vol_obj, const H5VL_loc_params_t *loc_params,
+ const char *name, hid_t lcpl_id, hid_t gcpl_id, hid_t gapl_id, hid_t dxpl_id,
+ void **req)
+{
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_NOAPI(NULL)
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, NULL, "can't set VOL wrapper info")
+ vol_wrapper_set = TRUE;
+
+ /* Call the corresponding internal VOL routine */
+ if(NULL == (ret_value = H5VL__group_create(vol_obj->data, loc_params, vol_obj->connector->cls, name, lcpl_id, gcpl_id, gapl_id, dxpl_id, req)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCREATE, NULL, "group create failed")
+
+done:
+ /* Reset object wrapping info in API context */
+ if(vol_wrapper_set && H5VL_reset_vol_wrapper() < 0)
+ HDONE_ERROR(H5E_VOL, H5E_CANTRESET, NULL, "can't reset VOL wrapper info")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_group_create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLgroup_create
+ *
+ * Purpose: Creates a group
+ *
+ * Return: Success: Pointer to the new group
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VLgroup_create(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id,
+ const char *name, hid_t lcpl_id, hid_t gcpl_id, hid_t gapl_id,hid_t dxpl_id,
+ void **req)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE9("*x", "*x*xi*siiii**x", obj, loc_params, connector_id, name, lcpl_id,
+ gcpl_id, gapl_id, dxpl_id, req);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid object")
+ if(NULL == (cls = (H5VL_class_t *)H5I_object_verify(connector_id, H5I_VOL)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a VOL connector ID")
+
+ /* Call the corresponding internal VOL routine */
+ if(NULL == (ret_value = H5VL__group_create(obj, loc_params, cls, name, lcpl_id, gcpl_id, gapl_id, dxpl_id, req)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCREATE, NULL, "unable to create group")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLgroup_create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__group_open
+ *
+ * Purpose: Opens a group through the VOL
+ *
+ * Return: Success: Pointer to group
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5VL__group_open(void *obj, const H5VL_loc_params_t *loc_params, const H5VL_class_t *cls,
+ const char *name, hid_t gapl_id, hid_t dxpl_id, void **req)
+{
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->group_cls.open)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, NULL, "VOL connector has no 'group open' method")
+
+ /* Call the corresponding VOL callback */
+ if(NULL == (ret_value = (cls->group_cls.open)(obj, loc_params, name, gapl_id, dxpl_id, req)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPENOBJ, NULL, "group open failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__group_open() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_group_open
+ *
+ * Purpose: Opens a group through the VOL
+ *
+ * Return: Success: Pointer to group
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VL_group_open(const H5VL_object_t *vol_obj, const H5VL_loc_params_t *loc_params,
+ const char *name, hid_t gapl_id, hid_t dxpl_id, void **req)
+{
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_NOAPI(NULL)
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, NULL, "can't set VOL wrapper info")
+ vol_wrapper_set = TRUE;
+
+ /* Call the corresponding internal VOL routine */
+ if(NULL == (ret_value = H5VL__group_open(vol_obj->data, loc_params, vol_obj->connector->cls, name, gapl_id, dxpl_id, req)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPENOBJ, NULL, "group open failed")
+
+done:
+ /* Reset object wrapping info in API context */
+ if(vol_wrapper_set && H5VL_reset_vol_wrapper() < 0)
+ HDONE_ERROR(H5E_VOL, H5E_CANTRESET, NULL, "can't reset VOL wrapper info")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_group_open() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLgroup_open
+ *
+ * Purpose: Opens a group
+ *
+ * Return: Success: Pointer to the group
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VLgroup_open(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, const char *name,
+ hid_t gapl_id, hid_t dxpl_id, void **req)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE7("*x", "*x*xi*sii**x", obj, loc_params, connector_id, name, gapl_id,
+ dxpl_id, req);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid object")
+ if(NULL == (cls = (H5VL_class_t *)H5I_object_verify(connector_id, H5I_VOL)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a VOL connector ID")
+
+ /* Call the corresponding internal VOL routine */
+ if(NULL == (ret_value = H5VL__group_open(obj, loc_params, cls, name, gapl_id, dxpl_id, req)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, NULL, "unable to open group")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLgroup_open() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__group_get
+ *
+ * Purpose: Get specific information about the group through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__group_get(void *obj, const H5VL_class_t *cls, H5VL_group_get_t get_type,
+ hid_t dxpl_id, void **req, va_list arguments)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->group_cls.get)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'group get' method")
+
+ /* Call the corresponding VOL callback */
+ if((cls->group_cls.get)(obj, get_type, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "group get failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__group_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_group_get
+ *
+ * Purpose: Get specific information about the group through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_group_get(const H5VL_object_t *vol_obj, H5VL_group_get_t get_type,
+ hid_t dxpl_id, void **req, ...)
+{
+ va_list arguments; /* Argument list passed from the API call */
+ hbool_t arg_started = FALSE; /* Whether the va_list has been started */
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL wrapper info")
+ vol_wrapper_set = TRUE;
+
+ /* Call the corresponding internal VOL routine */
+ HDva_start(arguments, req);
+ arg_started = TRUE;
+ if(H5VL__group_get(vol_obj->data, vol_obj->connector->cls, get_type, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "group get failed")
+
+done:
+ /* End access to the va_list, if we started it */
+ if(arg_started)
+ HDva_end(arguments);
+
+ /* 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_group_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLgroup_get
+ *
+ * Purpose: Gets information about the group
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLgroup_get(void *obj, hid_t connector_id, H5VL_group_get_t get_type,
+ hid_t dxpl_id, void **req, va_list arguments)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE6("e", "*xiVii**xx", obj, connector_id, get_type, dxpl_id, req,
+ arguments);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object")
+ 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__group_get(obj, cls, get_type, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "unable to execute group get callback")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLgroup_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__group_specific
+ *
+ * Purpose: Specific operation on groups through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__group_specific(void *obj, const H5VL_class_t *cls, H5VL_group_specific_t specific_type,
+ hid_t dxpl_id, void **req, va_list arguments)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->group_cls.specific)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'group specific' method")
+
+ /* Call the corresponding VOL callback */
+ if((cls->group_cls.specific)(obj, specific_type, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute group specific callback")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__group_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_group_specific
+ *
+ * Purpose: Specific operation on groups through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_group_specific(const H5VL_object_t *vol_obj, H5VL_group_specific_t specific_type,
+ hid_t dxpl_id, void **req, ...)
+{
+ va_list arguments; /* Argument list passed from the API call */
+ hbool_t arg_started = FALSE; /* Whether the va_list has been started */
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL wrapper info")
+ vol_wrapper_set = TRUE;
+
+ /* Call the corresponding internal VOL routine */
+ HDva_start(arguments, req);
+ arg_started = TRUE;
+ if(H5VL__group_specific(vol_obj->data, vol_obj->connector->cls, specific_type, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute group specific callback")
+
+done:
+ /* End access to the va_list, if we started it */
+ if(arg_started)
+ HDva_end(arguments);
+
+ /* 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_group_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLgroup_specific
+ *
+ * Purpose: Performs a connector-specific operation on a group
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLgroup_specific(void *obj, hid_t connector_id, H5VL_group_specific_t specific_type,
+ hid_t dxpl_id, void **req, va_list arguments)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE6("e", "*xiVji**xx", obj, connector_id, specific_type, dxpl_id, req,
+ arguments);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object")
+ 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__group_specific(obj, cls, specific_type, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute group specific callback")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLgroup_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__group_optional
+ *
+ * Purpose: Optional operation specific to connectors.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__group_optional(void *obj, const H5VL_class_t *cls, hid_t dxpl_id,
+ void **req, va_list arguments)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->group_cls.optional)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'group optional' method")
+
+ /* Call the corresponding VOL callback */
+ if((ret_value = (cls->group_cls.optional)(obj, dxpl_id, req, arguments)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute group optional callback")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__group_optional() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_group_optional
+ *
+ * Purpose: Optional operation specific to connectors.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_group_optional(const H5VL_object_t *vol_obj, hid_t dxpl_id, void **req, ...)
+{
+ va_list arguments; /* Argument list passed from the API call */
+ hbool_t arg_started = FALSE; /* Whether the va_list has been started */
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL wrapper info")
+ vol_wrapper_set = TRUE;
+
+ /* Call the corresponding internal VOL routine */
+ HDva_start(arguments, req);
+ arg_started = TRUE;
+ if((ret_value = H5VL__group_optional(vol_obj->data, vol_obj->connector->cls, dxpl_id, req, arguments)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute group optional callback")
+
+done:
+ /* End access to the va_list, if we started it */
+ if(arg_started)
+ HDva_end(arguments);
+
+ /* 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_group_optional() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLgroup_optional
+ *
+ * Purpose: Performs an optional connector-specific operation on a group
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLgroup_optional(void *obj, hid_t connector_id, hid_t dxpl_id, void **req,
+ va_list arguments)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE5("e", "*xii**xx", obj, connector_id, dxpl_id, req, arguments);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object")
+ 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((ret_value = H5VL__group_optional(obj, cls, dxpl_id, req, arguments)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute group optional callback")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLgroup_optional() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__group_close
+ *
+ * Purpose: Closes a group through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__group_close(void *obj, const H5VL_class_t *cls, hid_t dxpl_id, void **req)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ /* Sanity check */
+ HDassert(obj);
+ HDassert(cls);
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->group_cls.close)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'group close' method")
+
+ /* Call the corresponding VOL callback */
+ if((cls->group_cls.close)(obj, dxpl_id, req) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCLOSEOBJ, FAIL, "group close failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__group_close() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_group_close
+ *
+ * Purpose: Closes a group through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_group_close(const H5VL_object_t *vol_obj, hid_t dxpl_id, void **req)
+{
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 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__group_close(vol_obj->data, vol_obj->connector->cls, dxpl_id, req) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCLOSEOBJ, FAIL, "group close 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_group_close() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLgroup_close
+ *
+ * Purpose: Closes a group
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLgroup_close(void *obj, hid_t connector_id, hid_t dxpl_id, void **req)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE4("e", "*xii**x", obj, connector_id, dxpl_id, req);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object")
+ 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__group_close(obj, cls, dxpl_id, req) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCLOSEOBJ, FAIL, "unable to close group")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLgroup_close() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__link_create
+ *
+ * Purpose: Creates a link through the VOL
+ *
+ * Note: The 'obj' parameter is allowed to be NULL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__link_create(H5VL_link_create_type_t create_type, void *obj, const H5VL_loc_params_t *loc_params,
+ const H5VL_class_t *cls, hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id, void **req,
+ va_list arguments)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->link_cls.create)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'link create' method")
+
+ /* Call the corresponding VOL callback */
+ if((cls->link_cls.create)(create_type, obj, loc_params, lcpl_id, lapl_id, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCREATE, FAIL, "link create failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__link_create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_link_create
+ *
+ * Purpose: Creates a link through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_link_create(H5VL_link_create_type_t create_type, const H5VL_object_t *vol_obj,
+ const H5VL_loc_params_t *loc_params, hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id,
+ void **req, ...)
+{
+ H5VL_object_t tmp_vol_obj; /* Temporary object token of */
+ va_list arguments; /* Argument list passed from the API call */
+ hbool_t arg_started = FALSE; /* Whether the va_list has been started */
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Start the varargs, so they can be copied */
+ HDva_start(arguments, req);
+ arg_started = TRUE;
+
+ /* Special case for hard links */
+ if(H5VL_LINK_CREATE_HARD == create_type && NULL == vol_obj->data) {
+ va_list tmp_arguments; /* Copy of argument list passed in */
+
+ /* Get the VOL data pointer from the varargs */
+ HDva_copy(tmp_arguments, arguments);
+ tmp_vol_obj.data = HDva_arg(tmp_arguments, void *);
+ HDva_end(tmp_arguments);
+ } /* end if */
+ else
+ /* Use the VOL object passed in */
+ tmp_vol_obj.data = vol_obj->data;
+ tmp_vol_obj.connector = vol_obj->connector;
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(tmp_vol_obj.data, tmp_vol_obj.connector) < 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__link_create(create_type, vol_obj->data, loc_params, vol_obj->connector->cls, lcpl_id, lapl_id, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCREATE, FAIL, "link create failed")
+
+done:
+ /* End access to the va_list, if we started it */
+ if(arg_started)
+ HDva_end(arguments);
+
+ /* 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_link_create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLlink_create
+ *
+ * Purpose: Creates a link
+ *
+ * Note: The 'obj' parameter is allowed to be NULL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLlink_create(H5VL_link_create_type_t create_type, void *obj, const H5VL_loc_params_t *loc_params,
+ hid_t connector_id, hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id, void **req,
+ va_list arguments)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE9("e", "Vk*x*xiiii**xx", create_type, obj, loc_params, connector_id,
+ lcpl_id, lapl_id, dxpl_id, req, arguments);
+
+ /* Get class pointer */
+ 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__link_create(create_type, obj, loc_params, cls, lcpl_id, lapl_id, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCREATE, FAIL, "unable to create link")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLlink_create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__link_copy
+ *
+ * Purpose: Copys a link from src to dst.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__link_copy(void *src_obj, const H5VL_loc_params_t *loc_params1, void *dst_obj,
+ const H5VL_loc_params_t *loc_params2, const H5VL_class_t *cls, hid_t lcpl_id,
+ hid_t lapl_id, hid_t dxpl_id, void **req)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->link_cls.copy)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'link copy' method")
+
+ /* Call the corresponding VOL callback */
+ if((cls->link_cls.copy)(src_obj, loc_params1, dst_obj, loc_params2, lcpl_id, lapl_id, dxpl_id, req) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCOPY, FAIL, "link copy failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__link_copy() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_link_copy
+ *
+ * Purpose: Copys a link from src to dst.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_link_copy(const H5VL_object_t *src_vol_obj, const H5VL_loc_params_t *loc_params1,
+ const H5VL_object_t *dst_vol_obj, const H5VL_loc_params_t *loc_params2, hid_t lcpl_id,
+ hid_t lapl_id, hid_t dxpl_id, void **req)
+{
+ const H5VL_object_t *vol_obj; /* VOL object for object with data */
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Set wrapper info in API context */
+ vol_obj = (src_vol_obj->data ? src_vol_obj : dst_vol_obj);
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 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__link_copy(src_vol_obj->data, loc_params1, (dst_vol_obj ? dst_vol_obj->data : NULL), loc_params2, vol_obj->connector->cls, lcpl_id, lapl_id, dxpl_id, req) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCOPY, FAIL, "link copy 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_link_copy() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLlink_copy
+ *
+ * Purpose: Copies a link to a new location
+ *
+ * Note: The 'src_obj' and 'dst_obj' parameters are allowed to be NULL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLlink_copy(void *src_obj, const H5VL_loc_params_t *loc_params1, void *dst_obj,
+ const H5VL_loc_params_t *loc_params2, hid_t connector_id, hid_t lcpl_id,
+ hid_t lapl_id, hid_t dxpl_id, void **req)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE9("e", "*x*x*x*xiiii**x", src_obj, loc_params1, dst_obj, loc_params2,
+ connector_id, lcpl_id, lapl_id, dxpl_id, req);
+
+ /* Get class pointer */
+ 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__link_copy(src_obj, loc_params1, dst_obj, loc_params2, cls, lcpl_id, lapl_id, dxpl_id, req) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCOPY, FAIL, "unable to copy object")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLlink_copy() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__link_move
+ *
+ * Purpose: Moves a link from src to dst.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__link_move(void *src_obj, const H5VL_loc_params_t *loc_params1, void *dst_obj,
+ const H5VL_loc_params_t *loc_params2, const H5VL_class_t *cls, hid_t lcpl_id,
+ hid_t lapl_id, hid_t dxpl_id, void **req)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->link_cls.move)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'link move' method")
+
+ /* Call the corresponding VOL callback */
+ if((cls->link_cls.move)(src_obj, loc_params1, dst_obj, loc_params2, lcpl_id, lapl_id, dxpl_id, req) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTMOVE, FAIL, "link move failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__link_move() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_link_move
+ *
+ * Purpose: Moves a link from src to dst.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_link_move(const H5VL_object_t *src_vol_obj, const H5VL_loc_params_t *loc_params1,
+ const H5VL_object_t *dst_vol_obj, const H5VL_loc_params_t *loc_params2, hid_t lcpl_id,
+ hid_t lapl_id, hid_t dxpl_id, void **req)
+{
+ const H5VL_object_t *vol_obj; /* VOL object for object with data */
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Set wrapper info in API context */
+ vol_obj = (src_vol_obj->data ? src_vol_obj : dst_vol_obj);
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 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__link_move(src_vol_obj->data, loc_params1, (dst_vol_obj ? dst_vol_obj->data : NULL), loc_params2, vol_obj->connector->cls, lcpl_id, lapl_id, dxpl_id, req) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTMOVE, FAIL, "link move 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_link_move() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLlink_move
+ *
+ * Purpose: Moves a link to another location
+ *
+ * Note: The 'src_obj' and 'dst_obj' parameters are allowed to be NULL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLlink_move(void *src_obj, const H5VL_loc_params_t *loc_params1, void *dst_obj,
+ const H5VL_loc_params_t *loc_params2, hid_t connector_id, hid_t lcpl_id,
+ hid_t lapl_id, hid_t dxpl_id, void **req)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE9("e", "*x*x*x*xiiii**x", src_obj, loc_params1, dst_obj, loc_params2,
+ connector_id, lcpl_id, lapl_id, dxpl_id, req);
+
+ /* Get class pointer */
+ 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__link_move(src_obj, loc_params1, dst_obj, loc_params2, cls, lcpl_id, lapl_id, dxpl_id, req) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTMOVE, FAIL, "unable to move object")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLlink_move() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__link_get
+ *
+ * Purpose: Get specific information about the link through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__link_get(void *obj, const H5VL_loc_params_t *loc_params, const H5VL_class_t *cls,
+ H5VL_link_get_t get_type, hid_t dxpl_id, void **req, va_list arguments)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->link_cls.get)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'link get' method")
+
+ /* Call the corresponding VOL callback */
+ if((cls->link_cls.get)(obj, loc_params, get_type, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "link get failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__link_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_link_get
+ *
+ * Purpose: Get specific information about the link through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_link_get(const H5VL_object_t *vol_obj, const H5VL_loc_params_t *loc_params,
+ H5VL_link_get_t get_type, hid_t dxpl_id, void **req, ...)
+{
+ va_list arguments; /* Argument list passed from the API call */
+ hbool_t arg_started = FALSE; /* Whether the va_list has been started */
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL wrapper info")
+ vol_wrapper_set = TRUE;
+
+ /* Call the corresponding internal VOL routine */
+ HDva_start(arguments, req);
+ arg_started = TRUE;
+ if(H5VL__link_get(vol_obj->data, loc_params, vol_obj->connector->cls, get_type, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "link get failed")
+
+done:
+ /* End access to the va_list, if we started it */
+ if(arg_started)
+ HDva_end(arguments);
+
+ /* 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_link_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLlink_get
+ *
+ * Purpose: Gets information about a link
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLlink_get(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, H5VL_link_get_t get_type,
+ hid_t dxpl_id, void **req, va_list arguments)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE7("e", "*x*xiVli**xx", obj, loc_params, connector_id, get_type, dxpl_id,
+ req, arguments);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object")
+ 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__link_get(obj, loc_params, cls, get_type, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "unable to execute link get callback")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLlink_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__link_specific
+ *
+ * Purpose: Specific operation on links through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__link_specific(void *obj, const H5VL_loc_params_t *loc_params, const H5VL_class_t *cls,
+ H5VL_link_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->link_cls.specific)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'link specific' method")
+
+ /* Call the corresponding VOL callback */
+ if((ret_value = (cls->link_cls.specific)(obj, loc_params, specific_type, dxpl_id, req, arguments)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute link specific callback")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__link_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_link_specific
+ *
+ * Purpose: Specific operation on links through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_link_specific(const H5VL_object_t *vol_obj, const H5VL_loc_params_t *loc_params,
+ H5VL_link_specific_t specific_type, hid_t dxpl_id, void **req, ...)
+{
+ va_list arguments; /* Argument list passed from the API call */
+ hbool_t arg_started = FALSE; /* Whether the va_list has been started */
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL wrapper info")
+ vol_wrapper_set = TRUE;
+
+ /* Call the corresponding internal VOL routine */
+ HDva_start(arguments, req);
+ arg_started = TRUE;
+ if((ret_value = H5VL__link_specific(vol_obj->data, loc_params, vol_obj->connector->cls, specific_type, dxpl_id, req, arguments)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute link specific callback")
+
+done:
+ /* End access to the va_list, if we started it */
+ if(arg_started)
+ HDva_end(arguments);
+
+ /* 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_link_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLlink_specific
+ *
+ * Purpose: Performs a connector-specific operation on a link
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLlink_specific(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id,
+ H5VL_link_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE7("e", "*x*xiVmi**xx", obj, loc_params, connector_id, specific_type,
+ dxpl_id, req, arguments);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object")
+ 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((ret_value = H5VL__link_specific(obj, loc_params, cls, specific_type, dxpl_id, req, arguments)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute link specific callback")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLlink_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__link_optional
+ *
+ * Purpose: Optional operation specific to connectors.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__link_optional(void *obj, const H5VL_class_t *cls, hid_t dxpl_id,
+ void **req, va_list arguments)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->link_cls.optional)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'link optional' method")
+
+ /* Call the corresponding VOL callback */
+ if((cls->link_cls.optional)(obj, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute link optional callback")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__link_optional() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_link_optional
+ *
+ * Purpose: Optional operation specific to connectors.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_link_optional(const H5VL_object_t *vol_obj, hid_t dxpl_id, void **req, ...)
+{
+ va_list arguments; /* Argument list passed from the API call */
+ hbool_t arg_started = FALSE; /* Whether the va_list has been started */
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL wrapper info")
+ vol_wrapper_set = TRUE;
+
+ /* Call the corresponding internal VOL routine */
+ HDva_start(arguments, req);
+ arg_started = TRUE;
+ if(H5VL__link_optional(vol_obj->data, vol_obj->connector->cls, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute link optional callback")
+
+done:
+ /* End access to the va_list, if we started it */
+ if(arg_started)
+ HDva_end(arguments);
+
+ /* 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_link_optional() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLlink_optional
+ *
+ * Purpose: Performs an optional connector-specific operation on a link
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLlink_optional(void *obj, hid_t connector_id, hid_t dxpl_id, void **req, va_list arguments)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE5("e", "*xii**xx", obj, connector_id, dxpl_id, req, arguments);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object")
+ 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__link_optional(obj, cls, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute link optional callback")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLlink_optional() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__object_open
+ *
+ * Purpose: Opens a object through the VOL
+ *
+ * Return: Success: Pointer to the object
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5VL__object_open(void *obj, const H5VL_loc_params_t *params, const H5VL_class_t *cls, H5I_type_t *opened_type,
+ hid_t dxpl_id, void **req)
+{
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->object_cls.open)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, NULL, "VOL connector has no 'object open' method")
+
+ /* Call the corresponding VOL callback */
+ if(NULL == (ret_value = (cls->object_cls.open)(obj, params, opened_type, dxpl_id, req)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPENOBJ, NULL, "object open failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__object_open() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_object_open
+ *
+ * Purpose: Opens a object through the VOL
+ *
+ * Return: Success: Pointer to the object
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VL_object_open(const H5VL_object_t *vol_obj, const H5VL_loc_params_t *params,
+ H5I_type_t *opened_type, hid_t dxpl_id, void **req)
+{
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_NOAPI(NULL)
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, NULL, "can't set VOL wrapper info")
+ vol_wrapper_set = TRUE;
+
+ /* Call the corresponding internal VOL routine */
+ if(NULL == (ret_value = H5VL__object_open(vol_obj->data, params, vol_obj->connector->cls, opened_type, dxpl_id, req)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPENOBJ, NULL, "object open failed")
+
+done:
+ /* Reset object wrapping info in API context */
+ if(vol_wrapper_set && H5VL_reset_vol_wrapper() < 0)
+ HDONE_ERROR(H5E_VOL, H5E_CANTRESET, NULL, "can't reset VOL wrapper info")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_object_open() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLobject_open
+ *
+ * Purpose: Opens an object
+ *
+ * Return: Success: Pointer to the object
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VLobject_open(void *obj, const H5VL_loc_params_t *params, hid_t connector_id, H5I_type_t *opened_type,
+ hid_t dxpl_id, void **req)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE6("*x", "*x*xi*Iti**x", obj, params, connector_id, opened_type, dxpl_id,
+ req);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid object")
+ if(NULL == (cls = (H5VL_class_t *)H5I_object_verify(connector_id, H5I_VOL)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a VOL connector ID")
+
+ /* Call the corresponding internal VOL routine */
+ if(NULL == (ret_value = H5VL__object_open(obj, params, cls, opened_type, dxpl_id, req)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPENOBJ, NULL, "unable to open object")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLobject_open() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__object_copy
+ *
+ * Purpose: Copies an object to another destination through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__object_copy(void *src_obj, const H5VL_loc_params_t *src_loc_params, const char *src_name,
+ void *dst_obj, const H5VL_loc_params_t *dst_loc_params, const char *dst_name,
+ const H5VL_class_t *cls, hid_t ocpypl_id, hid_t lcpl_id, hid_t dxpl_id,
+ void **req)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->object_cls.copy)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'object copy' method")
+
+ /* Call the corresponding VOL callback */
+ if((cls->object_cls.copy)(src_obj, src_loc_params, src_name, dst_obj, dst_loc_params, dst_name, ocpypl_id, lcpl_id, dxpl_id, req) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCOPY, FAIL, "object copy failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__object_copy() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_object_copy
+ *
+ * Purpose: Copies an object to another destination through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_object_copy(const H5VL_object_t *src_obj, const H5VL_loc_params_t *src_loc_params,
+ const char *src_name, const H5VL_object_t *dst_obj, const H5VL_loc_params_t *dst_loc_params,
+ const char *dst_name, hid_t ocpypl_id, hid_t lcpl_id, hid_t dxpl_id,
+ void **req)
+{
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Make sure that the VOL connectors are the same */
+ if(src_obj->connector->cls->value != dst_obj->connector->cls->value)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "objects are accessed through different VOL connectors and can't be copied")
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(src_obj->data, src_obj->connector) < 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__object_copy(src_obj->data, src_loc_params, src_name, dst_obj->data, dst_loc_params, dst_name, src_obj->connector->cls, ocpypl_id, lcpl_id, dxpl_id, req) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCOPY, FAIL, "object copy 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_object_copy() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLobject_copy
+ *
+ * Purpose: Copies an object to another location
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLobject_copy(void *src_obj, const H5VL_loc_params_t *src_loc_params,
+ const char *src_name, void *dst_obj, const H5VL_loc_params_t *dst_loc_params,
+ const char *dst_name, hid_t connector_id, hid_t ocpypl_id, hid_t lcpl_id,
+ hid_t dxpl_id, void **req)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE11("e", "*x*x*s*x*x*siiii**x", src_obj, src_loc_params, src_name,
+ dst_obj, dst_loc_params, dst_name, connector_id, ocpypl_id, lcpl_id,
+ dxpl_id, req);
+
+ /* Check args and get class pointers */
+ if(NULL == src_obj || NULL == dst_obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object")
+ 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__object_copy(src_obj, src_loc_params, src_name, dst_obj, dst_loc_params, dst_name, cls, ocpypl_id, lcpl_id, dxpl_id, req) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCOPY, FAIL, "unable to copy object")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLobject_copy() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__object_get
+ *
+ * Purpose: Get specific information about the object through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__object_get(void *obj, const H5VL_loc_params_t *loc_params, const H5VL_class_t *cls,
+ H5VL_object_get_t get_type, hid_t dxpl_id, void **req, va_list arguments)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->object_cls.get)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'object get' method")
+
+ /* Call the corresponding VOL callback */
+ if((cls->object_cls.get)(obj, loc_params, get_type, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "get failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__object_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_object_get
+ *
+ * Purpose: Get specific information about the object through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_object_get(const H5VL_object_t *vol_obj, const H5VL_loc_params_t *loc_params,
+ H5VL_object_get_t get_type, hid_t dxpl_id, void **req, ...)
+{
+ va_list arguments; /* Argument list passed from the API call */
+ hbool_t arg_started = FALSE; /* Whether the va_list has been started */
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL wrapper info")
+ vol_wrapper_set = TRUE;
+
+ /* Call the corresponding internal VOL routine */
+ HDva_start(arguments, req);
+ arg_started = TRUE;
+ if(H5VL__object_get(vol_obj->data, loc_params, vol_obj->connector->cls, get_type, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "get failed")
+
+done:
+ /* End access to the va_list, if we started it */
+ if(arg_started)
+ HDva_end(arguments);
+
+ /* 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_object_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLobject_get
+ *
+ * Purpose: Gets information about an object
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLobject_get(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, H5VL_object_get_t get_type,
+ hid_t dxpl_id, void **req, va_list arguments)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE7("e", "*x*xiVni**xx", obj, loc_params, connector_id, get_type, dxpl_id,
+ req, arguments);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object")
+ 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__object_get(obj, loc_params, cls, get_type, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "unable to execute object get callback")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLobject_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__object_specific
+ *
+ * Purpose: Specific operation on objects through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__object_specific(void *obj, const H5VL_loc_params_t *loc_params, const H5VL_class_t *cls,
+ H5VL_object_specific_t specific_type, hid_t dxpl_id, void **req,
+ va_list arguments)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->object_cls.specific)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'object specific' method")
+
+ /* Call the corresponding VOL callback */
+ if((ret_value = (cls->object_cls.specific)(obj, loc_params, specific_type, dxpl_id, req, arguments)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "object specific failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__object_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_object_specific
+ *
+ * Purpose: Specific operation on objects through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_object_specific(const H5VL_object_t *vol_obj, const H5VL_loc_params_t *loc_params,
+ H5VL_object_specific_t specific_type, hid_t dxpl_id, void **req, ...)
+{
+ va_list arguments; /* Argument list passed from the API call */
+ hbool_t arg_started = FALSE; /* Whether the va_list has been started */
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL wrapper info")
+ vol_wrapper_set = TRUE;
+
+ /* Call the corresponding internal VOL routine */
+ HDva_start(arguments, req);
+ arg_started = TRUE;
+ if((ret_value = H5VL__object_specific(vol_obj->data, loc_params, vol_obj->connector->cls, specific_type, dxpl_id, req, arguments)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "object specific failed")
+
+done:
+ /* End access to the va_list, if we started it */
+ if(arg_started)
+ HDva_end(arguments);
+
+ /* 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_object_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLobject_specific
+ *
+ * Purpose: Performs a connector-specific operation on an object
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLobject_specific(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id,
+ H5VL_object_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE7("e", "*x*xiVoi**xx", obj, loc_params, connector_id, specific_type,
+ dxpl_id, req, arguments);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object")
+ 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")
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->object_cls.specific)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no `object specific' method")
+
+ /* Bypass the H5VLint layer, calling the VOL callback directly */
+ if((ret_value = (cls->object_cls.specific)(obj, loc_params, specific_type, dxpl_id, req, arguments)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute object specific callback")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLobject_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__object_optional
+ *
+ * Purpose: Optional operation specific to connectors.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__object_optional(void *obj, const H5VL_class_t *cls, hid_t dxpl_id,
+ void **req, va_list arguments)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->object_cls.optional)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'object optional' method")
+
+ /* Call the corresponding VOL callback */
+ if((cls->object_cls.optional)(obj, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute object optional callback")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__object_optional() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_object_optional
+ *
+ * Purpose: Optional operation specific to connectors.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_object_optional(const H5VL_object_t *vol_obj, hid_t dxpl_id, void **req, ...)
+{
+ va_list arguments; /* Argument list passed from the API call */
+ hbool_t arg_started = FALSE; /* Whether the va_list has been started */
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL wrapper info")
+ vol_wrapper_set = TRUE;
+
+ /* Call the corresponding internal VOL routine */
+ HDva_start(arguments, req);
+ arg_started = TRUE;
+ if(H5VL__object_optional(vol_obj->data, vol_obj->connector->cls, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute object optional callback")
+
+done:
+ /* End access to the va_list, if we started it */
+ if(arg_started)
+ HDva_end(arguments);
+
+ /* 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_object_optional() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLobject_optional
+ *
+ * Purpose: Performs an optional connector-specific operation on an object
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLobject_optional(void *obj, hid_t connector_id, hid_t dxpl_id, void **req, va_list arguments)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE5("e", "*xii**xx", obj, connector_id, dxpl_id, req, arguments);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object")
+ 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__object_optional(obj, cls, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute object optional callback")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLobject_optional() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__datatype_commit
+ *
+ * Purpose: Commits a datatype to the file through the VOL
+ *
+ * Return: Success: Pointer to the new datatype
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5VL__datatype_commit(void *obj, const H5VL_loc_params_t *loc_params, const H5VL_class_t *cls,
+ const char *name, hid_t type_id, hid_t lcpl_id, hid_t tcpl_id, hid_t tapl_id,
+ hid_t dxpl_id, void **req)
+{
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->datatype_cls.commit)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, NULL, "VOL connector has no 'datatype commit' method")
+
+ /* Call the corresponding VOL callback */
+ if(NULL == (ret_value = (cls->datatype_cls.commit)(obj, loc_params, name, type_id, lcpl_id, tcpl_id, tapl_id, dxpl_id, req)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCREATE, NULL, "datatype commit failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__datatype_commit() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_datatype_commit
+ *
+ * Purpose: Commits a datatype to the file through the VOL
+ *
+ * Return: Success: Pointer to the new datatype
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VL_datatype_commit(const H5VL_object_t *vol_obj, const H5VL_loc_params_t *loc_params,
+ const char *name, hid_t type_id, hid_t lcpl_id, hid_t tcpl_id, hid_t tapl_id,
+ hid_t dxpl_id, void **req)
+{
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_NOAPI(NULL)
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, NULL, "can't set VOL wrapper info")
+ vol_wrapper_set = TRUE;
+
+ /* Call the corresponding internal VOL routine */
+ if(NULL == (ret_value = H5VL__datatype_commit(vol_obj->data, loc_params, vol_obj->connector->cls, name, type_id, lcpl_id, tcpl_id, tapl_id, dxpl_id, req)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCREATE, NULL, "datatype commit failed")
+
+done:
+ /* Reset object wrapping info in API context */
+ if(vol_wrapper_set && H5VL_reset_vol_wrapper() < 0)
+ HDONE_ERROR(H5E_VOL, H5E_CANTRESET, NULL, "can't reset VOL wrapper info")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_datatype_commit() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLdatatype_commit
+ *
+ * Purpose: Commits a datatype to the file
+ *
+ * Return: Success: Pointer to the new datatype
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VLdatatype_commit(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id,
+ const char *name, hid_t type_id, hid_t lcpl_id, hid_t tcpl_id,
+ hid_t tapl_id, hid_t dxpl_id, void **req)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE10("*x", "*x*xi*siiiii**x", obj, loc_params, connector_id, name,
+ type_id, lcpl_id, tcpl_id, tapl_id, dxpl_id, req);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid object")
+ if(NULL == (cls = (H5VL_class_t *)H5I_object_verify(connector_id, H5I_VOL)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a VOL connector ID")
+
+ /* Call the corresponding internal VOL routine */
+ if(NULL == (ret_value = H5VL__datatype_commit(obj, loc_params, cls, name, type_id, lcpl_id, tcpl_id, tapl_id, dxpl_id, req)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCREATE, NULL, "unable to commit datatype")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLdatatype_commit() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__datatype_open
+ *
+ * Purpose: Opens a named datatype through the VOL
+ *
+ * Return: Success: Pointer to the datatype
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5VL__datatype_open(void *obj, const H5VL_loc_params_t *loc_params, const H5VL_class_t *cls,
+ const char *name, hid_t tapl_id, hid_t dxpl_id, void **req)
+{
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->datatype_cls.open)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, NULL, "no datatype open callback")
+
+ /* Call the corresponding VOL callback */
+ if(NULL == (ret_value = (cls->datatype_cls.open)(obj, loc_params, name, tapl_id, dxpl_id, req)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPENOBJ, NULL, "datatype open failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__datatype_open() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_datatype_open
+ *
+ * Purpose: Opens a named datatype through the VOL
+ *
+ * Return: Success: Pointer to the datatype
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VL_datatype_open(const H5VL_object_t *vol_obj, const H5VL_loc_params_t *loc_params,
+ const char *name, hid_t tapl_id, hid_t dxpl_id, void **req)
+{
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_NOAPI(NULL)
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, NULL, "can't set VOL wrapper info")
+ vol_wrapper_set = TRUE;
+
+ /* Call the corresponding internal VOL routine */
+ if(NULL == (ret_value = H5VL__datatype_open(vol_obj->data, loc_params, vol_obj->connector->cls, name, tapl_id, dxpl_id, req)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPENOBJ, NULL, "datatype open failed")
+
+done:
+ /* Reset object wrapping info in API context */
+ if(vol_wrapper_set && H5VL_reset_vol_wrapper() < 0)
+ HDONE_ERROR(H5E_VOL, H5E_CANTRESET, NULL, "can't reset VOL wrapper info")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_datatype_open() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLdatatype_open
+ *
+ * Purpose: Opens a named datatype
+ *
+ * Return: Success: Pointer to the datatype
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VLdatatype_open(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id,
+ const char *name, hid_t tapl_id, hid_t dxpl_id, void **req)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE7("*x", "*x*xi*sii**x", obj, loc_params, connector_id, name, tapl_id,
+ dxpl_id, req);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid object")
+ if(NULL == (cls = (H5VL_class_t *)H5I_object_verify(connector_id, H5I_VOL)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a VOL connector ID")
+
+ /* Call the corresponding internal VOL routine */
+ if(NULL == (ret_value = H5VL__datatype_open(obj, loc_params, cls, name, tapl_id, dxpl_id, req)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPENOBJ, NULL, "unable to open datatype")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLdatatype_open() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__datatype_get
+ *
+ * Purpose: Get specific information about the datatype through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__datatype_get(void *obj, const H5VL_class_t *cls, H5VL_datatype_get_t get_type,
+ hid_t dxpl_id, void **req, va_list arguments)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->datatype_cls.get)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'datatype get' method")
+
+ /* Call the corresponding VOL callback */
+ if((cls->datatype_cls.get)(obj, get_type, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "datatype get failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__datatype_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_datatype_get
+ *
+ * Purpose: Get specific information about the datatype through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_datatype_get(const H5VL_object_t *vol_obj, H5VL_datatype_get_t get_type,
+ hid_t dxpl_id, void **req, ...)
+{
+ va_list arguments; /* Argument list passed from the API call */
+ hbool_t arg_started = FALSE; /* Whether the va_list has been started */
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL wrapper info")
+ vol_wrapper_set = TRUE;
+
+ /* Call the corresponding internal VOL routine */
+ HDva_start(arguments, req);
+ arg_started = TRUE;
+ if(H5VL__datatype_get(vol_obj->data, vol_obj->connector->cls, get_type, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "datatype get failed")
+
+done:
+ /* End access to the va_list, if we started it */
+ if(arg_started)
+ HDva_end(arguments);
+
+ /* 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_datatype_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLdatatype_get
+ *
+ * Purpose: Gets information about the datatype
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLdatatype_get(void *obj, hid_t connector_id, H5VL_datatype_get_t get_type,
+ hid_t dxpl_id, void **req, va_list arguments)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE6("e", "*xiVei**xx", obj, connector_id, get_type, dxpl_id, req,
+ arguments);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object")
+ 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")
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->datatype_cls.get)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no `datatype get' method")
+
+ /* Call the corresponding internal VOL routine */
+ if(H5VL__datatype_get(obj, cls, get_type, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "unable to execute datatype get callback")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLdatatype_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__datatype_specific
+ *
+ * Purpose: Specific operation on datatypes through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__datatype_specific(void *obj, const H5VL_class_t *cls, H5VL_datatype_specific_t specific_type,
+ hid_t dxpl_id, void **req, va_list arguments)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->datatype_cls.specific)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'datatype specific' method")
+
+ /* Call the corresponding VOL callback */
+ if((cls->datatype_cls.specific)(obj, specific_type, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute datatype specific callback")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__datatype_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_datatype_specific
+ *
+ * Purpose: Specific operation on datatypes through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_datatype_specific(const H5VL_object_t *vol_obj, H5VL_datatype_specific_t specific_type,
+ hid_t dxpl_id, void **req, ...)
+{
+ va_list arguments; /* Argument list passed from the API call */
+ hbool_t arg_started = FALSE; /* Whether the va_list has been started */
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL wrapper info")
+ vol_wrapper_set = TRUE;
+
+ /* Call the corresponding internal VOL routine */
+ HDva_start(arguments, req);
+ arg_started = TRUE;
+ if(H5VL__datatype_specific(vol_obj->data, vol_obj->connector->cls, specific_type, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute datatype specific callback")
+
+done:
+ /* End access to the va_list, if we started it */
+ if(arg_started)
+ HDva_end(arguments);
+
+ /* 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_datatype_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLdatatype_specific
+ *
+ * Purpose: Performs a connector-specific operation on a datatype
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLdatatype_specific(void *obj, hid_t connector_id, H5VL_datatype_specific_t specific_type,
+ hid_t dxpl_id, void **req, va_list arguments)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE6("e", "*xiVfi**xx", obj, connector_id, specific_type, dxpl_id, req,
+ arguments);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object")
+ 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__datatype_specific(obj, cls, specific_type, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute datatype specific callback")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLdatatype_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__datatype_optional
+ *
+ * Purpose: Optional operation specific to connectors.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__datatype_optional(void *obj, const H5VL_class_t *cls, hid_t dxpl_id,
+ void **req, va_list arguments)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->datatype_cls.optional)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'datatype optional' method")
+
+ /* Call the corresponding VOL callback */
+ if((cls->datatype_cls.optional)(obj, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute datatype optional callback")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__datatype_optional() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_datatype_optional
+ *
+ * Purpose: Optional operation specific to connectors.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_datatype_optional(const H5VL_object_t *vol_obj, hid_t dxpl_id,
+ void **req, ...)
+{
+ va_list arguments; /* Argument list passed from the API call */
+ hbool_t arg_started = FALSE; /* Whether the va_list has been started */
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL wrapper info")
+ vol_wrapper_set = TRUE;
+
+ /* Call the corresponding internal VOL routine */
+ HDva_start(arguments, req);
+ arg_started = TRUE;
+ if(H5VL__datatype_optional(vol_obj->data, vol_obj->connector->cls, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute datatype optional callback")
+
+done:
+ /* End access to the va_list, if we started it */
+ if(arg_started)
+ HDva_end(arguments);
+
+ /* 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_datatype_optional() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLdatatype_optional
+ *
+ * Purpose: Performs an optional connector-specific operation on a datatype
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLdatatype_optional(void *obj, hid_t connector_id, hid_t dxpl_id, void **req,
+ va_list arguments)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE5("e", "*xii**xx", obj, connector_id, dxpl_id, req, arguments);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object")
+ 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__datatype_optional(obj, cls, dxpl_id, req, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute datatype optional callback")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLdatatype_optional() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__datatype_close
+ *
+ * Purpose: Closes a datatype through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__datatype_close(void *obj, const H5VL_class_t *cls, hid_t dxpl_id,
+ void **req)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->datatype_cls.close)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'datatype close' method")
+
+ /* Call the corresponding VOL callback */
+ if((cls->datatype_cls.close)(obj, dxpl_id, req) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCLOSEOBJ, FAIL, "datatype close failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__datatype_close() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_datatype_close
+ *
+ * Purpose: Closes a datatype through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_datatype_close(const H5VL_object_t *vol_obj, hid_t dxpl_id, void **req)
+{
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 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__datatype_close(vol_obj->data, vol_obj->connector->cls, dxpl_id, req) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCLOSEOBJ, FAIL, "datatype close 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_datatype_close() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLdatatype_close
+ *
+ * Purpose: Closes a datatype
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLdatatype_close(void *obj, hid_t connector_id, hid_t dxpl_id, void **req)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE4("e", "*xii**x", obj, connector_id, dxpl_id, req);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object")
+ 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__datatype_close(obj, cls, dxpl_id, req) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCLOSEOBJ, FAIL, "unable to close datatype")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLdatatype_close() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__request_wait
+ *
+ * Purpose: Waits on an asychronous request through the VOL
+ *
+ * Note: Releases the request if the operation has completed and the
+ * connector callback succeeds
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__request_wait(void *req, const H5VL_class_t *cls, uint64_t timeout,
+ H5ES_status_t *status)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(req);
+ HDassert(cls);
+ HDassert(status);
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->request_cls.wait)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'async wait' method")
+
+ /* Call the corresponding VOL callback */
+ if((cls->request_cls.wait)(req, timeout, status) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "request wait failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__request_wait() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_request_wait
+ *
+ * Purpose: Waits on an asychronous request through the VOL
+ *
+ * Note: Releases the request if the operation has completed and the
+ * connector callback succeeds
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_request_wait(const H5VL_object_t *vol_obj, uint64_t timeout,
+ H5ES_status_t *status)
+{
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(vol_obj);
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 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__request_wait(vol_obj->data, vol_obj->connector->cls, timeout, status) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "request wait 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_request_wait() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLrequest_wait
+ *
+ * Purpose: Waits on a request
+ *
+ * Note: Releases the request if the operation has completed and the
+ * connector callback succeeds
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLrequest_wait(void *req, hid_t connector_id, uint64_t timeout, H5ES_status_t *status)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE4("e", "*xiUL*Es", req, connector_id, timeout, status);
+
+ /* Get class pointer */
+ 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__request_wait(req, cls, timeout, status) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "unable to wait on request")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLrequest_wait() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__request_notify
+ *
+ * Purpose: Registers a user callback to be invoked when an asynchronous
+ * operation completes
+ *
+ * Note: Releases the request, if connector callback succeeds
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__request_notify(void *req, const H5VL_class_t *cls, H5VL_request_notify_t cb,
+ void *ctx)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity check */
+ HDassert(req);
+ HDassert(cls);
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->request_cls.notify)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'async notify' method")
+
+ /* Call the corresponding VOL callback */
+ if((cls->request_cls.notify)(req, cb, ctx) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "request notify failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__request_notify() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_request_notify
+ *
+ * Purpose: Registers a user callback to be invoked when an asynchronous
+ * operation completes
+ *
+ * Note: Releases the request, if connector callback succeeds
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_request_notify(const H5VL_object_t *vol_obj, H5VL_request_notify_t cb,
+ void *ctx)
+{
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check */
+ HDassert(vol_obj);
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 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__request_notify(vol_obj->data, vol_obj->connector->cls, cb, ctx) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "request notify 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_request_notify() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLrequest_notify
+ *
+ * Purpose: Registers a user callback to be invoked when an asynchronous
+ * operation completes
+ *
+ * Note: Releases the request, if connector callback succeeds
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLrequest_notify(void *req, hid_t connector_id, H5VL_request_notify_t cb,
+ void *ctx)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE4("e", "*xix*x", req, connector_id, cb, ctx);
+
+ /* Get class pointer */
+ 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__request_notify(req, cls, cb, ctx) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "unable to register notify callback for request")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLrequest_notify() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__request_cancel
+ *
+ * Purpose: Cancels an asynchronous request through the VOL
+ *
+ * Note: Releases the request, if connector callback succeeds
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__request_cancel(void *req, const H5VL_class_t *cls)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity check */
+ HDassert(req);
+ HDassert(cls);
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->request_cls.cancel)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'async cancel' method")
+
+ /* Call the corresponding VOL callback */
+ if((cls->request_cls.cancel)(req) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "request cancel failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__request_cancel() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_request_cancel
+ *
+ * Purpose: Cancels an asynchronous request through the VOL
+ *
+ * Note: Releases the request, if connector callback succeeds
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_request_cancel(const H5VL_object_t *vol_obj)
+{
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check */
+ HDassert(vol_obj);
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 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__request_cancel(vol_obj->data, vol_obj->connector->cls) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "request cancel 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_request_cancel() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLrequest_cancel
+ *
+ * Purpose: Cancels a request
+ *
+ * Note: Releases the request, if connector callback succeeds
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLrequest_cancel(void *req, hid_t connector_id)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE2("e", "*xi", req, connector_id);
+
+ /* Get class pointer */
+ 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__request_cancel(req, cls) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "unable to cancel request")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLrequest_cancel() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__request_specific
+ *
+ * Purpose: Specific operation on asynchronous request through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__request_specific(void *req, const H5VL_class_t *cls,
+ H5VL_request_specific_t specific_type, va_list arguments)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity check */
+ HDassert(req);
+ HDassert(cls);
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->request_cls.specific)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'async specific' method")
+
+ /* Call the corresponding VOL callback */
+ if((ret_value = (cls->request_cls.specific)(req, specific_type, arguments)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute asynchronous request specific callback")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__request_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_request_specific
+ *
+ * Purpose: Specific operation on asynchronous request through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_request_specific(const H5VL_object_t *vol_obj,
+ H5VL_request_specific_t specific_type, ...)
+{
+ va_list arguments; /* Argument list passed from the API call */
+ hbool_t arg_started = FALSE; /* Whether the va_list has been started */
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check */
+ HDassert(vol_obj);
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL wrapper info")
+ vol_wrapper_set = TRUE;
+
+ /* Call the corresponding internal VOL routine */
+ HDva_start(arguments, specific_type);
+ arg_started = TRUE;
+ if((ret_value = H5VL__request_specific(vol_obj->data, vol_obj->connector->cls, specific_type, arguments)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute asynchronous request specific callback")
+
+done:
+ /* End access to the va_list, if we started it */
+ if(arg_started)
+ HDva_end(arguments);
+
+ /* 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_request_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLrequest_specific
+ *
+ * Purpose: Performs a connector-specific operation on an asynchronous request
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLrequest_specific(void *req, hid_t connector_id, H5VL_request_specific_t specific_type,
+ va_list arguments)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE4("e", "*xiVrx", req, connector_id, specific_type, arguments);
+
+ /* Get class pointer */
+ 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((ret_value = H5VL__request_specific(req, cls, specific_type, arguments)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute asynchronous request specific callback")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLrequest_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__request_optional
+ *
+ * Purpose: Optional operation specific to connectors.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__request_optional(void *req, const H5VL_class_t *cls, va_list arguments)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity check */
+ HDassert(req);
+ HDassert(cls);
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->request_cls.optional)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'async optional' method")
+
+ /* Call the corresponding VOL callback */
+ if((ret_value = (cls->request_cls.optional)(req, arguments)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute asynchronous request optional callback")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__request_optional() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_request_optional
+ *
+ * Purpose: Optional operation specific to connectors.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_request_optional(const H5VL_object_t *vol_obj, ...)
+{
+ va_list arguments; /* Argument list passed from the API call */
+ hbool_t arg_started = FALSE; /* Whether the va_list has been started */
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check */
+ HDassert(vol_obj);
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL wrapper info")
+ vol_wrapper_set = TRUE;
+
+ /* Call the corresponding internal VOL routine */
+ HDva_start(arguments, vol_obj);
+ arg_started = TRUE;
+ if((ret_value = H5VL__request_optional(vol_obj->data, vol_obj->connector->cls, arguments)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute asynchronous request optional callback")
+
+done:
+ /* End access to the va_list, if we started it */
+ if(arg_started)
+ HDva_end(arguments);
+
+ /* 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_request_optional() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLrequest_optional
+ *
+ * Purpose: Performs an optional connector-specific operation on an asynchronous request
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLrequest_optional(void *req, hid_t connector_id, va_list arguments)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE3("e", "*xix", req, connector_id, arguments);
+
+ /* Get class pointer */
+ 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((ret_value = H5VL__request_optional(req, cls, arguments)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute asynchronous request optional callback")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLrequest_optional() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__request_free
+ *
+ * Purpose: Frees an asynchronous request through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__request_free(void *req, const H5VL_class_t *cls)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity check */
+ HDassert(req);
+ HDassert(cls);
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->request_cls.free)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'async free' method")
+
+ /* Call the corresponding VOL callback */
+ if((cls->request_cls.free)(req) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "request free failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__request_free() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_request_free
+ *
+ * Purpose: Frees an asynchronous request through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_request_free(const H5VL_object_t *vol_obj)
+{
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check */
+ HDassert(vol_obj);
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL wrapper info")
+ vol_wrapper_set = TRUE;
+
+ /* Call the corresponding VOL callback */
+ if(H5VL__request_free(vol_obj->data, vol_obj->connector->cls) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "request free 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_request_free() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLrequest_free
+ *
+ * Purpose: Frees a request
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLrequest_free(void *req, hid_t connector_id)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE2("e", "*xi", req, connector_id);
+
+ /* Get class pointer */
+ 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__request_free(req, cls) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "unable to free request")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLrequest_free() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__blob_put
+ *
+ * Purpose: Put a blob through the VOL
+ *
+ * Return: SUCCEED / FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__blob_put(void *obj, const H5VL_class_t *cls, const void *buf, size_t size,
+ void *blob_id, void *ctx)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity check */
+ HDassert(obj);
+ HDassert(cls);
+ HDassert(size == 0 || buf);
+ HDassert(blob_id);
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->blob_cls.put)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'blob put' method")
+
+ /* Call the corresponding VOL callback */
+ if((cls->blob_cls.put)(obj, buf, size, blob_id, ctx) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "blob put callback failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__blob_put() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_blob_put
+ *
+ * Purpose: Put a blob through the VOL
+ *
+ * Return: SUCCEED / FAIL
+ *
+ * Programmer: Quincey Koziol
+ * Wednesday, August 21, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_blob_put(const H5VL_object_t *vol_obj, const void *buf, size_t size,
+ void *blob_id, void *ctx)
+{
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check */
+ HDassert(vol_obj);
+ HDassert(size == 0 || buf);
+ HDassert(blob_id);
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL wrapper info")
+ vol_wrapper_set = TRUE;
+
+ /* Call the corresponding VOL callback */
+ if(H5VL__blob_put(vol_obj->data, vol_obj->connector->cls, buf, size, blob_id, ctx) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "blob put 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_blob_put() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLblob_put
+ *
+ * Purpose: Put a blob through the VOL
+ *
+ * Return: SUCCEED / FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLblob_put(void *obj, hid_t connector_id, const void *buf, size_t size,
+ void *blob_id, void *ctx)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE6("e", "*xi*xz*x*x", obj, connector_id, buf, size, blob_id, ctx);
+
+ /* Get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object")
+ 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 VOL callback */
+ if(H5VL__blob_put(obj, cls, buf, size, blob_id, ctx) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "blob put failed")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLblob_put() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__blob_get
+ *
+ * Purpose: Get a blob through the VOL
+ *
+ * Return: SUCCEED / FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__blob_get(void *obj, const H5VL_class_t *cls, const void *blob_id,
+ void *buf, size_t *size, void *ctx)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity check */
+ HDassert(obj);
+ HDassert(cls);
+ HDassert(blob_id);
+ HDassert(size || buf);
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->blob_cls.get)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'blob get' method")
+
+ /* Call the corresponding VOL callback */
+ if((cls->blob_cls.get)(obj, blob_id, buf, size, ctx) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "blob get callback failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__blob_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_blob_get
+ *
+ * Purpose: Get a blob through the VOL
+ *
+ * Return: SUCCEED / FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_blob_get(const H5VL_object_t *vol_obj, const void *blob_id, void *buf,
+ size_t *size, void *ctx)
+{
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check */
+ HDassert(vol_obj);
+ HDassert(blob_id);
+ HDassert(size || buf);
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL wrapper info")
+ vol_wrapper_set = TRUE;
+
+ /* Call the corresponding VOL callback */
+ if(H5VL__blob_get(vol_obj->data, vol_obj->connector->cls, blob_id, buf, size, ctx) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "blob get 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_blob_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLblob_get
+ *
+ * Purpose: Get a blob through the VOL
+ *
+ * Return: SUCCEED / FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLblob_get(void *obj, hid_t connector_id, const void *blob_id, void *buf,
+ size_t *size, void *ctx)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE6("e", "*xi*x*x*z*x", obj, connector_id, blob_id, buf, size, ctx);
+
+ /* Get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object")
+ 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 VOL callback */
+ if(H5VL__blob_get(obj, cls, blob_id, buf, size, ctx) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "blob get failed")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLblob_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__blob_specific
+ *
+ * Purpose: Specific operation on blobs through the VOL
+ *
+ * Return: SUCCEED / FAIL
+ *
+ * Programmer: Quincey Koziol
+ * Saturday, August 17, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__blob_specific(void *obj, const H5VL_class_t *cls, void *blob_id,
+ H5VL_blob_specific_t specific_type, va_list arguments)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity check */
+ HDassert(obj);
+ HDassert(cls);
+ HDassert(blob_id);
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->blob_cls.specific)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'blob specific' method")
+
+ /* Call the corresponding VOL callback */
+ if((cls->blob_cls.specific)(obj, blob_id, specific_type, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute blob specific callback")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__blob_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_blob_specific
+ *
+ * Purpose: Specific operation on blobs through the VOL
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_blob_specific(const H5VL_object_t *vol_obj, void *blob_id,
+ H5VL_blob_specific_t specific_type, ...)
+{
+ va_list arguments; /* Argument list passed from the API call */
+ hbool_t arg_started = FALSE; /* Whether the va_list has been started */
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check */
+ HDassert(vol_obj);
+ HDassert(blob_id);
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL wrapper info")
+ vol_wrapper_set = TRUE;
+
+ /* Call the corresponding internal VOL routine */
+ HDva_start(arguments, specific_type);
+ arg_started = TRUE;
+ if((ret_value = H5VL__blob_specific(vol_obj->data, vol_obj->connector->cls, blob_id, specific_type, arguments)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute blob specific callback")
+
+done:
+ /* End access to the va_list, if we started it */
+ if(arg_started)
+ HDva_end(arguments);
+
+ /* 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_blob_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLblob_specific
+ *
+ * Purpose: Specific operation on blobs through the VOL
+ *
+ * Return: SUCCEED / FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLblob_specific(void *obj, hid_t connector_id, void *blob_id,
+ H5VL_blob_specific_t specific_type, va_list arguments)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE5("e", "*xi*xVBx", obj, connector_id, blob_id, specific_type, arguments);
+
+ /* Get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object")
+ 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 VOL callback */
+ if(H5VL__blob_specific(obj, cls, blob_id, specific_type, arguments) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "blob specific operation failed")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLblob_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__optional
+ *
+ * Purpose: Optional operation specific to connectors.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__optional(void *obj, const H5VL_class_t *cls, hid_t dxpl_id,
+ void **req, va_list arguments)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check if the corresponding VOL callback exists */
+ if(NULL == cls->optional)
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'optional' method")
+
+ /* Call the corresponding VOL callback */
+ if((ret_value = (cls->optional)(obj, dxpl_id, req, arguments)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, ret_value, "unable to execute optional callback")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__optional() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_optional
+ *
+ * Purpose: Optional operation specific to connectors.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_optional(const H5VL_object_t *vol_obj, hid_t dxpl_id,
+ void **req, ...)
+{
+ va_list arguments; /* Argument list passed from the API call */
+ hbool_t arg_started = FALSE; /* Whether the va_list has been started */
+ hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Set wrapper info in API context */
+ if(H5VL_set_vol_wrapper(vol_obj->data, vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL wrapper info")
+ vol_wrapper_set = TRUE;
+
+ /* Call the corresponding internal VOL routine */
+ HDva_start(arguments, req);
+ arg_started = TRUE;
+ if((ret_value = H5VL__optional(vol_obj->data, vol_obj->connector->cls, dxpl_id, req, arguments)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, FAIL, "unable to execute optional callback")
+
+done:
+ /* End access to the va_list, if we started it */
+ if(arg_started)
+ HDva_end(arguments);
+
+ /* Reset object wrapping info in API context */
+ if(vol_wrapper_set && H5VL_reset_vol_wrapper() < 0)
+ HDONE_ERROR(H5E_VOL, H5E_CANTRESET, ret_value, "can't reset VOL wrapper info")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_optional() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VLoptional
+ *
+ * Purpose: Performs an optional connector-specific operation
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VLoptional(void *obj, hid_t connector_id, hid_t dxpl_id, void **req,
+ va_list arguments)
+{
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API_NOINIT
+ H5TRACE5("e", "*xii**xx", obj, connector_id, dxpl_id, req, arguments);
+
+ /* Check args and get class pointer */
+ if(NULL == obj)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object")
+ 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((ret_value = H5VL__optional(obj, cls, dxpl_id, req, arguments)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPERATE, ret_value, "unable to execute optional callback")
+
+done:
+ FUNC_LEAVE_API_NOINIT(ret_value)
+} /* end H5VLoptional() */
+
diff --git a/src/H5VLconnector.h b/src/H5VLconnector.h
new file mode 100644
index 0000000..3597751
--- /dev/null
+++ b/src/H5VLconnector.h
@@ -0,0 +1,449 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * This file contains public declarations for authoring VOL connectors.
+ */
+
+#ifndef _H5VLconnector_H
+#define _H5VLconnector_H
+
+/* Public headers needed by this file */
+#include "H5public.h" /* Generic Functions */
+#include "H5Apublic.h" /* Attributes */
+#include "H5ESpublic.h" /* Event Stack */
+#include "H5Fpublic.h" /* Files */
+#include "H5Ipublic.h" /* IDs */
+#include "H5Lpublic.h" /* Links */
+#include "H5Opublic.h" /* Objects */
+#include "H5Rpublic.h" /* References */
+#include "H5VLpublic.h" /* Virtual Object Layer */
+
+
+/*****************/
+/* Public Macros */
+/*****************/
+
+/* Capability flags for connector */
+#define H5VL_CAP_FLAG_NONE 0 /* No special connector capabilities */
+#define H5VL_CAP_FLAG_THREADSAFE 0x01 /* Connector is threadsafe */
+
+/* Container info version */
+#define H5VL_CONTAINER_INFO_VERSION 0x01 /* Container info struct version */
+
+/* The maximum size allowed for blobs */
+#define H5VL_MAX_BLOB_ID_SIZE (16) /* Allow for 128-bits blob IDs */
+
+/* The maximum size allowed for tokens */
+#define H5VL_MAX_TOKEN_SIZE (16) /* Allow for 128-bits tokens */
+
+/*******************/
+/* Public Typedefs */
+/*******************/
+
+/* type for tokens. Token are unique and permanent identifiers that are
+ * used to reference HDF5 objects. */
+typedef unsigned char H5VL_token_t[H5VL_MAX_TOKEN_SIZE];
+
+/* types for attribute GET callback */
+typedef enum H5VL_attr_get_t {
+ H5VL_ATTR_GET_ACPL, /* creation property list */
+ H5VL_ATTR_GET_INFO, /* info */
+ H5VL_ATTR_GET_NAME, /* access property list */
+ H5VL_ATTR_GET_SPACE, /* dataspace */
+ H5VL_ATTR_GET_STORAGE_SIZE, /* storage size */
+ H5VL_ATTR_GET_TYPE /* datatype */
+} H5VL_attr_get_t;
+
+/* types for attribute SPECFIC callback */
+typedef enum H5VL_attr_specific_t {
+ H5VL_ATTR_DELETE, /* H5Adelete(_by_name/idx) */
+ H5VL_ATTR_EXISTS, /* H5Aexists(_by_name) */
+ H5VL_ATTR_ITER, /* H5Aiterate(_by_name) */
+ H5VL_ATTR_RENAME /* H5Arename(_by_name) */
+} H5VL_attr_specific_t;
+
+/* types for dataset GET callback */
+typedef enum H5VL_dataset_get_t {
+ H5VL_DATASET_GET_DAPL, /* access property list */
+ H5VL_DATASET_GET_DCPL, /* creation property list */
+ H5VL_DATASET_GET_OFFSET, /* offset */
+ H5VL_DATASET_GET_SPACE, /* dataspace */
+ H5VL_DATASET_GET_SPACE_STATUS, /* space status */
+ H5VL_DATASET_GET_STORAGE_SIZE, /* storage size */
+ H5VL_DATASET_GET_TYPE /* datatype */
+} H5VL_dataset_get_t;
+
+/* types for dataset SPECFIC callback */
+typedef enum H5VL_dataset_specific_t {
+ H5VL_DATASET_SET_EXTENT, /* H5Dset_extent */
+ H5VL_DATASET_FLUSH, /* H5Dflush */
+ H5VL_DATASET_REFRESH /* H5Drefresh */
+} H5VL_dataset_specific_t;
+
+/* types for datatype GET callback */
+typedef enum H5VL_datatype_get_t {
+ H5VL_DATATYPE_GET_BINARY, /* get serialized form of transient type */
+ H5VL_DATATYPE_GET_TCPL /* datatype creation property list */
+} H5VL_datatype_get_t;
+
+/* types for datatype SPECFIC callback */
+typedef enum H5VL_datatype_specific_t {
+ H5VL_DATATYPE_FLUSH,
+ H5VL_DATATYPE_REFRESH
+} H5VL_datatype_specific_t;
+
+/* types for file GET callback */
+typedef enum H5VL_file_get_t {
+ H5VL_FILE_GET_CONT_INFO, /* file get container info */
+ H5VL_FILE_GET_FAPL, /* file access property list */
+ H5VL_FILE_GET_FCPL, /* file creation property list */
+ H5VL_FILE_GET_FILENO, /* file number */
+ H5VL_FILE_GET_INTENT, /* file intent */
+ H5VL_FILE_GET_NAME, /* file name */
+ H5VL_FILE_GET_OBJ_COUNT, /* object count in file */
+ H5VL_FILE_GET_OBJ_IDS /* object ids in file */
+} H5VL_file_get_t;
+
+/* types for file SPECIFIC callback */
+typedef enum H5VL_file_specific_t {
+ H5VL_FILE_FLUSH, /* Flush file */
+ H5VL_FILE_REOPEN, /* Reopen the file */
+ H5VL_FILE_MOUNT, /* Mount a file */
+ H5VL_FILE_UNMOUNT, /* Unmount a file */
+ H5VL_FILE_IS_ACCESSIBLE, /* Check if a file is accessible */
+ H5VL_FILE_DELETE /* Delete a file */
+} H5VL_file_specific_t;
+
+/* types for group GET callback */
+typedef enum H5VL_group_get_t {
+ H5VL_GROUP_GET_GCPL, /* group creation property list */
+ H5VL_GROUP_GET_INFO /* group info */
+} H5VL_group_get_t;
+
+/* types for group SPECFIC callback */
+typedef enum H5VL_group_specific_t {
+ H5VL_GROUP_FLUSH,
+ H5VL_GROUP_REFRESH
+} H5VL_group_specific_t;
+
+/* link create types for VOL */
+typedef enum H5VL_link_create_type_t {
+ H5VL_LINK_CREATE_HARD,
+ H5VL_LINK_CREATE_SOFT,
+ H5VL_LINK_CREATE_UD
+} H5VL_link_create_type_t;
+
+/* types for link GET callback */
+typedef enum H5VL_link_get_t {
+ H5VL_LINK_GET_INFO, /* link info */
+ H5VL_LINK_GET_NAME, /* link name */
+ H5VL_LINK_GET_VAL /* link value */
+} H5VL_link_get_t;
+
+/* types for link SPECIFIC callback */
+typedef enum H5VL_link_specific_t {
+ H5VL_LINK_DELETE, /* H5Ldelete(_by_idx) */
+ H5VL_LINK_EXISTS, /* link existence */
+ H5VL_LINK_ITER /* H5Literate/visit(_by_name) */
+} H5VL_link_specific_t;
+
+/* types for object GET callback */
+typedef enum H5VL_object_get_t {
+ H5VL_OBJECT_GET_NAME, /* object name */
+ H5VL_OBJECT_GET_TYPE /* object type */
+} H5VL_object_get_t;
+
+/* types for object SPECIFIC callback */
+typedef enum H5VL_object_specific_t {
+ H5VL_OBJECT_CHANGE_REF_COUNT, /* H5Oincr/decr_refcount */
+ H5VL_OBJECT_EXISTS, /* H5Oexists_by_name */
+ H5VL_OBJECT_LOOKUP, /* Lookup object */
+ H5VL_OBJECT_VISIT, /* H5Ovisit(_by_name) */
+ H5VL_OBJECT_FLUSH, /* H5{D|G|O|T}flush */
+ H5VL_OBJECT_REFRESH /* H5{D|G|O|T}refresh */
+} H5VL_object_specific_t;
+
+/* types for async request SPECIFIC callback */
+typedef enum H5VL_request_specific_t {
+ H5VL_REQUEST_WAITANY, /* Wait until any request completes */
+ H5VL_REQUEST_WAITSOME, /* Wait until at least one requesst completes */
+ H5VL_REQUEST_WAITALL /* Wait until all requests complete */
+} H5VL_request_specific_t;
+
+/* types for 'blob' SPECIFIC callback */
+typedef enum H5VL_blob_specific_t {
+ H5VL_BLOB_DELETE, /* Delete a blob (by ID) */
+ H5VL_BLOB_GETSIZE, /* Get size of blob */
+ H5VL_BLOB_ISNULL, /* Check if a blob ID is "null" */
+ H5VL_BLOB_SETNULL /* Set a blob ID to the connector's "null" blob ID value */
+} H5VL_blob_specific_t;
+
+/* Types for different ways that objects are located in an HDF5 container */
+typedef enum H5VL_loc_type_t {
+ H5VL_OBJECT_BY_SELF,
+ H5VL_OBJECT_BY_NAME,
+ H5VL_OBJECT_BY_IDX,
+ H5VL_OBJECT_BY_TOKEN
+} H5VL_loc_type_t;
+
+typedef struct H5VL_loc_by_name {
+ const char *name;
+ hid_t lapl_id;
+} H5VL_loc_by_name_t;
+
+typedef struct H5VL_loc_by_idx {
+ const char *name;
+ H5_index_t idx_type;
+ H5_iter_order_t order;
+ hsize_t n;
+ hid_t lapl_id;
+} H5VL_loc_by_idx_t;
+
+typedef struct H5VL_loc_by_token {
+ void *token;
+} H5VL_loc_by_token_t;
+
+/* Structure to hold parameters for object locations.
+ * Either: BY_SELF, BY_NAME, BY_IDX, BY_TOKEN
+ *
+ * Note: Leave loc_by_token as the first union member so we
+ * can perform the simplest initialization of the struct
+ * without raising warnings.
+ *
+ * Note: BY_SELF requires no union members.
+ */
+typedef struct H5VL_loc_params_t {
+ H5I_type_t obj_type;
+ H5VL_loc_type_t type;
+ union {
+ H5VL_loc_by_token_t loc_by_token;
+ H5VL_loc_by_name_t loc_by_name;
+ H5VL_loc_by_idx_t loc_by_idx;
+ } loc_data;
+} H5VL_loc_params_t;
+
+/* Info for H5VL_FILE_GET_CONT_INFO */
+typedef struct H5VL_file_cont_info_t {
+ unsigned version; /* version information (keep first) */
+ uint64_t feature_flags; /* Container feature flags */
+ /* (none currently defined) */
+ size_t token_size; /* Size of tokens */
+ size_t blob_id_size; /* Size of blob IDs */
+} H5VL_file_cont_info_t;
+
+/* VOL connector info fields & callbacks */
+typedef struct H5VL_info_class_t {
+ size_t size; /* Size of the VOL info */
+ void * (*copy)(const void *info); /* Callback to create a copy of the VOL info */
+ herr_t (*cmp)(int *cmp_value, const void *info1, const void *info2); /* Callback to compare VOL info */
+ herr_t (*free)(void *info); /* Callback to release a VOL info */
+ herr_t (*to_str)(const void *info, char **str); /* Callback to serialize connector's info into a string */
+ herr_t (*from_str)(const char *str, void **info); /* Callback to deserialize a string into connector's info */
+} H5VL_info_class_t;
+
+/* VOL object wrap / retrieval callbacks */
+/* (These only need to be implemented by "pass through" VOL connectors) */
+typedef struct H5VL_wrap_class_t {
+ void * (*get_object)(const void *obj); /* Callback to retrieve underlying object */
+ herr_t (*get_wrap_ctx)(const void *obj, void **wrap_ctx); /* Callback to retrieve the object wrapping context for the connector */
+ void * (*wrap_object)(void *obj, H5I_type_t obj_type, void *wrap_ctx); /* Callback to wrap a library object */
+ void * (*unwrap_object)(void *obj); /* Callback to unwrap a library object */
+ herr_t (*free_wrap_ctx)(void *wrap_ctx); /* Callback to release the object wrapping context for the connector */
+} H5VL_wrap_class_t;
+
+/* H5A routines */
+typedef struct H5VL_attr_class_t {
+ void *(*create)(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_name,
+ hid_t type_id, hid_t space_id, hid_t acpl_id, hid_t aapl_id,
+ hid_t dxpl_id, void **req);
+ void *(*open)(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_name,
+ hid_t aapl_id, hid_t dxpl_id, void **req);
+ herr_t (*read)(void *attr, hid_t mem_type_id, void *buf, hid_t dxpl_id, void **req);
+ herr_t (*write)(void *attr, hid_t mem_type_id, const void *buf, hid_t dxpl_id, void **req);
+ herr_t (*get)(void *obj, H5VL_attr_get_t get_type, hid_t dxpl_id, void **req, va_list arguments);
+ herr_t (*specific)(void *obj, const H5VL_loc_params_t *loc_params, H5VL_attr_specific_t specific_type,
+ hid_t dxpl_id, void **req, va_list arguments);
+ herr_t (*optional)(void *obj, hid_t dxpl_id, void **req, va_list arguments);
+ herr_t (*close) (void *attr, hid_t dxpl_id, void **req);
+} H5VL_attr_class_t;
+
+/* H5D routines */
+typedef struct H5VL_dataset_class_t {
+ void *(*create)(void *obj, const H5VL_loc_params_t *loc_params, const char *name,
+ hid_t lcpl_id, 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 xfer_plist_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 xfer_plist_id, const void * buf, void **req);
+ herr_t (*get)(void *obj, H5VL_dataset_get_t get_type, hid_t dxpl_id, void **req, va_list arguments);
+ herr_t (*specific)(void *obj, H5VL_dataset_specific_t specific_type,
+ hid_t dxpl_id, void **req, va_list arguments);
+ herr_t (*optional)(void *obj, hid_t dxpl_id, void **req, va_list arguments);
+ herr_t (*close) (void *dset, hid_t dxpl_id, void **req);
+} H5VL_dataset_class_t;
+
+/* H5T routines*/
+typedef struct H5VL_datatype_class_t {
+ void *(*commit)(void *obj, const H5VL_loc_params_t *loc_params, const char *name, hid_t type_id,
+ hid_t lcpl_id, hid_t tcpl_id, hid_t tapl_id, hid_t dxpl_id, void **req);
+ void *(*open)(void *obj, const H5VL_loc_params_t *loc_params, const char * name,
+ hid_t tapl_id, hid_t dxpl_id, void **req);
+ herr_t (*get) (void *obj, H5VL_datatype_get_t get_type, hid_t dxpl_id, void **req, va_list arguments);
+ herr_t (*specific)(void *obj, H5VL_datatype_specific_t specific_type,
+ hid_t dxpl_id, void **req, va_list arguments);
+ herr_t (*optional)(void *obj, hid_t dxpl_id, void **req, va_list arguments);
+ herr_t (*close) (void *dt, hid_t dxpl_id, void **req);
+} H5VL_datatype_class_t;
+
+/* H5F routines */
+typedef struct H5VL_file_class_t {
+ void *(*create)(const char *name, unsigned flags, hid_t fcpl_id,
+ hid_t fapl_id, hid_t dxpl_id, void **req);
+ void *(*open)(const char *name, unsigned flags, hid_t fapl_id, hid_t dxpl_id, void **req);
+ herr_t (*get)(void *obj, H5VL_file_get_t get_type, hid_t dxpl_id, void **req, va_list arguments);
+ herr_t (*specific)(void *obj, H5VL_file_specific_t specific_type,
+ hid_t dxpl_id, void **req, va_list arguments);
+ herr_t (*optional)(void *obj, hid_t dxpl_id, void **req, va_list arguments);
+ herr_t (*close) (void *file, hid_t dxpl_id, void **req);
+} H5VL_file_class_t;
+
+/* H5G routines */
+typedef struct H5VL_group_class_t {
+ void *(*create)(void *obj, const H5VL_loc_params_t *loc_params, const char *name,
+ hid_t lcpl_id, hid_t gcpl_id, hid_t gapl_id, hid_t dxpl_id, void **req);
+ void *(*open)(void *obj, const H5VL_loc_params_t *loc_params, const char *name,
+ hid_t gapl_id, hid_t dxpl_id, void **req);
+ herr_t (*get)(void *obj, H5VL_group_get_t get_type, hid_t dxpl_id, void **req, va_list arguments);
+ herr_t (*specific)(void *obj, H5VL_group_specific_t specific_type,
+ hid_t dxpl_id, void **req, va_list arguments);
+ herr_t (*optional)(void *obj, hid_t dxpl_id, void **req, va_list arguments);
+ herr_t (*close) (void *grp, hid_t dxpl_id, void **req);
+} H5VL_group_class_t;
+
+/* H5L routines */
+typedef struct H5VL_link_class_t {
+ herr_t (*create)(H5VL_link_create_type_t create_type, void *obj, const H5VL_loc_params_t *loc_params,
+ hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id, void **req, va_list arguments);
+ herr_t (*copy)(void *src_obj, const H5VL_loc_params_t *loc_params1,
+ void *dst_obj, const H5VL_loc_params_t *loc_params2,
+ hid_t lcpl, hid_t lapl, hid_t dxpl_id, void **req);
+ herr_t (*move)(void *src_obj, const H5VL_loc_params_t *loc_params1,
+ void *dst_obj, const H5VL_loc_params_t *loc_params2,
+ hid_t lcpl, hid_t lapl, hid_t dxpl_id, void **req);
+ herr_t (*get)(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_get_t get_type,
+ hid_t dxpl_id, void **req, va_list arguments);
+ herr_t (*specific)(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_specific_t specific_type,
+ hid_t dxpl_id, void **req, va_list arguments);
+ herr_t (*optional)(void *obj, hid_t dxpl_id, void **req, va_list arguments);
+} H5VL_link_class_t;
+
+/* H5O routines */
+typedef struct H5VL_object_class_t {
+ void *(*open)(void *obj, const H5VL_loc_params_t *loc_params, H5I_type_t *opened_type,
+ hid_t dxpl_id, void **req);
+ herr_t (*copy)(void *src_obj, const H5VL_loc_params_t *loc_params1, const char *src_name,
+ void *dst_obj, const H5VL_loc_params_t *loc_params2, const char *dst_name,
+ hid_t ocpypl_id, hid_t lcpl_id, hid_t dxpl_id, void **req);
+ herr_t (*get)(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_get_t get_type,
+ hid_t dxpl_id, void **req, va_list arguments);
+ herr_t (*specific)(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_specific_t specific_type,
+ hid_t dxpl_id, void **req, va_list arguments);
+ herr_t (*optional)(void *obj, hid_t dxpl_id, void **req, va_list arguments);
+} H5VL_object_class_t;
+
+/* Asynchronous request 'notify' callback */
+typedef herr_t (*H5VL_request_notify_t)(void *ctx, H5ES_status_t status);
+
+/* Async request operation routines */
+typedef struct H5VL_request_class_t {
+ herr_t (*wait)(void *req, uint64_t timeout, H5ES_status_t *status);
+ herr_t (*notify)(void *req, H5VL_request_notify_t cb, void *ctx);
+ herr_t (*cancel)(void *req);
+ herr_t (*specific)(void *req, H5VL_request_specific_t specific_type, va_list arguments);
+ herr_t (*optional)(void *req, va_list arguments);
+ herr_t (*free)(void *req);
+} H5VL_request_class_t;
+
+/* 'blob' routines */
+typedef struct H5VL_blob_class_t {
+ herr_t (*put)(void *obj, const void *buf, size_t size, void *blob_id, void *ctx);
+ herr_t (*get)(void *obj, const void *blob_id, void *buf, size_t *size, void *ctx);
+ herr_t (*specific)(void *obj, void *blob_id, H5VL_blob_specific_t specific_type, va_list arguments);
+ herr_t (*optional)(void *obj, void *blob_id, va_list arguments);
+} H5VL_blob_class_t;
+
+/*
+ * VOL connector identifiers. Values 0 through 255 are for connectors defined
+ * by the HDF5 library. Values 256 through 511 are available for testing new
+ * filters. Subsequent values should be obtained from the HDF5 development
+ * team at help@hdfgroup.org.
+ */
+typedef int H5VL_class_value_t;
+
+/* Class information for each VOL connector */
+typedef struct H5VL_class_t {
+ /* Overall connector fields & callbacks */
+ unsigned int version; /* VOL connector class struct version # */
+ H5VL_class_value_t value; /* Value to identify connector */
+ const char *name; /* Connector name (MUST be unique!) */
+ unsigned cap_flags; /* Capability flags for connector */
+ herr_t (*initialize)(hid_t vipl_id); /* Connector initialization callback */
+ herr_t (*terminate)(void); /* Connector termination callback */
+
+ /* VOL framework */
+ H5VL_info_class_t info_cls; /* VOL info fields & callbacks */
+ H5VL_wrap_class_t wrap_cls; /* VOL object wrap / retrieval callbacks */
+
+ /* Data Model */
+ H5VL_attr_class_t attr_cls; /* Attribute (H5A*) class callbacks */
+ H5VL_dataset_class_t dataset_cls; /* Dataset (H5D*) class callbacks */
+ H5VL_datatype_class_t datatype_cls; /* Datatype (H5T*) class callbacks */
+ H5VL_file_class_t file_cls; /* File (H5F*) class callbacks */
+ H5VL_group_class_t group_cls; /* Group (H5G*) class callbacks */
+ H5VL_link_class_t link_cls; /* Link (H5L*) class callbacks */
+ H5VL_object_class_t object_cls; /* Object (H5O*) class callbacks */
+
+ /* Infrastructure / Services */
+ H5VL_request_class_t request_cls; /* Asynchronous request class callbacks */
+ H5VL_blob_class_t blob_cls; /* 'blob' callbacks */
+
+ /* Catch-all */
+ herr_t (*optional)(void *obj, hid_t dxpl_id, void **req, va_list arguments); /* Optional callback */
+} H5VL_class_t;
+
+
+/********************/
+/* Public Variables */
+/********************/
+
+
+/*********************/
+/* Public Prototypes */
+/*********************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Helper routines for VOL connector authors */
+H5_DLL void *H5VLobject(hid_t obj_id);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _H5VLconnector_H */
+
diff --git a/src/H5VLconnector_passthru.h b/src/H5VLconnector_passthru.h
new file mode 100644
index 0000000..d0d73d2
--- /dev/null
+++ b/src/H5VLconnector_passthru.h
@@ -0,0 +1,175 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * This file contains public declarations for authoring VOL connectors
+ * which act as "passthrough" connectors that forward their API calls to
+ * an underlying connector.
+ *
+ * An example of this might be a logging connector, which creates log messages
+ * and then passes the call on to an underlying VOL connector.
+ *
+ * The functionality required to implement such a connector is specialized
+ * and non-trivial so it has been split into this header in an effort to keep
+ * the H5VLconnector.h header easier to understand.
+ */
+
+#ifndef _H5VLconnector_passthru_H
+#define _H5VLconnector_passthru_H
+
+/* Public headers needed by this file */
+#include "H5public.h" /* Generic Functions */
+#include "H5Ipublic.h" /* IDs */
+#include "H5VLpublic.h" /* Virtual Object Layer */
+
+/* Semi-public headers mainly for VOL connector authors */
+#include "H5VLconnector.h"
+
+
+/*****************/
+/* Public Macros */
+/*****************/
+
+/*******************/
+/* Public Typedefs */
+/*******************/
+
+/********************/
+/* Public Variables */
+/********************/
+
+/*********************/
+/* Public Prototypes */
+/*********************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Helper routines for VOL connector authors */
+H5_DLL herr_t H5VLcmp_connector_cls(int *cmp, hid_t connector_id1, hid_t connector_id2);
+H5_DLL hid_t H5VLwrap_register(void *obj, H5I_type_t type);
+H5_DLL herr_t H5VLretrieve_lib_state(void **state);
+H5_DLL herr_t H5VLrestore_lib_state(const void *state);
+H5_DLL herr_t H5VLreset_lib_state(void);
+H5_DLL herr_t H5VLfree_lib_state(void *state);
+
+/* Pass-through callbacks */
+H5_DLL void *H5VLget_object(void *obj, hid_t connector_id);
+H5_DLL herr_t H5VLget_wrap_ctx(void *obj, hid_t connector_id, void **wrap_ctx);
+H5_DLL void *H5VLwrap_object(void *obj, H5I_type_t obj_type, hid_t connector_id,
+ void *wrap_ctx);
+H5_DLL void *H5VLunwrap_object(void *obj, hid_t connector_id);
+H5_DLL herr_t H5VLfree_wrap_ctx(void *wrap_ctx, hid_t connector_id);
+
+/* Public wrappers for generic callbacks */
+H5_DLL herr_t H5VLinitialize(hid_t connector_id, hid_t vipl_id);
+H5_DLL herr_t H5VLterminate(hid_t connector_id);
+H5_DLL herr_t H5VLget_cap_flags(hid_t connector_id, unsigned *cap_flags);
+H5_DLL herr_t H5VLget_value(hid_t connector_id, H5VL_class_value_t *conn_value);
+
+/* Public wrappers for info fields and callbacks */
+H5_DLL herr_t H5VLcopy_connector_info(hid_t connector_id, void **dst_vol_info, void *src_vol_info);
+H5_DLL herr_t H5VLcmp_connector_info(int *cmp, hid_t connector_id, const void *info1,
+ const void *info2);
+H5_DLL herr_t H5VLfree_connector_info(hid_t connector_id, void *vol_info);
+H5_DLL herr_t H5VLconnector_info_to_str(const void *info, hid_t connector_id, char **str);
+H5_DLL herr_t H5VLconnector_str_to_info(const char *str, hid_t connector_id, void **info);
+
+/* Public wrappers for attribute callbacks */
+H5_DLL void *H5VLattr_create(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, const char *attr_name, hid_t type_id, hid_t space_id, hid_t acpl_id, hid_t aapl_id, hid_t dxpl_id, void **req);
+H5_DLL void *H5VLattr_open(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, const char *name, hid_t aapl_id, hid_t dxpl_id, void **req);
+H5_DLL herr_t H5VLattr_read(void *attr, hid_t connector_id, hid_t dtype_id, void *buf, hid_t dxpl_id, void **req);
+H5_DLL herr_t H5VLattr_write(void *attr, hid_t connector_id, hid_t dtype_id, const void *buf, hid_t dxpl_id, void **req);
+H5_DLL herr_t H5VLattr_get(void *obj, hid_t connector_id, H5VL_attr_get_t get_type, hid_t dxpl_id, void **req, va_list arguments);
+H5_DLL herr_t H5VLattr_specific(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, H5VL_attr_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments);
+H5_DLL herr_t H5VLattr_optional(void *obj, hid_t connector_id, hid_t dxpl_id, void **req, va_list arguments);
+H5_DLL herr_t H5VLattr_close(void *attr, hid_t connector_id, hid_t dxpl_id, void **req);
+
+/* Public wrappers for dataset callbacks */
+H5_DLL void *H5VLdataset_create(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, const char *name, hid_t lcpl_id, hid_t type_id, hid_t space_id, hid_t dcpl_id, 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_get(void *dset, hid_t connector_id, H5VL_dataset_get_t get_type, hid_t dxpl_id, void **req, va_list arguments);
+H5_DLL herr_t H5VLdataset_specific(void *obj, hid_t connector_id, H5VL_dataset_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments);
+H5_DLL herr_t H5VLdataset_optional(void *obj, hid_t connector_id, hid_t dxpl_id, void **req, va_list arguments);
+H5_DLL herr_t H5VLdataset_close(void *dset, hid_t connector_id, hid_t dxpl_id, void **req);
+
+/* Public wrappers for file callbacks */
+H5_DLL void *H5VLfile_create(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t dxpl_id, void **req);
+H5_DLL void *H5VLfile_open(const char *name, unsigned flags, hid_t fapl_id, hid_t dxpl_id, void **req);
+H5_DLL herr_t H5VLfile_get(void *file, hid_t connector_id, H5VL_file_get_t get_type, hid_t dxpl_id, void **req, va_list arguments);
+H5_DLL herr_t H5VLfile_specific(void *obj, hid_t connector_id, H5VL_file_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments);
+H5_DLL herr_t H5VLfile_optional(void *obj, hid_t connector_id, hid_t dxpl_id, void **req, va_list arguments);
+H5_DLL herr_t H5VLfile_close(void *file, hid_t connector_id, hid_t dxpl_id, void **req);
+
+/* Public wrappers for group callbacks */
+H5_DLL void *H5VLgroup_create(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, const char *name, hid_t lcpl_id, hid_t gcpl_id, hid_t gapl_id, hid_t dxpl_id, void **req);
+H5_DLL void *H5VLgroup_open(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, const char *name, hid_t gapl_id, hid_t dxpl_id, void **req);
+H5_DLL herr_t H5VLgroup_get(void *obj, hid_t connector_id, H5VL_group_get_t get_type, hid_t dxpl_id, void **req, va_list arguments);
+H5_DLL herr_t H5VLgroup_specific(void *obj, hid_t connector_id, H5VL_group_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments);
+H5_DLL herr_t H5VLgroup_optional(void *obj, hid_t connector_id, hid_t dxpl_id, void **req, va_list arguments);
+H5_DLL herr_t H5VLgroup_close(void *grp, hid_t connector_id, hid_t dxpl_id, void **req);
+
+/* Public wrappers for link callbacks */
+H5_DLL herr_t H5VLlink_create(H5VL_link_create_type_t create_type, void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id, void **req, va_list arguments);
+H5_DLL herr_t H5VLlink_copy(void *src_obj, const H5VL_loc_params_t *loc_params1,
+ void *dst_obj, const H5VL_loc_params_t *loc_params2, hid_t connector_id,
+ hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id, void **req);
+H5_DLL herr_t H5VLlink_move(void *src_obj, const H5VL_loc_params_t *loc_params1,
+ void *dst_obj, const H5VL_loc_params_t *loc_params2, hid_t connector_id,
+ hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id, void **req);
+H5_DLL herr_t H5VLlink_get(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, H5VL_link_get_t get_type, hid_t dxpl_id, void **req, va_list arguments);
+H5_DLL herr_t H5VLlink_specific(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, H5VL_link_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments);
+H5_DLL herr_t H5VLlink_optional(void *obj, hid_t connector_id, hid_t dxpl_id, void **req, va_list arguments);
+
+/* Public wrappers for object callbacks */
+H5_DLL void *H5VLobject_open(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, H5I_type_t *opened_type, hid_t dxpl_id, void **req);
+H5_DLL herr_t H5VLobject_copy(void *src_obj, const H5VL_loc_params_t *loc_params1, const char *src_name,
+ void *dst_obj, const H5VL_loc_params_t *loc_params2, const char *dst_name,
+ hid_t connector_id, hid_t ocpypl_id, hid_t lcpl_id, hid_t dxpl_id, void **req);
+H5_DLL herr_t H5VLobject_get(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, H5VL_object_get_t get_type, hid_t dxpl_id, void **req, va_list arguments);
+H5_DLL herr_t H5VLobject_specific(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, H5VL_object_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments);
+H5_DLL herr_t H5VLobject_optional(void *obj, hid_t connector_id, hid_t dxpl_id, void **req, va_list arguments);
+
+/* Public wrappers for named datatype callbacks */
+H5_DLL void *H5VLdatatype_commit(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, const char *name, hid_t type_id, hid_t lcpl_id, hid_t tcpl_id, hid_t tapl_id, hid_t dxpl_id, void **req);
+H5_DLL void *H5VLdatatype_open(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id, const char *name, hid_t tapl_id, hid_t dxpl_id, void **req);
+H5_DLL herr_t H5VLdatatype_get(void *dt, hid_t connector_id, H5VL_datatype_get_t get_type, hid_t dxpl_id, void **req, va_list arguments);
+H5_DLL herr_t H5VLdatatype_specific(void *obj, hid_t connector_id, H5VL_datatype_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments);
+H5_DLL herr_t H5VLdatatype_optional(void *obj, hid_t connector_id, hid_t dxpl_id, void **req, va_list arguments);
+H5_DLL herr_t H5VLdatatype_close(void *dt, hid_t connector_id, hid_t dxpl_id, void **req);
+
+/* Public wrappers for asynchronous request callbacks */
+H5_DLL herr_t H5VLrequest_wait(void *req, hid_t connector_id, uint64_t timeout, H5ES_status_t *status);
+H5_DLL herr_t H5VLrequest_notify(void *req, hid_t connector_id, H5VL_request_notify_t cb, void *ctx);
+H5_DLL herr_t H5VLrequest_cancel(void *req, hid_t connector_id);
+H5_DLL herr_t H5VLrequest_specific(void *req, hid_t connector_id, H5VL_request_specific_t specific_type, va_list arguments);
+H5_DLL herr_t H5VLrequest_optional(void *req, hid_t connector_id, va_list arguments);
+H5_DLL herr_t H5VLrequest_free(void *req, hid_t connector_id);
+
+/* Public wrappers for blob callbacks */
+H5_DLL herr_t H5VLblob_put(void *obj, hid_t connector_id, const void *buf, size_t size, void *blob_id, void *ctx);
+H5_DLL herr_t H5VLblob_get(void *obj, hid_t connector_id, const void *blob_id, void *buf, size_t *size, void *ctx);
+H5_DLL herr_t H5VLblob_specific(void *obj, hid_t connector_id, void *blob_id, H5VL_blob_specific_t specific_type, va_list arguments);
+
+/* Public wrappers for generic 'optional' callback */
+H5_DLL herr_t H5VLoptional(void *obj, hid_t connector_id, hid_t dxpl_id,
+ void **req, va_list arguments);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _H5VLconnector_passthru_H */
+
diff --git a/src/H5VLint.c b/src/H5VLint.c
new file mode 100644
index 0000000..09acb2a
--- /dev/null
+++ b/src/H5VLint.c
@@ -0,0 +1,2029 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Purpose: The Virtual Object Layer as described in documentation.
+ * The pupose is to provide an abstraction on how to access the
+ * underlying HDF5 container, whether in a local file with
+ * a specific file format, or remotely on other machines, etc...
+ */
+
+
+/****************/
+/* Module Setup */
+/****************/
+
+#include "H5VLmodule.h" /* This source code file is part of the H5VL module */
+
+
+/***********/
+/* Headers */
+/***********/
+
+#include "H5private.h" /* Generic Functions */
+#include "H5CXprivate.h" /* API Contexts */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5FLprivate.h" /* Free lists */
+#include "H5Iprivate.h" /* IDs */
+#include "H5MMprivate.h" /* Memory management */
+#include "H5PLprivate.h" /* Plugins */
+#include "H5Tprivate.h" /* Datatypes */
+#include "H5VLpkg.h" /* Virtual Object Layer */
+
+/* VOL connectors */
+#include "H5VLnative.h" /* Native VOL connector */
+#include "H5VLpassthru.h" /* Pass-through VOL connector */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+/* Object wrapping context info */
+typedef struct H5VL_wrap_ctx_t {
+ unsigned rc; /* Ref. count for the # of times the context was set / reset */
+ H5VL_t *connector; /* VOL connector for "outermost" class to start wrap */
+ void *obj_wrap_ctx; /* "wrap context" for outermost connector */
+} H5VL_wrap_ctx_t;
+
+/* Information needed for iterating over the registered VOL connector hid_t IDs.
+ * The name or value of the new VOL connector that is being registered is
+ * stored in the name (or value) field and the found_id field is initialized to
+ * H5I_INVALID_HID (-1). If we find a VOL connector with the same name / value,
+ * we set the found_id field to the existing ID for return to the function.
+ */
+typedef struct {
+ /* IN */
+ H5VL_get_connector_kind_t kind; /* Which kind of connector search to make */
+ union {
+ const char *name; /* The name of the VOL connector to check */
+ H5VL_class_value_t value; /* The value of the VOL connector to check */
+ } u;
+
+ /* OUT */
+ hid_t found_id; /* The connector ID, if we found a match */
+} H5VL_get_connector_ud_t;
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+static herr_t H5VL__free_cls(H5VL_class_t *cls);
+static int H5VL__get_connector_cb(void *obj, hid_t id, void *_op_data);
+static herr_t H5VL__set_def_conn(void);
+static void *H5VL__wrap_obj(void *obj, H5I_type_t obj_type);
+static H5VL_object_t *H5VL__new_vol_obj(H5I_type_t type, void *object,
+ H5VL_t *vol_connector, hbool_t wrap_obj);
+static int64_t H5VL__conn_inc_rc(H5VL_t *connector);
+static int64_t H5VL__conn_dec_rc(H5VL_t *connector);
+static void *H5VL__object(hid_t id, H5I_type_t obj_type);
+static herr_t H5VL__free_vol_wrapper(H5VL_wrap_ctx_t *vol_wrap_ctx);
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+/* Package initialization variable */
+hbool_t H5_PKG_INIT_VAR = FALSE;
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* VOL ID class */
+static const H5I_class_t H5I_VOL_CLS[1] = {{
+ H5I_VOL, /* ID class value */
+ 0, /* Class flags */
+ 0, /* # of reserved IDs for class */
+ (H5I_free_t)H5VL__free_cls /* Callback routine for closing objects of this class */
+}};
+
+/* Declare a free list to manage the H5VL_class_t struct */
+H5FL_DEFINE_STATIC(H5VL_class_t);
+
+/* Declare a free list to manage the H5VL_t struct */
+H5FL_DEFINE(H5VL_t);
+
+/* Declare a free list to manage the H5VL_object_t struct */
+H5FL_DEFINE(H5VL_object_t);
+
+/* Declare a free list to manage the H5VL_wrap_ctx_t struct */
+H5FL_DEFINE_STATIC(H5VL_wrap_ctx_t);
+
+/* Default VOL connector */
+static H5VL_connector_prop_t H5VL_def_conn_s = {-1, NULL};
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_init_phase1
+ *
+ * Purpose: Initialize the interface from some other package. This should
+ * be followed with a call to H5VL_init_phase2 after the H5P
+ * interface is completely set up, finish setting up the H5VL
+ * information.
+ *
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_init_phase1(void)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* FUNC_ENTER() does all the work */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_init_phase1() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_init_phase2
+ *
+ * Purpose: Finish initializing the interface from some other package.
+ *
+ * Note: This is broken out as a separate routine to avoid a circular
+ * reference with the H5P package.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_init_phase2(void)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Set up the default VOL connector in the default FAPL */
+ if(H5VL__set_def_conn() < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "unable to set default VOL connector")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_init_phase2() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__init_package
+ *
+ * Purpose: Initialize interface-specific information
+ *
+ * Return: Success: Non-negative
+ *
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL__init_package(void)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Initialize the atom group for the VL IDs */
+ if(H5I_register_type(H5I_VOL_CLS) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "unable to initialize H5VL interface")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__init_package() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_term_package
+ *
+ * Purpose: Terminate various H5VL objects
+ *
+ * Return: Success: Positive if anything was done that might
+ * affect other interfaces; zero otherwise.
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+H5VL_term_package(void)
+{
+ int n = 0;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ if(H5_PKG_INIT_VAR) {
+ if(H5VL_def_conn_s.connector_id > 0) {
+ /* Release the default VOL connector */
+ (void)H5VL_conn_free(&H5VL_def_conn_s);
+ H5VL_def_conn_s.connector_id = -1;
+ H5VL_def_conn_s.connector_info = NULL;
+ n++;
+ } /* end if */
+ else {
+ if(H5I_nmembers(H5I_VOL) > 0) {
+ /* Unregister all VOL connectors */
+ (void)H5I_clear_type(H5I_VOL, FALSE, FALSE);
+ n++;
+ } /* end if */
+ else {
+ /* Destroy the VOL connector ID group */
+ n += (H5I_dec_type_ref(H5I_VOL) > 0);
+
+ /* Mark interface as closed */
+ if(0 == n)
+ H5_PKG_INIT_VAR = FALSE;
+ } /* end else */
+ } /* end else */
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(n)
+} /* end H5VL_term_package() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__free_cls
+ *
+ * Purpose: Frees a file VOL class struct and returns an indication of
+ * success. This function is used as the free callback for the
+ * virtual object layer object identifiers
+ * (c.f.: H5VL_init_interface).
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__free_cls(H5VL_class_t *cls)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity check */
+ HDassert(cls);
+
+ /* Shut down the VOL connector */
+ if(cls->terminate && cls->terminate() < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCLOSEOBJ, FAIL, "VOL connector did not terminate cleanly")
+
+ /* Release the class */
+ H5MM_xfree((void *)cls->name); /* Casting away const OK -QAK */
+ H5FL_FREE(H5VL_class_t, cls);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__free_cls() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__get_connector_cb
+ *
+ * Purpose: Callback routine to search through registered VOLs
+ *
+ * Return: Success: H5_ITER_STOP if the class and op_data name
+ * members match. H5_ITER_CONT otherwise.
+ * Failure: Can't fail
+ *
+ * Programmer: Dana Robinson
+ * June 22, 2017
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+H5VL__get_connector_cb(void *obj, hid_t id, void *_op_data)
+{
+ H5VL_get_connector_ud_t *op_data = (H5VL_get_connector_ud_t *)_op_data; /* User data for callback */
+ H5VL_class_t *cls = (H5VL_class_t *)obj;
+ int ret_value = H5_ITER_CONT; /* Callback return value */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ if(H5VL_GET_CONNECTOR_BY_NAME == op_data->kind) {
+ if(0 == HDstrcmp(cls->name, op_data->u.name)) {
+ op_data->found_id = id;
+ ret_value = H5_ITER_STOP;
+ } /* end if */
+ } /* end if */
+ else {
+ HDassert(H5VL_GET_CONNECTOR_BY_VALUE == op_data->kind);
+ if(cls->value == op_data->u.value) {
+ op_data->found_id = id;
+ ret_value = H5_ITER_STOP;
+ } /* end if */
+ } /* end else */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__get_connector_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__set_def_conn
+ *
+ * Purpose: Parses a string that contains the default VOL connector for
+ * the library.
+ *
+ * Note: Usually from the environment variable "HDF5_VOL_CONNECTOR",
+ * but could be from elsewhere.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ * Programmer: Jordan Henderson
+ * November 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__set_def_conn(void)
+{
+ H5P_genplist_t *def_fapl; /* Default file access property list */
+ H5P_genclass_t *def_fapclass; /* Default file access property class */
+ const char *env_var; /* Environment variable for default VOL connector */
+ char *buf = NULL; /* Buffer for tokenizing string */
+ hid_t connector_id = -1; /* VOL conntector ID */
+ void *vol_info = NULL; /* VOL connector info */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity check */
+ HDassert(H5VL_def_conn_s.connector_id == (-1));
+ HDassert(H5VL_def_conn_s.connector_info == NULL);
+
+ /* Check for environment variable set */
+ env_var = HDgetenv("HDF5_VOL_CONNECTOR");
+
+ /* Only parse the string if it's set */
+ if(env_var && *env_var) {
+ char *lasts = NULL; /* Context pointer for strtok_r() call */
+ const char *tok = NULL; /* Token from strtok_r call */
+ htri_t connector_is_registered; /* Whether connector is already registered */
+
+ /* Duplicate the string to parse, as it is modified as we go */
+ if(NULL == (buf = H5MM_strdup(env_var)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTALLOC, FAIL, "can't allocate memory for environment variable string")
+
+ /* Get the first 'word' of the environment variable.
+ * If it's nothing (environment variable was whitespace) return error.
+ */
+ if(NULL == (tok = HDstrtok_r(buf, " \t\n\r", &lasts)))
+ HGOTO_ERROR(H5E_VOL, H5E_BADVALUE, FAIL, "VOL connector environment variable set empty?")
+
+ /* First, check to see if the connector is already registered */
+ if((connector_is_registered = H5VL__is_connector_registered(tok)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't check if VOL connector already registered")
+ else if(connector_is_registered) {
+ /* Retrieve the ID of the already-registered VOL connector */
+ if((connector_id = H5VL__get_connector_id(tok, FALSE)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't get VOL connector ID")
+ } /* end else-if */
+ else {
+ /* Check for VOL connectors that ship with the library */
+ if(!HDstrcmp(tok, "native")) {
+ connector_id = H5VL_NATIVE;
+ if(H5I_inc_ref(connector_id, FALSE) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTINC, FAIL, "can't increment VOL connector refcount")
+ } /* end if */
+ else if(!HDstrcmp(tok, "pass_through")) {
+ connector_id = H5VL_PASSTHRU;
+ if(H5I_inc_ref(connector_id, FALSE) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTINC, FAIL, "can't increment VOL connector refcount")
+ } /* end else-if */
+ else {
+ /* Register the VOL connector */
+ /* (NOTE: No provisions for vipl_id currently) */
+ if((connector_id = H5VL__register_connector_by_name(tok, FALSE, H5P_DEFAULT)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, FAIL, "can't register connector")
+ } /* end else */
+ } /* end else */
+
+ /* Was there any connector info specified in the environment variable? */
+ if(NULL != (tok = HDstrtok_r(NULL, " \t\n\r", &lasts)))
+ if(H5VL__connector_str_to_info(tok, connector_id, &vol_info) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTDECODE, FAIL, "can't deserialize connector info")
+
+ /* Set the default VOL connector */
+ H5VL_def_conn_s.connector_id = connector_id;
+ H5VL_def_conn_s.connector_info = vol_info;
+ } /* end if */
+ else {
+ /* Set the default VOL connector */
+ H5VL_def_conn_s.connector_id = H5_DEFAULT_VOL;
+ H5VL_def_conn_s.connector_info = NULL;
+
+ /* Increment the ref count on the default connector */
+ if(H5I_inc_ref(H5VL_def_conn_s.connector_id, FALSE) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTINC, FAIL, "can't increment VOL connector refcount")
+ } /* end else */
+
+ /* Get default file access pclass */
+ if(NULL == (def_fapclass = (H5P_genclass_t *)H5I_object(H5P_FILE_ACCESS)))
+ HGOTO_ERROR(H5E_VOL, H5E_BADATOM, FAIL, "can't find object for default file access property class ID")
+
+ /* Change the default VOL for the default file access pclass */
+ if(H5P_reset_vol_class(def_fapclass, &H5VL_def_conn_s) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set default VOL connector for default file access property class")
+
+ /* Get default file access plist */
+ if(NULL == (def_fapl = (H5P_genplist_t *)H5I_object(H5P_FILE_ACCESS_DEFAULT)))
+ HGOTO_ERROR(H5E_VOL, H5E_BADATOM, FAIL, "can't find object for default fapl ID")
+
+ /* Change the default VOL for the default FAPL */
+ if(H5P_set_vol(def_fapl, H5VL_def_conn_s.connector_id, H5VL_def_conn_s.connector_info) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set default VOL connector for default FAPL")
+
+done:
+ /* Clean up on error */
+ if(ret_value < 0) {
+ if(vol_info)
+ if(H5VL_free_connector_info(connector_id, vol_info) < 0)
+ HDONE_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "can't free VOL connector info")
+ if(connector_id >= 0)
+ /* The H5VL_class_t struct will be freed by this function */
+ if(H5I_dec_ref(connector_id) < 0)
+ HDONE_ERROR(H5E_VOL, H5E_CANTDEC, FAIL, "unable to unregister VOL connector")
+ } /* end if */
+
+ /* Clean up */
+ H5MM_xfree(buf);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__set_def_conn() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__wrap_obj
+ *
+ * Purpose: Wraps a library object with possible VOL connector wrappers, to
+ * match the VOL connector stack for the file.
+ *
+ * Return: Success: Wrapped object pointer
+ * Failure: NULL
+ *
+ * Programmer: Quincey Koziol
+ * Friday, October 7, 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5VL__wrap_obj(void *obj, H5I_type_t obj_type)
+{
+ H5VL_wrap_ctx_t *vol_wrap_ctx = NULL; /* Object wrapping context */
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check arguments */
+ HDassert(obj);
+
+ /* Retrieve the VOL object wrapping context */
+ if(H5CX_get_vol_wrap_ctx((void **)&vol_wrap_ctx) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, NULL, "can't get VOL object wrap context")
+
+ /* If there is a VOL object wrapping context, wrap the object */
+ if(vol_wrap_ctx) {
+ /* Wrap object, using the VOL callback */
+ if(NULL == (ret_value = H5VL_wrap_object(vol_wrap_ctx->connector->cls, vol_wrap_ctx->obj_wrap_ctx, obj, obj_type)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, NULL, "can't wrap object")
+ } /* end if */
+ else
+ ret_value = obj;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__wrap_obj() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__new_vol_obj
+ *
+ * Purpose: Creates a new VOL object, to use when registering an ID.
+ *
+ * Return: Success: VOL object pointer
+ * Failure: NULL
+ *
+ * Programmer: Quincey Koziol
+ * Friday, October 7, 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5VL_object_t *
+H5VL__new_vol_obj(H5I_type_t type, void *object, H5VL_t *vol_connector, hbool_t wrap_obj)
+{
+ H5VL_object_t *new_vol_obj = NULL; /* Pointer to new VOL object */
+ hbool_t conn_rc_incr = FALSE; /* Whether the VOL connector refcount has been incremented */
+ H5VL_object_t *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check arguments */
+ HDassert(object);
+ HDassert(vol_connector);
+
+ /* Make sure type number is valid */
+ if(type != H5I_ATTR && type != H5I_DATASET && type != H5I_DATATYPE
+ && type != H5I_FILE && type != H5I_GROUP && type != H5I_MAP)
+ HGOTO_ERROR(H5E_VOL, H5E_BADVALUE, NULL, "invalid type number")
+
+ /* Create the new VOL object */
+ if(NULL == (new_vol_obj = H5FL_CALLOC(H5VL_object_t)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTALLOC, NULL, "can't allocate memory for VOL object")
+ new_vol_obj->connector = vol_connector;
+ if(wrap_obj) {
+ if(NULL == (new_vol_obj->data = H5VL__wrap_obj(object, type)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCREATE, NULL, "can't wrap library object")
+ } /* end if */
+ else
+ new_vol_obj->data = object;
+
+ /* Bump the reference count on the VOL connector */
+ H5VL__conn_inc_rc(vol_connector);
+ conn_rc_incr = TRUE;
+
+ /* If this is a datatype, we have to hide the VOL object under the H5T_t pointer */
+ if(H5I_DATATYPE == type) {
+ if(NULL == (ret_value = (H5VL_object_t *)H5T_construct_datatype(new_vol_obj)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, NULL, "can't construct datatype object")
+ } /* end if */
+ else
+ ret_value = (H5VL_object_t *)new_vol_obj;
+
+done:
+ /* Cleanup on error */
+ if(NULL == ret_value) {
+ if(conn_rc_incr && H5VL__conn_dec_rc(vol_connector) < 0)
+ HDONE_ERROR(H5E_VOL, H5E_CANTDEC, NULL, "unable to decrement ref count on VOL connector")
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__new_vol_obj() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_conn_copy
+ *
+ * Purpose: Copy VOL connector ID & info.
+ *
+ * Note: This is an "in-place" copy.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_conn_copy(H5VL_connector_prop_t *connector_prop)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ if(connector_prop) {
+ /* Copy the connector ID & info, if there is one */
+ if(connector_prop->connector_id > 0) {
+ /* Increment the reference count on connector ID and copy connector info */
+ if(H5I_inc_ref(connector_prop->connector_id, FALSE) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTINC, FAIL, "unable to increment ref count on VOL connector ID")
+
+ /* Copy connector info, if it exists */
+ if(connector_prop->connector_info) {
+ H5VL_class_t *connector; /* Pointer to connector */
+ void *new_connector_info = NULL; /* Copy of connector info */
+
+ /* Retrieve the connector for the ID */
+ if(NULL == (connector = (H5VL_class_t *)H5I_object(connector_prop->connector_id)))
+ HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a VOL connector ID")
+
+ /* Allocate and copy connector info */
+ if(H5VL_copy_connector_info(connector, &new_connector_info, connector_prop->connector_info) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "connector info copy failed")
+
+ /* Set the connector info to the copy */
+ connector_prop->connector_info = new_connector_info;
+ } /* end if */
+ } /* end if */
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_conn_copy() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_conn_free
+ *
+ * Purpose: Free VOL connector ID & info.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_conn_free(const H5VL_connector_prop_t *connector_prop)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ if(connector_prop) {
+ /* Free the connector info (if it exists) and decrement the ID */
+ if(connector_prop->connector_id > 0) {
+ if(connector_prop->connector_info)
+ /* Free the connector info */
+ if(H5VL_free_connector_info(connector_prop->connector_id, (void *)connector_prop->connector_info) < 0) /* Casting away const OK - QAK */
+ HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "unable to release VOL connector info object")
+
+ /* Decrement reference count for connector ID */
+ if(H5I_dec_ref(connector_prop->connector_id) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTDEC, FAIL, "can't decrement reference count for connector ID")
+ } /* end if */
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_conn_free() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_register
+ *
+ * Purpose: VOL-aware version of H5I_register. Constructs an H5VL_object_t
+ * from the passed-in object and registers that. Does the right
+ * thing with datatypes, which are complicated under the VOL.
+ *
+ * Return: Success: A valid HDF5 ID
+ * Failure: H5I_INVALID_HID
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5VL_register(H5I_type_t type, void *object, H5VL_t *vol_connector, hbool_t app_ref)
+{
+ H5VL_object_t *vol_obj = NULL; /* VOL object wrapper for library object */
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5I_INVALID_HID)
+
+ /* Check arguments */
+ HDassert(object);
+ HDassert(vol_connector);
+
+ /* Set up VOL object for the passed-in data */
+ /* (Does not wrap object, since it's from a VOL callback) */
+ if(NULL == (vol_obj = H5VL__new_vol_obj(type, object, vol_connector, FALSE)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCREATE, FAIL, "can't create VOL object")
+
+ /* Register VOL object as _object_ type, for future object API calls */
+ if((ret_value = H5I_register(type, vol_obj, app_ref)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to atomize handle")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_register() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_register_using_existing_id
+ *
+ * Purpose: Registers an OBJECT in a TYPE with the supplied ID for it.
+ * This routine will check to ensure the supplied ID is not already
+ * in use, and ensure that it is a valid ID for the given type,
+ * but will NOT check to ensure the OBJECT is not already
+ * registered (thus, it is possible to register one object under
+ * multiple IDs).
+ *
+ * NOTE: Intended for use in refresh calls, where we have to close
+ * and re-open the underlying data, then hook the VOL object back
+ * up to the original ID.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_register_using_existing_id(H5I_type_t type, void *object, H5VL_t *vol_connector, hbool_t app_ref, hid_t existing_id)
+{
+ H5VL_object_t *new_vol_obj = NULL; /* Pointer to new VOL object */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Check arguments */
+ HDassert(object);
+ HDassert(vol_connector);
+
+ /* Set up VOL object for the passed-in data */
+ /* (Wraps object, since it's a library object) */
+ if(NULL == (new_vol_obj = H5VL__new_vol_obj(type, object, vol_connector, TRUE)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCREATE, FAIL, "can't create VOL object")
+
+ /* Call the underlying H5I function to complete the registration */
+ if(H5I_register_using_existing_id(type, new_vol_obj, app_ref, existing_id) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, FAIL, "can't register object under existing ID")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_register_using_existing_id() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_register_using_vol_id
+ *
+ * Purpose: Utility function to create a user ID for an object created
+ * or opened through the VOL. Uses the VOL connector's ID to
+ * get the connector information instead of it being passed in.
+ *
+ * Return: Success: A valid HDF5 ID
+ * Failure: H5I_INVALID_HID
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5VL_register_using_vol_id(H5I_type_t type, void *obj, hid_t connector_id, hbool_t app_ref)
+{
+ H5VL_class_t *cls = NULL; /* VOL connector class */
+ H5VL_t *connector = NULL; /* VOL connector struct */
+ hbool_t conn_id_incr = FALSE; /* Whether the VOL connector ID has been incremented */
+ hid_t ret_value = H5I_INVALID_HID;/* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Get the VOL class object from the connector's ID */
+ if(NULL == (cls = (H5VL_class_t *)H5I_object_verify(connector_id, H5I_VOL)))
+ HGOTO_ERROR(H5E_VOL, H5E_BADTYPE, H5I_INVALID_HID, "not a VOL connector ID")
+
+ /* Setup VOL info struct */
+ if(NULL == (connector = H5FL_CALLOC(H5VL_t)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTALLOC, H5I_INVALID_HID, "can't allocate VOL info struct")
+ connector->cls = cls;
+ connector->id = connector_id;
+ if(H5I_inc_ref(connector->id, FALSE) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTINC, H5I_INVALID_HID, "unable to increment ref count on VOL connector")
+ conn_id_incr = TRUE;
+
+ /* Get an ID for the VOL object */
+ if((ret_value = H5VL_register(type, obj, connector, app_ref)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register object handle")
+
+done:
+ /* Clean up on error */
+ if(ret_value < 0) {
+ /* Decrement VOL connector ID ref count on error */
+ if(conn_id_incr && H5I_dec_ref(connector_id) < 0)
+ HDONE_ERROR(H5E_VOL, H5E_CANTDEC, H5I_INVALID_HID, "unable to decrement ref count on VOL connector")
+
+ /* Free VOL connector struct */
+ if(NULL != connector)
+ connector = H5FL_FREE(H5VL_t, connector);
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_register_using_vol_id() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__conn_inc_rc
+ *
+ * Purpose: Wrapper to increment the ref. count on a connector.
+ *
+ * Return: Current ref. count (can't fail)
+ *
+ * Programmer: Quincey Koziol
+ * February 23, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+static int64_t
+H5VL__conn_inc_rc(H5VL_t *connector)
+{
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Check arguments */
+ HDassert(connector);
+
+ /* Increment refcount for connector */
+ connector->nrefs++;
+
+ FUNC_LEAVE_NOAPI(connector->nrefs)
+} /* end H5VL__conn_inc_rc() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__conn_dec_rc
+ *
+ * Purpose: Wrapper to decrement the ref. count on a connector.
+ *
+ * Return: Current ref. count (>=0) on success, <0 on failure
+ *
+ * Programmer: Quincey Koziol
+ * February 23, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+static int64_t
+H5VL__conn_dec_rc(H5VL_t *connector)
+{
+ int64_t ret_value = -1; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check arguments */
+ HDassert(connector);
+
+ /* Decrement refcount for connector */
+ connector->nrefs--;
+
+ /* Check for last reference */
+ if(0 == connector->nrefs) {
+ if(H5I_dec_ref(connector->id) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTDEC, FAIL, "unable to decrement ref count on VOL connector")
+ H5FL_FREE(H5VL_t, connector);
+
+ /* Set return value */
+ ret_value = 0;
+ } /* end if */
+ else
+ /* Set return value */
+ ret_value = connector->nrefs;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__conn_dec_rc() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_free_object
+ *
+ * Purpose: Wrapper to unregister an object ID with a VOL aux struct
+ * and decrement ref count on VOL connector ID
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_free_object(H5VL_object_t *vol_obj)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Check arguments */
+ HDassert(vol_obj);
+
+ /* Decrement refcount on connector */
+ if(H5VL__conn_dec_rc(vol_obj->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTDEC, FAIL, "unable to decrement ref count on VOL connector")
+
+ vol_obj = H5FL_FREE(H5VL_object_t, vol_obj);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_free_object() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_register_connector
+ *
+ * Purpose: Registers a new VOL connector as a member of the virtual object
+ * layer class.
+ *
+ * Return: Success: A VOL connector ID which is good until the
+ * library is closed or the connector is unregistered.
+ *
+ * Failure: H5I_INVALID_HID
+ *
+ * Programmer: Dana Robinson
+ * June 22, 2017
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5VL_register_connector(const void *_cls, hbool_t app_ref, hid_t vipl_id)
+{
+ const H5VL_class_t *cls = (const H5VL_class_t *)_cls;
+ H5VL_class_t *saved = NULL;
+ hid_t ret_value = H5I_INVALID_HID;
+
+ FUNC_ENTER_NOAPI(H5I_INVALID_HID)
+
+ /* Check arguments */
+ HDassert(cls);
+
+ /* Copy the class structure so the caller can reuse or free it */
+ if(NULL == (saved = H5FL_MALLOC(H5VL_class_t)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTALLOC, H5I_INVALID_HID, "memory allocation failed for VOL connector class struct")
+ H5MM_memcpy(saved, cls, sizeof(H5VL_class_t));
+ if(NULL == (saved->name = H5MM_strdup(cls->name)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTALLOC, H5I_INVALID_HID, "memory allocation failed for VOL connector name")
+
+ /* Initialize the VOL connector */
+ if(cls->initialize && cls->initialize(vipl_id) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, H5I_INVALID_HID, "unable to init VOL connector")
+
+ /* Create the new class ID */
+ if((ret_value = H5I_register(H5I_VOL, saved, app_ref)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VOL connector ID")
+
+done:
+ if(ret_value < 0 && saved) {
+ if(saved->name)
+ H5MM_xfree((void *)(saved->name)); /* Casting away const OK -QAK */
+
+ H5FL_FREE(H5VL_class_t, saved);
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_register_connector() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__register_connector
+ *
+ * Purpose: Registers a new VOL connector as a member of the virtual object
+ * layer class.
+ *
+ * Return: Success: A VOL connector ID which is good until the
+ * library is closed or the connector is
+ * unregistered.
+ *
+ * Failure: H5I_INVALID_HID
+ *
+ * Programmer: Dana Robinson
+ * June 22, 2017
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5VL__register_connector(const H5VL_class_t *cls, hbool_t app_ref, hid_t vipl_id)
+{
+ H5VL_get_connector_ud_t op_data; /* Callback info for connector search */
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Set up op data for iteration */
+ op_data.kind = H5VL_GET_CONNECTOR_BY_NAME;
+ op_data.u.name = cls->name;
+ op_data.found_id = H5I_INVALID_HID;
+
+ /* Check if connector is already registered */
+ if(H5I_iterate(H5I_VOL, H5VL__get_connector_cb, &op_data, TRUE) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_BADITER, H5I_INVALID_HID, "can't iterate over VOL IDs")
+
+ /* Increment the ref count on the existing VOL connector ID, if it's already registered */
+ if(op_data.found_id != H5I_INVALID_HID) {
+ if(H5I_inc_ref(op_data.found_id, app_ref) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTINC, H5I_INVALID_HID, "unable to increment ref count on VOL connector")
+ ret_value = op_data.found_id;
+ } /* end if */
+ else {
+ /* Create a new class ID */
+ if((ret_value = H5VL_register_connector(cls, app_ref, vipl_id)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VOL connector")
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__register_connector() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__register_connector_by_name
+ *
+ * Purpose: Registers a new VOL connector as a member of the virtual object
+ * layer class.
+ *
+ * Return: Success: A VOL connector ID which is good until the
+ * library is closed or the connector is
+ * unregistered.
+ *
+ * Failure: H5I_INVALID_HID
+ *
+ * Programmer: Dana Robinson
+ * June 22, 2017
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5VL__register_connector_by_name(const char *name, hbool_t app_ref, hid_t vipl_id)
+{
+ H5VL_get_connector_ud_t op_data; /* Callback info for connector search */
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Set up op data for iteration */
+ op_data.kind = H5VL_GET_CONNECTOR_BY_NAME;
+ op_data.u.name = name;
+ op_data.found_id = H5I_INVALID_HID;
+
+ /* Check if connector is already registered */
+ if(H5I_iterate(H5I_VOL, H5VL__get_connector_cb, &op_data, TRUE) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_BADITER, H5I_INVALID_HID, "can't iterate over VOL ids")
+
+ /* If connector alread registered, increment ref count on ID and return ID */
+ if(op_data.found_id != H5I_INVALID_HID) {
+ if(H5I_inc_ref(op_data.found_id, app_ref) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTINC, H5I_INVALID_HID, "unable to increment ref count on VOL connector")
+ ret_value = op_data.found_id;
+ } /* end if */
+ else {
+ H5PL_key_t key;
+ const H5VL_class_t *cls;
+
+ /* Try loading the connector */
+ key.vol.kind = H5VL_GET_CONNECTOR_BY_NAME;
+ key.vol.u.name = name;
+ if(NULL == (cls = (const H5VL_class_t *)H5PL_load(H5PL_TYPE_VOL, &key)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, H5I_INVALID_HID, "unable to load VOL connector")
+
+ /* Register the connector we loaded */
+ if((ret_value = H5VL_register_connector(cls, app_ref, vipl_id)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VOL connector ID")
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__register_connector_by_name() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__register_connector_by_value
+ *
+ * Purpose: Registers a new VOL connector as a member of the virtual object
+ * layer class.
+ *
+ * Return: Success: A VOL connector ID which is good until the
+ * library is closed or the connector is
+ * unregistered.
+ *
+ * Failure: H5I_INVALID_HID
+ *
+ * Programmer: Dana Robinson
+ * June 22, 2017
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5VL__register_connector_by_value(H5VL_class_value_t value, hbool_t app_ref, hid_t vipl_id)
+{
+ H5VL_get_connector_ud_t op_data; /* Callback info for connector search */
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Set up op data for iteration */
+ op_data.kind = H5VL_GET_CONNECTOR_BY_VALUE;
+ op_data.u.value = value;
+ op_data.found_id = H5I_INVALID_HID;
+
+ /* Check if connector is already registered */
+ if(H5I_iterate(H5I_VOL, H5VL__get_connector_cb, &op_data, TRUE) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_BADITER, H5I_INVALID_HID, "can't iterate over VOL ids")
+
+ /* If connector alread registered, increment ref count on ID and return ID */
+ if(op_data.found_id != H5I_INVALID_HID) {
+ if(H5I_inc_ref(op_data.found_id, app_ref) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTINC, H5I_INVALID_HID, "unable to increment ref count on VOL connector")
+ ret_value = op_data.found_id;
+ } /* end if */
+ else {
+ H5PL_key_t key;
+ const H5VL_class_t *cls;
+
+ /* Try loading the connector */
+ key.vol.kind = H5VL_GET_CONNECTOR_BY_VALUE;
+ key.vol.u.value = value;
+ if(NULL == (cls = (const H5VL_class_t *)H5PL_load(H5PL_TYPE_VOL, &key)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, H5I_INVALID_HID, "unable to load VOL connector")
+
+ /* Register the connector we loaded */
+ if((ret_value = H5VL_register_connector(cls, app_ref, vipl_id)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VOL connector ID")
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__register_connector_by_value() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__is_connector_registered
+ *
+ * Purpose: Checks if a connector with a particular name is registered.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ * Programmer: Dana Robinson
+ * June 17, 2017
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5VL__is_connector_registered(const char *name)
+{
+ H5VL_get_connector_ud_t op_data; /* Callback info for connector search */
+ htri_t ret_value = FALSE; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Set up op data for iteration */
+ op_data.kind = H5VL_GET_CONNECTOR_BY_NAME;
+ op_data.u.name = name;
+ op_data.found_id = H5I_INVALID_HID;
+
+ /* Find connector with name */
+ if(H5I_iterate(H5I_VOL, H5VL__get_connector_cb, &op_data, TRUE) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_BADITER, FAIL, "can't iterate over VOL connectors")
+
+ /* Found a connector with that name */
+ if(op_data.found_id != H5I_INVALID_HID)
+ ret_value = TRUE;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__is_connector_registered() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__get_connector_id
+ *
+ * Purpose: Retrieves the ID for a registered VOL connector.
+ *
+ * Return: Positive if the VOL class has been registered
+ * Negative on error (if the class is not a valid class or not registered)
+ *
+ * Programmer: Dana Robinson
+ * June 17, 2017
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5VL__get_connector_id(const char *name, hbool_t is_api)
+{
+ H5VL_get_connector_ud_t op_data; /* Callback info for connector search */
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Set up op data for iteration */
+ op_data.kind = H5VL_GET_CONNECTOR_BY_NAME;
+ op_data.u.name = name;
+ op_data.found_id = H5I_INVALID_HID;
+
+ /* Find connector with name */
+ if(H5I_iterate(H5I_VOL, H5VL__get_connector_cb, &op_data, TRUE) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_BADITER, H5I_INVALID_HID, "can't iterate over VOL connectors")
+
+ /* Found a connector with that name */
+ if(op_data.found_id != H5I_INVALID_HID) {
+ if(H5I_inc_ref(op_data.found_id, is_api) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINC, H5I_INVALID_HID, "unable to increment ref count on VOL connector")
+ ret_value = op_data.found_id;
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__get_connector_id() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__connector_str_to_info
+ *
+ * Purpose: Deserializes a string into a connector's info object
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * March 2, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL__connector_str_to_info(const char *str, hid_t connector_id, void **info)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Only deserialize string, if it's non-NULL */
+ if(str) {
+ H5VL_class_t *cls; /* VOL connector's class struct */
+
+ /* Check args and get class pointer */
+ if(NULL == (cls = (H5VL_class_t *)H5I_object_verify(connector_id, H5I_VOL)))
+ HGOTO_ERROR(H5E_VOL, H5E_BADTYPE, FAIL, "not a VOL connector ID")
+
+ /* Allow the connector to deserialize info */
+ if(cls->info_cls.from_str) {
+ if((cls->info_cls.from_str)(str, info) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTUNSERIALIZE, FAIL, "can't deserialize connector info")
+ } /* end if */
+ else
+ *info = NULL;
+ } /* end if */
+ else
+ *info = NULL;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__connector_str_to_info() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__get_connector_name
+ *
+ * Purpose: Private version of H5VLget_connector_name
+ *
+ * Return: Success: The length of the connector name
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+ssize_t
+H5VL__get_connector_name(hid_t id, char *name /*out*/, size_t size)
+{
+ H5VL_object_t *vol_obj;
+ const H5VL_class_t *cls;
+ size_t len;
+ ssize_t ret_value = -1;
+
+ FUNC_ENTER_PACKAGE
+
+ /* get the object pointer */
+ if (NULL == (vol_obj = H5VL_vol_object(id)))
+ HGOTO_ERROR(H5E_VOL, H5E_BADTYPE, FAIL, "invalid VOL identifier")
+
+ cls = vol_obj->connector->cls;
+
+ len = HDstrlen(cls->name);
+ if(name) {
+ HDstrncpy(name, cls->name, MIN(len + 1, size));
+ if(len >= size)
+ name[size - 1] = '\0';
+ } /* end if */
+
+ /* Set the return value for the API call */
+ ret_value = (ssize_t)len;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__get_connector_name() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_vol_object
+ *
+ * Purpose: Utility function to return the object pointer associated with
+ * a hid_t. This routine is the same as H5I_object for all types
+ * except for named datatypes, where the vol_obj is returned that
+ * is attached to the H5T_t struct.
+ *
+ * Return: Success: object pointer
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+H5VL_object_t *
+H5VL_vol_object(hid_t id)
+{
+ void *obj = NULL;
+ H5I_type_t obj_type;
+ H5VL_object_t *ret_value = NULL;
+
+ FUNC_ENTER_NOAPI(NULL)
+
+ obj_type = H5I_get_type(id);
+ if (H5I_FILE == obj_type || H5I_GROUP == obj_type || H5I_ATTR == obj_type ||
+ H5I_DATASET == obj_type || H5I_DATATYPE == obj_type) {
+ /* Get the object */
+ if (NULL == (obj = H5I_object(id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "invalid identifier")
+
+ /* if this is a datatype, get the VOL object attached to the H5T_t struct */
+ if (H5I_DATATYPE == obj_type)
+ if (NULL == (obj = H5T_get_named_type((H5T_t *)obj)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a named datatype")
+ } /* end if */
+ else
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "invalid identifier type to function")
+
+ ret_value = (H5VL_object_t *)obj;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_vol_object() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_object_data
+ *
+ * Purpose: Correctly retrieve the 'data' field for a VOL object (H5VL_object),
+ * even for nested / stacked VOL connectors.
+ *
+ * Return: Success: object pointer
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VL_object_data(const H5VL_object_t *vol_obj)
+{
+ void *ret_value = NULL;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ /* Check for 'get_object' callback in connector */
+ if(vol_obj->connector->cls->wrap_cls.get_object)
+ ret_value = (vol_obj->connector->cls->wrap_cls.get_object)(vol_obj->data);
+ else
+ ret_value = vol_obj->data;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_object_data() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_object_unwrap
+ *
+ * Purpose: Correctly unwrap the 'data' field for a VOL object (H5VL_object),
+ * even for nested / stacked VOL connectors.
+ *
+ * Return: Success: Object pointer
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VL_object_unwrap(const H5VL_object_t *vol_obj)
+{
+ void *ret_value = NULL;
+
+ FUNC_ENTER_NOAPI(NULL)
+
+ if(NULL == (ret_value = H5VL_unwrap_object(vol_obj->connector->cls, vol_obj->data)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, NULL, "can't unwrap object")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_object_unwrap() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__object
+ *
+ * Purpose: Internal function to return the VOL object pointer associated
+ * with an hid_t.
+ *
+ * Return: Success: object pointer
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5VL__object(hid_t id, H5I_type_t obj_type)
+{
+ H5VL_object_t *vol_obj = NULL;
+ void *ret_value = NULL;
+
+ FUNC_ENTER_STATIC
+
+ /* Get the underlying object */
+ switch(obj_type) {
+ case H5I_GROUP:
+ case H5I_DATASET:
+ case H5I_FILE:
+ case H5I_ATTR:
+ case H5I_MAP:
+ /* get the object */
+ if (NULL == (vol_obj = (H5VL_object_t *)H5I_object(id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "invalid identifier")
+ break;
+
+ case H5I_DATATYPE:
+ {
+ H5T_t *dt = NULL;
+
+ /* get the object */
+ if (NULL == (dt = (H5T_t *)H5I_object(id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "invalid identifier")
+
+ /* Get the actual datatype object that should be the vol_obj */
+ if (NULL == (vol_obj = H5T_get_named_type(dt)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a named datatype")
+ break;
+ }
+
+ case H5I_UNINIT:
+ case H5I_BADID:
+ case H5I_DATASPACE:
+ case H5I_VFL:
+ case H5I_VOL:
+ case H5I_GENPROP_CLS:
+ case H5I_GENPROP_LST:
+ case H5I_ERROR_CLASS:
+ case H5I_ERROR_MSG:
+ case H5I_ERROR_STACK:
+ case H5I_SPACE_SEL_ITER:
+ case H5I_NTYPES:
+ default:
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "unknown data object type")
+ } /* end switch */
+
+ /* Set the return value */
+ ret_value = H5VL_object_data(vol_obj);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__object() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_object
+ *
+ * Purpose: Utility function to return the VOL object pointer associated with
+ * a hid_t.
+ *
+ * Return: Success: object pointer
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VL_object(hid_t id)
+{
+ void *ret_value = NULL;
+
+ FUNC_ENTER_NOAPI(NULL)
+
+ /* Get the underlying object */
+ if(NULL == (ret_value = H5VL__object(id, H5I_get_type(id))))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, NULL, "can't retrieve object for ID")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_object() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_object_verify
+ *
+ * Purpose: Utility function to return the VOL object pointer associated
+ * with an identifier.
+ *
+ * Return: Success: object pointer
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VL_object_verify(hid_t id, H5I_type_t obj_type)
+{
+ void *ret_value = NULL;
+
+ FUNC_ENTER_NOAPI(NULL)
+
+ /* Check of ID of correct type */
+ if(obj_type != H5I_get_type(id))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "invalid identifier")
+
+ /* Get the underlying object */
+ if(NULL == (ret_value = H5VL__object(id, obj_type)))
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTGET, NULL, "can't retrieve object for ID")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_object_verify() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_cmp_connector_cls
+ *
+ * Purpose: Compare VOL class for a connector
+ *
+ * Note: Sets *cmp_value positive if VALUE1 is greater than VALUE2,
+ * negative if VALUE2 is greater than VALUE1, and zero if VALUE1
+ * and VALUE2 are equal (like strcmp).
+ *
+ * Return: SUCCEED / FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_cmp_connector_cls(int *cmp_value, const H5VL_class_t *cls1, const H5VL_class_t *cls2)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(cls1);
+ HDassert(cls2);
+
+ /* Compare connector "values" */
+ if(cls1->value < cls2->value) {
+ *cmp_value = -1;
+ HGOTO_DONE(SUCCEED)
+ } /* end if */
+ if(cls1->value > cls2->value) {
+ *cmp_value = 1;
+ HGOTO_DONE(SUCCEED)
+ } /* end if */
+ HDassert(cls1->value == cls2->value);
+
+ /* Compare connector names */
+ if(cls1->name == NULL && cls2->name != NULL) {
+ *cmp_value = -1;
+ HGOTO_DONE(SUCCEED)
+ } /* end if */
+ if(cls1->name != NULL && cls2->name == NULL) {
+ *cmp_value = 1;
+ HGOTO_DONE(SUCCEED)
+ } /* end if */
+ if(0 != (*cmp_value = HDstrcmp(cls1->name, cls2->name)))
+ HGOTO_DONE(SUCCEED)
+
+ /* Compare connector VOL API versions */
+ if(cls1->version < cls2->version) {
+ *cmp_value = -1;
+ HGOTO_DONE(SUCCEED)
+ } /* end if */
+ if(cls1->version > cls2->version) {
+ *cmp_value = 1;
+ HGOTO_DONE(SUCCEED)
+ } /* end if */
+ HDassert(cls1->version == cls2->version);
+
+ /* Compare connector info */
+ if(cls1->info_cls.size < cls2->info_cls.size) {
+ *cmp_value = -1;
+ HGOTO_DONE(SUCCEED)
+ } /* end if */
+ if(cls1->info_cls.size > cls2->info_cls.size) {
+ *cmp_value = 1;
+ HGOTO_DONE(SUCCEED)
+ } /* end if */
+ HDassert(cls1->info_cls.size == cls2->info_cls.size);
+
+ /* Set comparison value to 'equal' */
+ *cmp_value = 0;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_cmp_connector_cls() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_retrieve_lib_state
+ *
+ * Purpose: Retrieve the state of the library.
+ *
+ * Note: Currently just retrieves the API context state, but could be
+ * expanded in the future.
+ *
+ * Return: Success: Non-negative, *state set
+ * Failure: Negative, *state unset
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_retrieve_lib_state(void **state)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(state);
+
+ /* Retrieve the API context state */
+ if(H5CX_retrieve_state((H5CX_state_t **)state) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't get API context state")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_retrieve_lib_state() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_restore_lib_state
+ *
+ * Purpose: Restore the state of the library.
+ *
+ * Note: Currently just restores the API context state, but could be
+ * expanded in the future.
+ *
+ * Return: SUCCEED / FAIL
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, January 10, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_restore_lib_state(const void *state)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(state);
+
+ /* Push a new API context on the stack */
+ if(H5CX_push() < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't push API context")
+
+ /* Restore the API context state */
+ if(H5CX_restore_state((const H5CX_state_t *)state) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set API context state")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_restore_lib_state() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_reset_lib_state
+ *
+ * Purpose: Reset the state of the library, undoing affects of
+ * H5VL_restore_lib_state.
+ *
+ * Note: Currently just resets the API context state, but could be
+ * expanded in the future.
+ *
+ * Note: This routine must be called as a "pair" with
+ * H5VL_restore_lib_state. It can be called before / after /
+ * independently of H5VL_free_lib_state.
+ *
+ * Return: SUCCEED / FAIL
+ *
+ * Programmer: Quincey Koziol
+ * Saturday, February 23, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_reset_lib_state(void)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Pop the API context off the stack */
+ if(H5CX_pop() < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTRESET, FAIL, "can't pop API context")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_reset_lib_state() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_free_lib_state
+ *
+ * Purpose: Free a library state.
+ *
+ * Note: This routine must be called as a "pair" with
+ * H5VL_retrieve_lib_state.
+ *
+ * Return: SUCCEED / FAIL
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, January 10, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_free_lib_state(void *state)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(state);
+
+ /* Free the API context state */
+ if(H5CX_free_state((H5CX_state_t *)state) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "can't free API context state")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_free_lib_state() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__free_vol_wrapper
+ *
+ * Purpose: Free object wrapping context for VOL connector
+ *
+ * Return: SUCCEED / FAIL
+ *
+ * Programmer: Quincey Koziol
+ * Wednesday, January 9, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__free_vol_wrapper(H5VL_wrap_ctx_t *vol_wrap_ctx)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity check */
+ HDassert(vol_wrap_ctx);
+ HDassert(0 == vol_wrap_ctx->rc);
+ HDassert(vol_wrap_ctx->connector);
+ HDassert(vol_wrap_ctx->connector->cls);
+
+ /* If there is a VOL connector object wrapping context, release it */
+ if(vol_wrap_ctx->obj_wrap_ctx)
+ /* Release the VOL connector's object wrapping context */
+ if((*vol_wrap_ctx->connector->cls->wrap_cls.free_wrap_ctx)(vol_wrap_ctx->obj_wrap_ctx) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "unable to release connector's object wrapping context")
+
+ /* Decrement refcount on connector */
+ if(H5VL__conn_dec_rc(vol_wrap_ctx->connector) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTDEC, FAIL, "unable to decrement ref count on VOL connector")
+
+ /* Release object wrapping context */
+ H5FL_FREE(H5VL_wrap_ctx_t, vol_wrap_ctx);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__free_vol_wrapper() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_set_vol_wrapper
+ *
+ * Purpose: Set up object wrapping context for current VOL connector
+ *
+ * Return: SUCCEED / FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_set_vol_wrapper(void *obj, H5VL_t *connector)
+{
+ H5VL_wrap_ctx_t *vol_wrap_ctx = NULL; /* Object wrapping context */
+ void *obj_wrap_ctx = NULL; /* VOL connector's wrapping context */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(obj);
+ HDassert(connector);
+
+ /* Retrieve the VOL object wrap context */
+ if(H5CX_get_vol_wrap_ctx((void **)&vol_wrap_ctx) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't get VOL object wrap context")
+
+ /* Check for existing wrapping context */
+ if(NULL == vol_wrap_ctx) {
+ /* Check if the connector can create a wrap context */
+ if(connector->cls->wrap_cls.get_wrap_ctx) {
+ /* Sanity check */
+ HDassert(connector->cls->wrap_cls.free_wrap_ctx);
+
+ /* Get the wrap context from the connector */
+ if((connector->cls->wrap_cls.get_wrap_ctx)(obj, &obj_wrap_ctx) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't retrieve VOL connector's object wrap context")
+ } /* end if */
+
+ /* Allocate VOL object wrapper context */
+ if(NULL == (vol_wrap_ctx = H5FL_MALLOC(H5VL_wrap_ctx_t)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTALLOC, FAIL, "can't allocate VOL wrap context")
+
+ /* Increment the outstanding objects that are using the connector */
+ H5VL__conn_inc_rc(connector);
+
+ /* Set up VOL object wrapper context */
+ vol_wrap_ctx->rc = 1;
+ vol_wrap_ctx->connector = connector;
+ vol_wrap_ctx->obj_wrap_ctx = obj_wrap_ctx;
+ } /* end if */
+ else
+ /* Incremeent ref count on existing wrapper context */
+ vol_wrap_ctx->rc++;
+
+ /* Save the wrapper context */
+ if(H5CX_set_vol_wrap_ctx(vol_wrap_ctx) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL object wrap context")
+
+done:
+ if(ret_value < 0 && vol_wrap_ctx)
+ /* Release object wrapping context */
+ H5FL_FREE(H5VL_wrap_ctx_t, vol_wrap_ctx);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_set_vol_wrapper() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_inc_vol_wrapper
+ *
+ * Purpose: Increment refcount on object wrapping context
+ *
+ * Return: SUCCEED / FAIL
+ *
+ * Programmer: Quincey Koziol
+ * Wednesday, January 9, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_inc_vol_wrapper(void *_vol_wrap_ctx)
+{
+ H5VL_wrap_ctx_t *vol_wrap_ctx = (H5VL_wrap_ctx_t *)_vol_wrap_ctx; /* VOL object wrapping context */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Check for valid, active VOL object wrap context */
+ if(NULL == vol_wrap_ctx)
+ HGOTO_ERROR(H5E_VOL, H5E_BADVALUE, FAIL, "no VOL object wrap context?")
+ if(0 == vol_wrap_ctx->rc)
+ HGOTO_ERROR(H5E_VOL, H5E_BADVALUE, FAIL, "bad VOL object wrap context refcount?")
+
+ /* Increment ref count on wrapping context */
+ vol_wrap_ctx->rc++;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_inc_vol_wrapper() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_dec_vol_wrapper
+ *
+ * Purpose: Decrement refcount on object wrapping context, releasing it
+ * if the refcount drops to zero.
+ *
+ * Return: SUCCEED / FAIL
+ *
+ * Programmer: Quincey Koziol
+ * Wednesday, January 9, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_dec_vol_wrapper(void *_vol_wrap_ctx)
+{
+ H5VL_wrap_ctx_t *vol_wrap_ctx = (H5VL_wrap_ctx_t *)_vol_wrap_ctx; /* VOL object wrapping context */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Check for valid, active VOL object wrap context */
+ if(NULL == vol_wrap_ctx)
+ HGOTO_ERROR(H5E_VOL, H5E_BADVALUE, FAIL, "no VOL object wrap context?")
+ if(0 == vol_wrap_ctx->rc)
+ HGOTO_ERROR(H5E_VOL, H5E_BADVALUE, FAIL, "bad VOL object wrap context refcount?")
+
+ /* Decrement ref count on wrapping context */
+ vol_wrap_ctx->rc--;
+
+ /* Release context if the ref count drops to zero */
+ if(0 == vol_wrap_ctx->rc)
+ if(H5VL__free_vol_wrapper(vol_wrap_ctx) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "unable to release VOL object wrapping context")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_dec_vol_wrapper() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_reset_vol_wrapper
+ *
+ * Purpose: Reset object wrapping context for current VOL connector
+ *
+ * Return: SUCCEED / FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_reset_vol_wrapper(void)
+{
+ H5VL_wrap_ctx_t *vol_wrap_ctx = NULL; /* Object wrapping context */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Retrieve the VOL object wrap context */
+ if(H5CX_get_vol_wrap_ctx((void **)&vol_wrap_ctx) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't get VOL object wrap context")
+
+ /* Check for VOL object wrap context */
+ if(NULL == vol_wrap_ctx)
+ HGOTO_ERROR(H5E_VOL, H5E_BADVALUE, FAIL, "no VOL object wrap context?")
+
+ /* Decrement ref count on wrapping context */
+ vol_wrap_ctx->rc--;
+
+ /* Release context if the ref count drops to zero */
+ if(0 == vol_wrap_ctx->rc) {
+ /* Release object wrapping context */
+ if(H5VL__free_vol_wrapper(vol_wrap_ctx) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "unable to release VOL object wrapping context")
+
+ /* Reset the wrapper context */
+ if(H5CX_set_vol_wrap_ctx(NULL) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL object wrap context")
+ } /* end if */
+ else
+ /* Save the updated wrapper context */
+ if(H5CX_set_vol_wrap_ctx(vol_wrap_ctx) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL object wrap context")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_reset_vol_wrapper() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_wrap_register
+ *
+ * Purpose: Wrap an object and register an ID for it
+ *
+ * Return: SUCCEED / FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5VL_wrap_register(H5I_type_t type, void *obj, hbool_t app_ref)
+{
+ H5VL_wrap_ctx_t *vol_wrap_ctx = NULL; /* Object wrapping context */
+ void *new_obj; /* Newly wrapped object */
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5I_INVALID_HID)
+
+ /* Sanity check */
+ HDassert(obj);
+
+ /* If the datatype is already VOL-managed, the datatype's vol_obj
+ * field will get clobbered later, so disallow this.
+ */
+ if(type == H5I_DATATYPE)
+ if(TRUE == H5T_already_vol_managed((const H5T_t *)obj))
+ HGOTO_ERROR(H5E_VOL, H5E_BADTYPE, H5I_INVALID_HID, "can't wrap an uncommitted datatype")
+
+ /* Wrap the object with VOL connector info */
+ if(NULL == (new_obj = H5VL__wrap_obj(obj, type)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTCREATE, H5I_INVALID_HID, "can't wrap library object")
+
+ /* Retrieve the VOL object wrapping context */
+ if(H5CX_get_vol_wrap_ctx((void **)&vol_wrap_ctx) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, H5I_INVALID_HID, "can't get VOL object wrap context")
+ if(NULL == vol_wrap_ctx || NULL == vol_wrap_ctx->connector)
+ HGOTO_ERROR(H5E_VOL, H5E_BADVALUE, H5I_INVALID_HID, "VOL object wrap context or its connector is NULL???")
+
+ /* Get an ID for the object */
+ if((ret_value = H5VL_register_using_vol_id(type, new_obj, vol_wrap_ctx->connector->id, app_ref)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to get an ID for the object")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_wrap_register() */
+
diff --git a/src/H5HGpublic.h b/src/H5VLmodule.h
index fcec593..1ae0d61 100644
--- a/src/H5HGpublic.h
+++ b/src/H5VLmodule.h
@@ -1,6 +1,5 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* 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 *
@@ -12,20 +11,21 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
- * Programmer: Robb Matzke <matzke@llnl.gov>
- * Friday, March 27, 1998
+ * Purpose: This file contains declarations which define macros for the
+ * H5VL package. Including this header means that the source file
+ * is part of the H5VL package.
*/
-#ifndef _H5HGpublic_H
-#define _H5HGpublic_H
-/* Public headers needed by this file */
-#include "H5public.h"
+#ifndef _H5VLmodule_H
+#define _H5VLmodule_H
-#ifdef __cplusplus
-extern "C" {
-#endif
+/* Define the proper control macros for the generic FUNC_ENTER/LEAVE and error
+ * reporting macros.
+ */
+#define H5VL_MODULE
+#define H5_MY_PKG H5VL
+#define H5_MY_PKG_ERR H5E_VOL
+#define H5_MY_PKG_INIT YES
+
+#endif /* _H5VLmodule_H */
-#ifdef __cplusplus
-}
-#endif
-#endif
diff --git a/src/H5VLnative.c b/src/H5VLnative.c
new file mode 100644
index 0000000..78eaee4
--- /dev/null
+++ b/src/H5VLnative.c
@@ -0,0 +1,182 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Purpose: The native VOL connector where access is to a single HDF5 file
+ * using HDF5 VFDs.
+ */
+
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Iprivate.h" /* IDs */
+#include "H5Pprivate.h" /* Property lists */
+#include "H5VLprivate.h" /* Virtual Object Layer */
+
+#include "H5VLnative_private.h" /* Native VOL connector */
+
+
+/* The VOL connector identification number */
+static hid_t H5VL_NATIVE_ID_g = H5I_INVALID_HID;
+
+/* Prototypes */
+static herr_t H5VL__native_term(void);
+
+/* Native VOL connector class struct */
+static H5VL_class_t H5VL_native_cls_g = {
+ H5VL_NATIVE_VERSION, /* version */
+ H5VL_NATIVE_VALUE, /* value */
+ H5VL_NATIVE_NAME, /* name */
+ 0, /* capability flags */
+ NULL, /* initialize */
+ H5VL__native_term, /* terminate */
+ { /* info_cls */
+ (size_t)0, /* info size */
+ NULL, /* info copy */
+ NULL, /* info compare */
+ NULL, /* info free */
+ NULL, /* info to str */
+ NULL /* str to info */
+ },
+ { /* wrap_cls */
+ NULL, /* get_object */
+ NULL, /* get_wrap_ctx */
+ NULL, /* wrap_object */
+ NULL, /* unwrap_object */
+ NULL /* free_wrap_ctx */
+ },
+ { /* attribute_cls */
+ H5VL__native_attr_create, /* create */
+ H5VL__native_attr_open, /* open */
+ H5VL__native_attr_read, /* read */
+ H5VL__native_attr_write, /* write */
+ H5VL__native_attr_get, /* get */
+ H5VL__native_attr_specific, /* specific */
+ H5VL__native_attr_optional, /* optional */
+ H5VL__native_attr_close /* close */
+ },
+ { /* dataset_cls */
+ H5VL__native_dataset_create, /* create */
+ H5VL__native_dataset_open, /* open */
+ H5VL__native_dataset_read, /* read */
+ H5VL__native_dataset_write, /* write */
+ H5VL__native_dataset_get, /* get */
+ H5VL__native_dataset_specific, /* specific */
+ H5VL__native_dataset_optional, /* optional */
+ H5VL__native_dataset_close /* close */
+ },
+ { /* datatype_cls */
+ H5VL__native_datatype_commit, /* commit */
+ H5VL__native_datatype_open, /* open */
+ H5VL__native_datatype_get, /* get */
+ H5VL__native_datatype_specific, /* specific */
+ NULL, /* optional */
+ H5VL__native_datatype_close /* close */
+ },
+ { /* file_cls */
+ H5VL__native_file_create, /* create */
+ H5VL__native_file_open, /* open */
+ H5VL__native_file_get, /* get */
+ H5VL__native_file_specific, /* specific */
+ H5VL__native_file_optional, /* optional */
+ H5VL__native_file_close /* close */
+ },
+ { /* group_cls */
+ H5VL__native_group_create, /* create */
+ H5VL__native_group_open, /* open */
+ H5VL__native_group_get, /* get */
+ H5VL__native_group_specific, /* specific */
+ H5VL__native_group_optional, /* optional */
+ H5VL__native_group_close /* close */
+ },
+ { /* link_cls */
+ H5VL__native_link_create, /* create */
+ H5VL__native_link_copy, /* copy */
+ H5VL__native_link_move, /* move */
+ H5VL__native_link_get, /* get */
+ H5VL__native_link_specific, /* specific */
+ NULL /* optional */
+ },
+ { /* object_cls */
+ H5VL__native_object_open, /* open */
+ H5VL__native_object_copy, /* copy */
+ H5VL__native_object_get, /* get */
+ H5VL__native_object_specific, /* specific */
+ H5VL__native_object_optional /* optional */
+ },
+ { /* request_cls */
+ NULL, /* wait */
+ NULL, /* notify */
+ NULL, /* cancel */
+ NULL, /* specific */
+ NULL, /* optional */
+ NULL /* free */
+ },
+ { /* blob_cls */
+ H5VL__native_blob_put, /* put */
+ H5VL__native_blob_get, /* get */
+ H5VL__native_blob_specific, /* specific */
+ NULL /* optional */
+ },
+ NULL /* optional */
+};
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_native_register
+ *
+ * Purpose: Register the native VOL connector and retrieve an ID for it.
+ *
+ * Return: Success: The ID for the native connector
+ * Failure: H5I_INVALID_HID
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5VL_native_register(void)
+{
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5I_INVALID_HID)
+
+ /* Register the native VOL connector, if it isn't already */
+ if(NULL == H5I_object_verify(H5VL_NATIVE_ID_g, H5I_VOL))
+ if((H5VL_NATIVE_ID_g = H5VL_register_connector((const H5VL_class_t *)&H5VL_native_cls_g, TRUE, H5P_DEFAULT)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTINSERT, H5I_INVALID_HID, "can't create ID for native VOL connector")
+
+ /* Set return value */
+ ret_value = H5VL_NATIVE_ID_g;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_native_register() */
+
+
+/*---------------------------------------------------------------------------
+ * Function: H5VL__native_term
+ *
+ * Purpose: Shut down the native VOL
+ *
+ * Returns: SUCCEED (Can't fail)
+ *
+ *---------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__native_term(void)
+{
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Reset VOL ID */
+ H5VL_NATIVE_ID_g = H5I_INVALID_HID;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5VL__native_term() */
+
diff --git a/src/H5VLnative.h b/src/H5VLnative.h
new file mode 100644
index 0000000..5b51e66
--- /dev/null
+++ b/src/H5VLnative.h
@@ -0,0 +1,108 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Purpose: The public header file for the native VOL connector.
+ */
+
+#ifndef _H5VLnative_H
+#define _H5VLnative_H
+
+/* Public headers needed by this file */
+#include "H5VLpublic.h" /* Virtual Object Layer */
+
+/* Identifier for the native VOL connector */
+#define H5VL_NATIVE (H5VL_native_register())
+
+/* Characteristics of the native VOL connector */
+#define H5VL_NATIVE_NAME "native"
+#define H5VL_NATIVE_VALUE H5_VOL_NATIVE /* enum value */
+#define H5VL_NATIVE_VERSION 0
+
+/* Typedef and values for native VOL connector attribute optional VOL operations */
+typedef int H5VL_native_attr_optional_t;
+#ifndef H5_NO_DEPRECATED_SYMBOLS
+#define H5VL_NATIVE_ATTR_ITERATE_OLD 0 /* H5Aiterate (deprecated routine) */
+#endif /* H5_NO_DEPRECATED_SYMBOLS */
+
+/* Typedef and values for native VOL connector dataset optional VOL operations */
+typedef int H5VL_native_dataset_optional_t;
+#define H5VL_NATIVE_DATASET_FORMAT_CONVERT 0 /* H5Dformat_convert (internal) */
+#define H5VL_NATIVE_DATASET_GET_CHUNK_INDEX_TYPE 1 /* H5Dget_chunk_index_type */
+#define H5VL_NATIVE_DATASET_GET_CHUNK_STORAGE_SIZE 2 /* H5Dget_chunk_storage_size */
+#define H5VL_NATIVE_DATASET_GET_NUM_CHUNKS 3 /* H5Dget_num_chunks */
+#define H5VL_NATIVE_DATASET_GET_CHUNK_INFO_BY_IDX 4 /* H5Dget_chunk_info */
+#define H5VL_NATIVE_DATASET_GET_CHUNK_INFO_BY_COORD 5 /* H5Dget_chunk_info_by_coord */
+#define H5VL_NATIVE_DATASET_CHUNK_READ 6 /* H5Dchunk_read */
+#define H5VL_NATIVE_DATASET_CHUNK_WRITE 7 /* H5Dchunk_write */
+
+/* Typedef and values for native VOL connector file optional VOL operations */
+typedef int H5VL_native_file_optional_t;
+#define H5VL_NATIVE_FILE_CLEAR_ELINK_CACHE 0 /* H5Fclear_elink_file_cache */
+#define H5VL_NATIVE_FILE_GET_FILE_IMAGE 1 /* H5Fget_file_image */
+#define H5VL_NATIVE_FILE_GET_FREE_SECTIONS 2 /* H5Fget_free_sections */
+#define H5VL_NATIVE_FILE_GET_FREE_SPACE 3 /* H5Fget_freespace */
+#define H5VL_NATIVE_FILE_GET_INFO 4 /* H5Fget_info1/2 */
+#define H5VL_NATIVE_FILE_GET_MDC_CONF 5 /* H5Fget_mdc_config */
+#define H5VL_NATIVE_FILE_GET_MDC_HR 6 /* H5Fget_mdc_hit_rate */
+#define H5VL_NATIVE_FILE_GET_MDC_SIZE 7 /* H5Fget_mdc_size */
+#define H5VL_NATIVE_FILE_GET_SIZE 8 /* H5Fget_filesize */
+#define H5VL_NATIVE_FILE_GET_VFD_HANDLE 9 /* H5Fget_vfd_handle */
+#define H5VL_NATIVE_FILE_GET_FILE_ID 10 /* H5Fget_file_id */
+#define H5VL_NATIVE_FILE_RESET_MDC_HIT_RATE 11 /* H5Freset_mdc_hit_rate_stats */
+#define H5VL_NATIVE_FILE_SET_MDC_CONFIG 12 /* H5Fset_mdc_config */
+#define H5VL_NATIVE_FILE_GET_METADATA_READ_RETRY_INFO 13 /* H5Fget_metadata_read_retry_info */
+#define H5VL_NATIVE_FILE_START_SWMR_WRITE 14 /* H5Fstart_swmr_write */
+#define H5VL_NATIVE_FILE_START_MDC_LOGGING 15 /* H5Fstart_mdc_logging */
+#define H5VL_NATIVE_FILE_STOP_MDC_LOGGING 16 /* H5Fstop_mdc_logging */
+#define H5VL_NATIVE_FILE_GET_MDC_LOGGING_STATUS 17 /* H5Fget_mdc_logging_status */
+#define H5VL_NATIVE_FILE_FORMAT_CONVERT 18 /* H5Fformat_convert */
+#define H5VL_NATIVE_FILE_RESET_PAGE_BUFFERING_STATS 19 /* H5Freset_page_buffering_stats */
+#define H5VL_NATIVE_FILE_GET_PAGE_BUFFERING_STATS 20 /* H5Fget_page_buffering_stats */
+#define H5VL_NATIVE_FILE_GET_MDC_IMAGE_INFO 21 /* H5Fget_mdc_image_info */
+#define H5VL_NATIVE_FILE_GET_EOA 22 /* H5Fget_eoa */
+#define H5VL_NATIVE_FILE_INCR_FILESIZE 23 /* H5Fincrement_filesize */
+#define H5VL_NATIVE_FILE_SET_LIBVER_BOUNDS 24 /* H5Fset_latest_format/libver_bounds */
+#define H5VL_NATIVE_FILE_GET_MIN_DSET_OHDR_FLAG 25 /* H5Fget_dset_no_attrs_hint */
+#define H5VL_NATIVE_FILE_SET_MIN_DSET_OHDR_FLAG 26 /* H5Fset_dset_no_attrs_hint */
+#define H5VL_NATIVE_FILE_GET_MPI_ATOMICITY 27 /* H5Fget_mpi_atomicity */
+#define H5VL_NATIVE_FILE_SET_MPI_ATOMICITY 28 /* H5Fset_mpi_atomicity */
+
+/* Typedef and values for native VOL connector group optional VOL operations */
+typedef int H5VL_native_group_optional_t;
+#ifndef H5_NO_DEPRECATED_SYMBOLS
+#define H5VL_NATIVE_GROUP_ITERATE_OLD 0 /* HG5Giterate (deprecated routine) */
+#define H5VL_NATIVE_GROUP_GET_OBJINFO 1 /* HG5Gget_objinfo (deprecated routine) */
+#endif /* H5_NO_DEPRECATED_SYMBOLS */
+
+/* Typedef and values for native VOL connector object optional VOL operations */
+typedef int H5VL_native_object_optional_t;
+#define H5VL_NATIVE_OBJECT_GET_COMMENT 0 /* H5G|H5Oget_comment, H5Oget_comment_by_name */
+#define H5VL_NATIVE_OBJECT_GET_INFO 1 /* H5Oget_info(_by_idx, _by_name)(2) */
+#define H5VL_NATIVE_OBJECT_SET_COMMENT 2 /* H5G|H5Oset_comment, H5Oset_comment_by_name */
+#define H5VL_NATIVE_OBJECT_DISABLE_MDC_FLUSHES 3 /* H5Odisable_mdc_flushes */
+#define H5VL_NATIVE_OBJECT_ENABLE_MDC_FLUSHES 4 /* H5Oenable_mdc_flushes */
+#define H5VL_NATIVE_OBJECT_ARE_MDC_FLUSHES_DISABLED 5 /* H5Oare_mdc_flushes_disabled */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Private functions */
+H5_DLL hid_t H5VL_native_register(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _H5VLnative_H */
+
diff --git a/src/H5VLnative_attr.c b/src/H5VLnative_attr.c
new file mode 100644
index 0000000..85af320
--- /dev/null
+++ b/src/H5VLnative_attr.c
@@ -0,0 +1,585 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Purpose: Attribute callbacks for the native VOL connector
+ *
+ */
+
+#define H5A_FRIEND /* Suppress error about including H5Apkg */
+
+#include "H5private.h" /* Generic Functions */
+#include "H5Apkg.h" /* Attributes */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fprivate.h" /* Files */
+#include "H5Gprivate.h" /* Groups */
+#include "H5Iprivate.h" /* IDs */
+#include "H5Pprivate.h" /* Property lists */
+#include "H5Sprivate.h" /* Dataspaces */
+#include "H5Tprivate.h" /* Datatypes */
+#include "H5VLprivate.h" /* Virtual Object Layer */
+
+#include "H5VLnative_private.h" /* Native VOL connector */
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_attr_create
+ *
+ * Purpose: Handles the attribute create callback
+ *
+ * Return: Success: attribute pointer
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VL__native_attr_create(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_name,
+ hid_t type_id, hid_t space_id, hid_t acpl_id, hid_t H5_ATTR_UNUSED aapl_id,
+ hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req)
+{
+ H5G_loc_t loc; /* Object location */
+ H5G_loc_t obj_loc; /* Location used to open group */
+ hbool_t loc_found = FALSE;
+ H5T_t *type, *dt; /* Datatype to use for attribute */
+ H5S_t *space; /* Dataspace to use for attribute */
+ H5A_t *attr = NULL;
+ void *ret_value = NULL;
+
+ FUNC_ENTER_PACKAGE
+
+ if(H5G_loc_real(obj, loc_params->obj_type, &loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file or file object")
+ if(0 == (H5F_INTENT(loc.oloc->file) & H5F_ACC_RDWR))
+ HGOTO_ERROR(H5E_ARGS, H5E_WRITEERROR, NULL, "no write intent on file")
+
+ if(NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a datatype")
+ /* If this is a named datatype, get the connector's pointer to the datatype */
+ type = H5T_get_actual_type(dt);
+
+ if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a data space")
+
+ if(loc_params->type == H5VL_OBJECT_BY_SELF) {
+ /* H5Acreate */
+ /* Go do the real work for attaching the attribute to the dataset */
+ if(NULL == (attr = H5A__create(&loc, attr_name, type, space, acpl_id)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "unable to create attribute")
+ } /* end if */
+ else if(loc_params->type == H5VL_OBJECT_BY_NAME) {
+ /* H5Acreate_by_name */
+ if(NULL == (attr = H5A__create_by_name(&loc, loc_params->loc_data.loc_by_name.name, attr_name, type, space, acpl_id)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "unable to create attribute")
+ } /* end else-if */
+ else
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, NULL, "unknown attribute create parameters")
+
+ ret_value = (void *)attr;
+
+done:
+ /* Release resources */
+ if(loc_found && H5G_loc_free(&obj_loc) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, NULL, "can't free location")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_attr_create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_attr_open
+ *
+ * Purpose: Handles the attribute open callback
+ *
+ * Return: Success: attribute pointer
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VL__native_attr_open(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_name,
+ hid_t H5_ATTR_UNUSED aapl_id, hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req)
+{
+ H5G_loc_t loc; /* Object location */
+ H5A_t *attr = NULL; /* Attribute opened */
+ void *ret_value;
+
+ FUNC_ENTER_PACKAGE
+
+ /* check arguments */
+ if(H5G_loc_real(obj, loc_params->obj_type, &loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file or file object")
+
+ if(loc_params->type == H5VL_OBJECT_BY_SELF) {
+ /* H5Aopen */
+ /* Open the attribute */
+ if(NULL == (attr = H5A__open(&loc, attr_name)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to open attribute: '%s'", attr_name)
+ } /* end if */
+ else if(loc_params->type == H5VL_OBJECT_BY_NAME) {
+ /* H5Aopen_by_name */
+ /* Open the attribute on the object header */
+ if(NULL == (attr = H5A__open_by_name(&loc, loc_params->loc_data.loc_by_name.name, attr_name)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "can't open attribute")
+ } /* end else-if */
+ else if(loc_params->type == H5VL_OBJECT_BY_IDX) {
+ /* H5Aopen_by_idx */
+ /* Open the attribute in the object header */
+ if(NULL == (attr = H5A__open_by_idx(&loc, loc_params->loc_data.loc_by_idx.name,
+ loc_params->loc_data.loc_by_idx.idx_type,
+ loc_params->loc_data.loc_by_idx.order,
+ loc_params->loc_data.loc_by_idx.n)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to open attribute")
+ } /* end else-if */
+ else
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, NULL, "unknown attribute open parameters")
+
+ ret_value = (void *)attr;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_attr_open() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_attr_read
+ *
+ * Purpose: Handles the attribute read callback
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL__native_attr_read(void *attr, hid_t dtype_id, void *buf,
+ hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req)
+{
+ H5T_t *mem_type; /* Memory datatype */
+ herr_t ret_value; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ if(NULL == (mem_type = (H5T_t *)H5I_object_verify(dtype_id, H5I_DATATYPE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
+
+ /* Go write the actual data to the attribute */
+ if((ret_value = H5A__read((H5A_t*)attr, mem_type, buf)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_READERROR, FAIL, "unable to read attribute")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_attr_read() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_attr_write
+ *
+ * Purpose: Handles the attribute write callback
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL__native_attr_write(void *attr, hid_t dtype_id, const void *buf,
+ hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req)
+{
+ H5T_t *mem_type; /* Memory datatype */
+ herr_t ret_value; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ if(NULL == (mem_type = (H5T_t *)H5I_object_verify(dtype_id, H5I_DATATYPE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
+
+ /* Go write the actual data to the attribute */
+ if((ret_value = H5A__write((H5A_t*)attr, mem_type, buf)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_WRITEERROR, FAIL, "unable to write attribute")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_attr_write() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_attr_get
+ *
+ * Purpose: Handles the attribute get callback
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL__native_attr_get(void *obj, H5VL_attr_get_t get_type,
+ hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req, va_list arguments)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ switch(get_type) {
+ /* H5Aget_space */
+ case H5VL_ATTR_GET_SPACE:
+ {
+ hid_t *ret_id = HDva_arg(arguments, hid_t *);
+ H5A_t *attr = (H5A_t *)obj;
+
+ if((*ret_id = H5A_get_space(attr)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTGET, FAIL, "can't get space ID of attribute")
+ break;
+ }
+
+ /* H5Aget_type */
+ case H5VL_ATTR_GET_TYPE:
+ {
+ hid_t *ret_id = HDva_arg(arguments, hid_t *);
+ H5A_t *attr = (H5A_t *)obj;
+
+ if((*ret_id = H5A__get_type(attr)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTGET, FAIL, "can't get datatype ID of attribute")
+ break;
+ }
+
+ /* H5Aget_create_plist */
+ case H5VL_ATTR_GET_ACPL:
+ {
+ hid_t *ret_id = HDva_arg(arguments, hid_t *);
+ H5A_t *attr = (H5A_t *)obj;
+
+ if((*ret_id = H5A__get_create_plist(attr)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTGET, FAIL, "can't get creation property list for attr")
+
+ break;
+ }
+
+ /* H5Aget_name */
+ case H5VL_ATTR_GET_NAME:
+ {
+ const H5VL_loc_params_t *loc_params = HDva_arg(arguments, const H5VL_loc_params_t *);
+ size_t buf_size = HDva_arg(arguments, size_t);
+ char *buf = HDva_arg(arguments, char *);
+ ssize_t *ret_val = HDva_arg(arguments, ssize_t *);
+ H5A_t *attr = NULL;
+
+ if(H5VL_OBJECT_BY_SELF == loc_params->type) {
+ attr = (H5A_t *)obj;
+ /* Call private function in turn */
+ if(0 > (*ret_val = H5A__get_name(attr, buf_size, buf)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't get attribute name")
+ }
+ else if(H5VL_OBJECT_BY_IDX == loc_params->type) {
+ H5G_loc_t loc;
+
+ /* check arguments */
+ if(H5G_loc_real(obj, loc_params->obj_type, &loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+
+ /* Open the attribute on the object header */
+ if(NULL == (attr = H5A__open_by_idx(&loc, loc_params->loc_data.loc_by_idx.name,
+ loc_params->loc_data.loc_by_idx.idx_type,
+ loc_params->loc_data.loc_by_idx.order,
+ loc_params->loc_data.loc_by_idx.n)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "can't open attribute")
+
+ /* Get the length of the name */
+ *ret_val = (ssize_t)HDstrlen(attr->shared->name);
+
+ /* Copy the name into the user's buffer, if given */
+ if(buf) {
+ HDstrncpy(buf, attr->shared->name, MIN((size_t)(*ret_val + 1), buf_size));
+ if((size_t)(*ret_val) >= buf_size)
+ buf[buf_size - 1]='\0';
+ } /* end if */
+
+ /* Release resources */
+ if(attr && H5A__close(attr) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "can't close attribute")
+ }
+ else
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get name of attr")
+
+ break;
+ }
+
+ /* H5Aget_info */
+ case H5VL_ATTR_GET_INFO:
+ {
+ const H5VL_loc_params_t *loc_params = HDva_arg(arguments, const H5VL_loc_params_t *);
+ H5A_info_t *ainfo = HDva_arg(arguments, H5A_info_t *);
+ H5A_t *attr = NULL;
+
+ if(H5VL_OBJECT_BY_SELF == loc_params->type) {
+ attr = (H5A_t *)obj;
+ if(H5A__get_info(attr, ainfo) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTGET, FAIL, "can't get attribute info")
+ }
+ else if(H5VL_OBJECT_BY_NAME == loc_params->type) {
+ char *attr_name = HDva_arg(arguments, char *);
+ H5G_loc_t loc;
+
+ /* check arguments */
+ if(H5G_loc_real(obj, loc_params->obj_type, &loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+
+ /* Open the attribute on the object header */
+ if(NULL == (attr = H5A__open_by_name(&loc, loc_params->loc_data.loc_by_name.name, attr_name)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "can't open attribute")
+
+ /* Get the attribute information */
+ if(H5A__get_info(attr, ainfo) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "unable to get attribute info")
+
+ /* Release resources */
+ if(attr && H5A__close(attr) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "can't close attribute")
+ }
+ else if(H5VL_OBJECT_BY_IDX == loc_params->type) {
+ H5G_loc_t loc;
+
+ /* check arguments */
+ if(H5G_loc_real(obj, loc_params->obj_type, &loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+
+ /* Open the attribute on the object header */
+ if(NULL == (attr = H5A__open_by_idx(&loc, loc_params->loc_data.loc_by_idx.name,
+ loc_params->loc_data.loc_by_idx.idx_type,
+ loc_params->loc_data.loc_by_idx.order,
+ loc_params->loc_data.loc_by_idx.n)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "can't open attribute")
+
+ /* Get the attribute information */
+ if(H5A__get_info(attr, ainfo) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "unable to get attribute info")
+
+ /* Release resources */
+ if(attr && H5A__close(attr) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "can't close attribute")
+ }
+ else
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get name of attr")
+
+ break;
+ }
+
+ case H5VL_ATTR_GET_STORAGE_SIZE:
+ {
+ hsize_t *ret = HDva_arg(arguments, hsize_t *);
+ H5A_t *attr = (H5A_t *)obj;
+
+ /* Set return value */
+ *ret = attr->shared->data_size;
+ break;
+ }
+
+ default:
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't get this type of information from attr")
+ } /* end switch */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_attr_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_attr_specific
+ *
+ * Purpose: Handles the attribute specific callback
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL__native_attr_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_attr_specific_t specific_type,
+ hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req, va_list arguments)
+{
+ H5G_loc_t loc;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Get location for passed-in object */
+ if(H5G_loc_real(obj, loc_params->obj_type, &loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+
+ switch(specific_type) {
+ case H5VL_ATTR_DELETE:
+ {
+ char *attr_name = HDva_arg(arguments, char *);
+
+ if(H5VL_OBJECT_BY_SELF == loc_params->type) {
+ /* H5Adelete */
+ /* Delete the attribute from the location */
+ if(H5O__attr_remove(loc.oloc, attr_name) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute")
+ } /* end if */
+ else if(H5VL_OBJECT_BY_NAME == loc_params->type) {
+ /* H5Adelete_by_name */
+ /* Delete the attribute */
+ if(H5A__delete_by_name(&loc, loc_params->loc_data.loc_by_name.name, attr_name) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute")
+ } /* end else-if */
+ else if(H5VL_OBJECT_BY_IDX == loc_params->type) {
+ /* H5Adelete_by_idx */
+ /* Delete the attribute from the location */
+ if(H5A__delete_by_idx(&loc, loc_params->loc_data.loc_by_idx.name, loc_params->loc_data.loc_by_idx.idx_type,
+ loc_params->loc_data.loc_by_idx.order, loc_params->loc_data.loc_by_idx.n) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute")
+ } /* end else-if */
+ else
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "unknown attribute remove parameters")
+ break;
+ }
+
+ case H5VL_ATTR_EXISTS:
+ {
+ const char *attr_name = HDva_arg(arguments, const char *);
+ htri_t *ret = HDva_arg(arguments, htri_t *);
+
+ if(loc_params->type == H5VL_OBJECT_BY_SELF) { /* H5Aexists */
+ /* Check if the attribute exists */
+ if((*ret = H5O__attr_exists(loc.oloc, attr_name)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "unable to determine if attribute exists")
+ } /* end if */
+ else if(loc_params->type == H5VL_OBJECT_BY_NAME) { /* H5Aexists_by_name */
+ /* Check if the attribute exists */
+ if((*ret = H5A__exists_by_name(loc, loc_params->loc_data.loc_by_name.name, attr_name)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "unable to determine if attribute exists")
+ } /* end else-if */
+ else
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "unknown parameters")
+ break;
+ }
+
+ case H5VL_ATTR_ITER:
+ {
+ H5_index_t idx_type = (H5_index_t)HDva_arg(arguments, int); /* enum work-around */
+ H5_iter_order_t order = (H5_iter_order_t)HDva_arg(arguments, int); /* enum work-around */
+ hsize_t *idx = HDva_arg(arguments, hsize_t *);
+ H5A_operator2_t op = HDva_arg(arguments, H5A_operator2_t);
+ void *op_data = HDva_arg(arguments, void *);
+
+ if(loc_params->type == H5VL_OBJECT_BY_SELF) { /* H5Aiterate2 */
+ /* Iterate over attributes */
+ if((ret_value = H5A__iterate(&loc, ".", idx_type, order, idx, op, op_data)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_BADITER, FAIL, "error iterating over attributes")
+ } /* end if */
+ else if(loc_params->type == H5VL_OBJECT_BY_NAME) { /* H5Aiterate_by_name */
+ /* Iterate over attributes by name */
+ if((ret_value = H5A__iterate(&loc, loc_params->loc_data.loc_by_name.name, idx_type, order, idx, op, op_data)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_BADITER, FAIL, "attribute iteration failed");
+ } /* end else-if */
+ else
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "unknown parameters")
+ break;
+ }
+
+ /* H5Arename/rename_by_name */
+ case H5VL_ATTR_RENAME:
+ {
+ const char *old_name = HDva_arg(arguments, const char *);
+ const char *new_name = HDva_arg(arguments, const char *);
+
+ if(loc_params->type == H5VL_OBJECT_BY_SELF) { /* H5Arename */
+ /* Call attribute rename routine */
+ if(H5O__attr_rename(loc.oloc, old_name, new_name) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTRENAME, FAIL, "can't rename attribute")
+ } /* end if */
+ else if(loc_params->type == H5VL_OBJECT_BY_NAME) { /* H5Arename_by_name */
+ /* Call attribute rename routine */
+ if(H5A__rename_by_name(loc, loc_params->loc_data.loc_by_name.name, old_name, new_name) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTRENAME, FAIL, "can't rename attribute")
+ } /* end else-if */
+ else
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "unknown attribute rename parameters")
+ break;
+ }
+
+ default:
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "invalid specific operation")
+ } /* end switch */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_attr_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_attr_optional
+ *
+ * Purpose: Handles the attribute optional callback
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL__native_attr_optional(void H5_ATTR_UNUSED *obj, hid_t H5_ATTR_UNUSED dxpl_id,
+ void H5_ATTR_UNUSED **req, va_list arguments)
+{
+ H5VL_native_attr_optional_t optional_type;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ optional_type = HDva_arg(arguments, H5VL_native_attr_optional_t);
+ switch(optional_type) {
+#ifndef H5_NO_DEPRECATED_SYMBOLS
+ case H5VL_NATIVE_ATTR_ITERATE_OLD:
+ {
+ hid_t loc_id = HDva_arg(arguments, hid_t);
+ unsigned *attr_num = HDva_arg(arguments, unsigned *);
+ H5A_operator1_t op = HDva_arg(arguments, H5A_operator1_t);
+ void *op_data = HDva_arg(arguments, void *);
+
+ /* Call the actual iteration routine */
+ if((ret_value = H5A__iterate_old(loc_id, attr_num, op, op_data)) < 0)
+ HERROR(H5E_VOL, H5E_BADITER, "error iterating over attributes");
+
+ break;
+ }
+#endif /* H5_NO_DEPRECATED_SYMBOLS */
+
+ default:
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "invalid optional operation")
+ } /* end switch */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_attr_optional() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_attr_close
+ *
+ * Purpose: Handles the attribute close callback
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL (attribute will not be closed)
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL__native_attr_close(void *attr, hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ if(H5A__close((H5A_t*)attr) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "can't close attribute")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_attr_close() */
+
diff --git a/src/H5VLnative_blob.c b/src/H5VLnative_blob.c
new file mode 100644
index 0000000..b16b407
--- /dev/null
+++ b/src/H5VLnative_blob.c
@@ -0,0 +1,237 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Purpose: Blob callbacks for the native VOL connector
+ */
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fprivate.h" /* File access */
+#include "H5HGprivate.h" /* Global Heaps */
+#include "H5VLnative_private.h" /* Native VOL connector */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_blob_put
+ *
+ * Purpose: Handles the blob 'put' callback
+ *
+ * Return: SUCCEED / FAIL
+ *
+ * Programmer: Quincey Koziol
+ * Friday, August 15, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL__native_blob_put(void *obj, const void *buf, size_t size, void *blob_id,
+ void H5_ATTR_UNUSED *ctx)
+{
+ H5F_t *f = (H5F_t *)obj; /* Retrieve file pointer */
+ uint8_t *id = (uint8_t *)blob_id; /* Pointer to blob ID */
+ H5HG_t hobjid; /* New VL sequence's heap ID */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Check parameters */
+ HDassert(f);
+ HDassert(size == 0 || buf);
+ HDassert(id);
+
+ /* Write the VL information to disk (allocates space also) */
+ if(H5HG_insert(f, size, (void *)buf, &hobjid) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_WRITEERROR, FAIL, "unable to write blob information")
+
+ /* Encode the heap information */
+ H5F_addr_encode(f, &id, hobjid.addr);
+ UINT32ENCODE(id, hobjid.idx);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_blob_put() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_blob_get
+ *
+ * Purpose: Handles the blob 'get' callback
+ *
+ * Return: SUCCEED / FAIL
+ *
+ * Programmer: Quincey Koziol
+ * Friday, August 15, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL__native_blob_get(void *obj, const void *blob_id, void *buf, size_t *size,
+ void H5_ATTR_UNUSED *ctx)
+{
+ H5F_t *f = (H5F_t *)obj; /* Retrieve file pointer */
+ const uint8_t *id = (const uint8_t *)blob_id; /* Pointer to the disk blob ID */
+ H5HG_t hobjid; /* Global heap ID for sequence */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(id);
+ HDassert(buf);
+
+ /* Get the heap information */
+ H5F_addr_decode(f, &id, &hobjid.addr);
+ UINT32DECODE(id, hobjid.idx);
+
+ /* Check if this sequence actually has any data */
+ if(hobjid.addr > 0)
+ /* Read the VL information from disk */
+ if(NULL == H5HG_read(f, &hobjid, buf, size))
+ HGOTO_ERROR(H5E_VOL, H5E_READERROR, FAIL, "unable to read VL information")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_blob_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_blob_specific
+ *
+ * Purpose: Handles the blob 'specific' callback
+ *
+ * Return: SUCCEED / FAIL
+ *
+ * Programmer: Quincey Koziol
+ * Friday, August 15, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL__native_blob_specific(void *obj, void *blob_id,
+ H5VL_blob_specific_t specific_type, va_list arguments)
+{
+ H5F_t *f = (H5F_t *)obj; /* Retrieve file pointer */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(blob_id);
+
+ switch(specific_type) {
+ case H5VL_BLOB_GETSIZE:
+ {
+ const uint8_t *id = (const uint8_t *)blob_id; /* Pointer to the blob ID */
+ size_t *size = HDva_arg(arguments, size_t *);
+ H5HG_t hobjid; /* blob's heap ID */
+
+ /* Get heap information */
+ H5F_addr_decode(f, &id, &(hobjid.addr));
+ UINT32DECODE(id, hobjid.idx);
+
+ /* Free heap object */
+ if(hobjid.addr > 0) {
+ if(H5HG_get_obj_size(f, &hobjid, size) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTREMOVE, FAIL, "unable to remove heap object")
+ } /* end if */
+ else
+ *size = 0; /* Return '0' size for 'nil' blob ID */
+
+ break;
+ }
+
+ case H5VL_BLOB_ISNULL:
+ {
+ const uint8_t *id = (const uint8_t *)blob_id; /* Pointer to the blob ID */
+ hbool_t *isnull = HDva_arg(arguments, hbool_t *);
+ haddr_t addr; /* Sequence's heap address */
+
+ /* Get the heap address */
+ H5F_addr_decode(f, &id, &addr);
+
+ /* Check if heap address is 'nil' */
+ *isnull = (addr == 0 ? TRUE : FALSE);
+
+ break;
+ }
+
+ case H5VL_BLOB_SETNULL:
+ {
+ uint8_t *id = (uint8_t *)blob_id; /* Pointer to the blob ID */
+ /* Encode the "nil" heap pointer information */
+ H5F_addr_encode(f, &id, (haddr_t)0);
+ UINT32ENCODE(id, 0);
+
+ break;
+ }
+
+ case H5VL_BLOB_DELETE:
+ {
+ const uint8_t *id = (const uint8_t *)blob_id; /* Pointer to the blob ID */
+ H5HG_t hobjid; /* VL sequence's heap ID */
+
+ /* Get heap information */
+ H5F_addr_decode(f, &id, &hobjid.addr);
+ UINT32DECODE(id, hobjid.idx);
+
+ /* Free heap object */
+ if(hobjid.addr > 0)
+ if(H5HG_remove(f, &hobjid) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTREMOVE, FAIL, "unable to remove heap object")
+
+ break;
+ }
+
+ default:
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "invalid specific operation")
+ } /* end switch */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_blob_specific() */
diff --git a/src/H5VLnative_dataset.c b/src/H5VLnative_dataset.c
new file mode 100644
index 0000000..676d859
--- /dev/null
+++ b/src/H5VLnative_dataset.c
@@ -0,0 +1,643 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Purpose: Dataset callbacks for the native VOL connector
+ *
+ */
+
+#define H5D_FRIEND /* Suppress error about including H5Dpkg */
+
+#include "H5private.h" /* Generic Functions */
+#include "H5Dpkg.h" /* Datasets */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fprivate.h" /* Files */
+#include "H5Gprivate.h" /* Groups */
+#include "H5Iprivate.h" /* IDs */
+#include "H5Pprivate.h" /* Property lists */
+#include "H5Sprivate.h" /* Dataspaces */
+#include "H5VLprivate.h" /* Virtual Object Layer */
+
+#include "H5VLnative_private.h" /* Native VOL connector */
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_dataset_create
+ *
+ * Purpose: Handles the dataset create callback
+ *
+ * Return: Success: dataset pointer
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VL__native_dataset_create(void *obj, const H5VL_loc_params_t *loc_params,
+ const char *name, hid_t lcpl_id, hid_t type_id, hid_t space_id,
+ hid_t dcpl_id, hid_t dapl_id, hid_t H5_ATTR_UNUSED dxpl_id,
+ void H5_ATTR_UNUSED **req)
+{
+ H5G_loc_t loc; /* Object location to insert dataset into */
+ H5D_t *dset = NULL; /* New dataset's info */
+ const H5S_t *space; /* Dataspace for dataset */
+ void *ret_value;
+
+ FUNC_ENTER_PACKAGE
+
+ /* Check arguments */
+ if(H5G_loc_real(obj, loc_params->obj_type, &loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file or file object")
+ if(H5I_DATATYPE != H5I_get_type(type_id))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a datatype ID")
+ if(NULL == (space = (const H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a dataspace ID")
+
+ /* H5Dcreate_anon */
+ if(NULL == name) {
+ /* build and open the new dataset */
+ if(NULL == (dset = H5D__create(loc.oloc->file, type_id, space, dcpl_id, dapl_id)))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to create dataset")
+ } /* end if */
+ /* H5Dcreate2 */
+ else {
+ /* Create the new dataset & get its ID */
+ if(NULL == (dset = H5D__create_named(&loc, name, type_id, space, lcpl_id, dcpl_id, dapl_id)))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to create dataset")
+ } /* end else */
+
+ ret_value = (void *)dset;
+
+done:
+ if(NULL == name) {
+ /* Release the dataset's object header, if it was created */
+ if(dset) {
+ H5O_loc_t *oloc; /* Object location for dataset */
+
+ /* Get the new dataset's object location */
+ if(NULL == (oloc = H5D_oloc(dset)))
+ HDONE_ERROR(H5E_DATASET, H5E_CANTGET, NULL, "unable to get object location of dataset")
+
+ /* Decrement refcount on dataset's object header in memory */
+ if(H5O_dec_rc_by_loc(oloc) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTDEC, NULL, "unable to decrement refcount on newly created object")
+ } /* end if */
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_dataset_create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_dataset_open
+ *
+ * Purpose: Handles the dataset open callback
+ *
+ * Return: Success: dataset pointer
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VL__native_dataset_open(void *obj, const H5VL_loc_params_t *loc_params, const char *name,
+ hid_t dapl_id, hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req)
+{
+ H5D_t *dset = NULL;
+ H5G_loc_t loc; /* Object location of group */
+ void *ret_value = NULL;
+
+ FUNC_ENTER_PACKAGE
+
+ if(H5G_loc_real(obj, loc_params->obj_type, &loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file or file object")
+
+ /* Open the dataset */
+ if(NULL == (dset = H5D__open_name(&loc, name, dapl_id)))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, NULL, "unable to open dataset")
+
+ ret_value = (void *)dset;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_dataset_open() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_dataset_read
+ *
+ * Purpose: Handles the dataset read callback
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+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 H5_ATTR_UNUSED dxpl_id, void *buf,
+ void H5_ATTR_UNUSED **req)
+{
+ H5D_t *dset = (H5D_t *)obj;
+ const H5S_t *mem_space = NULL;
+ const H5S_t *file_space = NULL;
+ 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")
+
+ /* Get validated dataspace pointers */
+ if(H5S_get_validated_dataspace(mem_space_id, &mem_space) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "could not get a validated dataspace from mem_space_id")
+ if(H5S_get_validated_dataspace(file_space_id, &file_space) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "could not get a validated dataspace from file_space_id")
+
+ /* Read raw data */
+ if(H5D__read(dset, mem_type_id, mem_space, file_space, buf/*out*/) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read data")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_dataset_read() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_dataset_write
+ *
+ * Purpose: Handles the dataset write callback
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+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 H5_ATTR_UNUSED dxpl_id, const void *buf,
+ void H5_ATTR_UNUSED **req)
+{
+ H5D_t *dset = (H5D_t *)obj;
+ const H5S_t *mem_space = NULL;
+ const H5S_t *file_space = NULL;
+ 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")
+
+ /* Get validated dataspace pointers */
+ if(H5S_get_validated_dataspace(mem_space_id, &mem_space) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "could not get a validated dataspace from mem_space_id")
+ if(H5S_get_validated_dataspace(file_space_id, &file_space) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "could not get a validated dataspace from file_space_id")
+
+ /* Write the data */
+ if(H5D__write(dset, mem_type_id, mem_space, file_space, buf) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write data")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_dataset_write() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_dataset_get
+ *
+ * Purpose: Handles the dataset get callback
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL__native_dataset_get(void *obj, H5VL_dataset_get_t get_type,
+ hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req, va_list arguments)
+{
+ H5D_t *dset = (H5D_t *)obj;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ switch(get_type) {
+ /* H5Dget_space */
+ case H5VL_DATASET_GET_SPACE:
+ {
+ hid_t *ret_id = HDva_arg(arguments, hid_t *);
+
+ if((*ret_id = H5D__get_space(dset)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTGET, FAIL, "can't get space ID of dataset")
+
+ break;
+ }
+
+ /* H5Dget_space_statuc */
+ case H5VL_DATASET_GET_SPACE_STATUS:
+ {
+ H5D_space_status_t *allocation = HDva_arg(arguments, H5D_space_status_t *);
+
+ /* Read data space address and return */
+ if(H5D__get_space_status(dset, allocation) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to get space status")
+
+ break;
+ }
+
+ /* H5Dget_type */
+ case H5VL_DATASET_GET_TYPE:
+ {
+ hid_t *ret_id = HDva_arg(arguments, hid_t *);
+
+ if((*ret_id = H5D__get_type(dset)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTGET, FAIL, "can't get datatype ID of dataset")
+
+ break;
+ }
+
+ /* H5Dget_create_plist */
+ case H5VL_DATASET_GET_DCPL:
+ {
+ hid_t *ret_id = HDva_arg(arguments, hid_t *);
+
+ if((*ret_id = H5D_get_create_plist(dset)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTGET, FAIL, "can't get creation property list for dataset")
+
+ break;
+ }
+
+ /* H5Dget_access_plist */
+ case H5VL_DATASET_GET_DAPL:
+ {
+ hid_t *ret_id = HDva_arg(arguments, hid_t *);
+
+ if((*ret_id = H5D_get_access_plist(dset)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTGET, FAIL, "can't get access property list for dataset")
+
+ break;
+ }
+
+ /* H5Dget_storage_size */
+ case H5VL_DATASET_GET_STORAGE_SIZE:
+ {
+ hsize_t *ret = HDva_arg(arguments, hsize_t *);
+
+ /* Set return value */
+ if(H5D__get_storage_size(dset, ret) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get size of dataset's storage")
+ break;
+ }
+
+ /* H5Dget_offset */
+ case H5VL_DATASET_GET_OFFSET:
+ {
+ haddr_t *ret = HDva_arg(arguments, haddr_t *);
+
+ /* Set return value */
+ *ret = H5D__get_offset(dset);
+ if(!H5F_addr_defined(*ret))
+ *ret = HADDR_UNDEF;
+ break;
+ }
+
+ default:
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't get this type of information from dataset")
+ } /* end switch */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_dataset_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_dataset_specific
+ *
+ * Purpose: Handles the dataset specific callback
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL__native_dataset_specific(void *obj, H5VL_dataset_specific_t specific_type,
+ hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req, va_list arguments)
+{
+ H5D_t *dset = (H5D_t *)obj;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ switch(specific_type) {
+ /* H5Dspecific_space */
+ case H5VL_DATASET_SET_EXTENT:
+ { /* H5Dset_extent (H5Dextend - deprecated) */
+ const hsize_t *size = HDva_arg(arguments, const hsize_t *);
+
+ if(H5D__set_extent(dset, size) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to set extent of dataset")
+ break;
+ }
+
+ case H5VL_DATASET_FLUSH:
+ { /* H5Dflush */
+ hid_t dset_id = HDva_arg(arguments, hid_t);
+
+ /* Flush the dataset */
+ if(H5D__flush(dset, dset_id) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTFLUSH, FAIL, "unable to flush dataset")
+
+ break;
+ }
+
+ case H5VL_DATASET_REFRESH:
+ { /* H5Drefresh */
+ hid_t dset_id = HDva_arg(arguments, hid_t);
+
+ /* Refresh the dataset */
+ if((H5D__refresh(dset_id, dset)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTLOAD, FAIL, "unable to refresh dataset")
+
+ break;
+ }
+
+ default:
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "invalid specific operation")
+ } /* end switch */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_dataset_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_dataset_optional
+ *
+ * Purpose: Handles the dataset optional callback
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL__native_dataset_optional(void *obj, hid_t H5_ATTR_UNUSED dxpl_id,
+ void H5_ATTR_UNUSED **req, va_list arguments)
+{
+ H5D_t *dset = NULL; /* Dataset */
+ H5VL_native_dataset_optional_t optional_type = HDva_arg(arguments, H5VL_native_dataset_optional_t);
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ switch(optional_type) {
+ case H5VL_NATIVE_DATASET_FORMAT_CONVERT:
+ { /* H5Dformat_convert */
+ dset = (H5D_t *)obj;
+
+ switch(dset->shared->layout.type) {
+ case H5D_CHUNKED:
+ /* Convert the chunk indexing type to version 1 B-tree if not */
+ if(dset->shared->layout.u.chunk.idx_type != H5D_CHUNK_IDX_BTREE)
+ if((H5D__format_convert(dset)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTLOAD, FAIL, "unable to downgrade chunk indexing type for dataset")
+ break;
+
+ case H5D_CONTIGUOUS:
+ case H5D_COMPACT:
+ /* Downgrade the layout version to 3 if greater than 3 */
+ if(dset->shared->layout.version > H5O_LAYOUT_VERSION_DEFAULT)
+ if((H5D__format_convert(dset)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTLOAD, FAIL, "unable to downgrade layout version for dataset")
+ break;
+
+ case H5D_VIRTUAL:
+ /* Nothing to do even though layout is version 4 */
+ break;
+
+ case H5D_LAYOUT_ERROR:
+ case H5D_NLAYOUTS:
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid dataset layout type")
+
+ default:
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "unknown dataset layout type")
+ } /* end switch */
+
+ break;
+ }
+
+ case H5VL_NATIVE_DATASET_GET_CHUNK_INDEX_TYPE:
+ { /* H5Dget_chunk_index_type */
+ H5D_chunk_index_t *idx_type = HDva_arg(arguments, H5D_chunk_index_t *);
+
+ dset = (H5D_t *)obj;
+
+ /* Make sure the dataset is chunked */
+ if(H5D_CHUNKED != dset->shared->layout.type)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a chunked dataset")
+
+ /* Get the chunk indexing type */
+ *idx_type = dset->shared->layout.u.chunk.idx_type;
+
+ break;
+ }
+
+ case H5VL_NATIVE_DATASET_GET_CHUNK_STORAGE_SIZE:
+ { /* H5Dget_chunk_storage_size */
+ hsize_t *offset = HDva_arg(arguments, hsize_t *);
+ hsize_t *chunk_nbytes = HDva_arg(arguments, hsize_t *);
+
+ dset = (H5D_t *)obj;
+
+ /* Make sure the dataset is chunked */
+ if(H5D_CHUNKED != dset->shared->layout.type)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a chunked dataset")
+
+ /* Call private function */
+ if(H5D__get_chunk_storage_size(dset, offset, chunk_nbytes) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get storage size of chunk")
+
+ break;
+ }
+
+ case H5VL_NATIVE_DATASET_GET_NUM_CHUNKS:
+ { /* H5Dget_num_chunks */
+ const H5S_t *space = NULL;
+ hid_t space_id = HDva_arg(arguments, hid_t);
+ hsize_t *nchunks = HDva_arg(arguments, hsize_t *);
+
+ dset = (H5D_t *)obj;
+ HDassert(dset);
+ HDassert(dset->shared);
+ HDassert(dset->shared->space);
+
+ /* When default dataspace is given, use the dataset's dataspace */
+ if(space_id == H5S_ALL)
+ space = dset->shared->space;
+ else /* otherwise, use the given space ID */
+ if(NULL == (space = (const H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a valid dataspace ID")
+
+ /* Make sure the dataset is chunked */
+ if(H5D_CHUNKED != dset->shared->layout.type)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a chunked dataset")
+
+ /* Call private function */
+ if(H5D__get_num_chunks(dset, space, nchunks) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get number of chunks")
+
+ break;
+ }
+
+ case H5VL_NATIVE_DATASET_GET_CHUNK_INFO_BY_IDX:
+ { /* H5Dget_chunk_info */
+ const H5S_t *space = NULL;
+ hid_t space_id = HDva_arg(arguments, hid_t);
+ hsize_t chk_index = HDva_arg(arguments, hsize_t);
+ hsize_t *offset = HDva_arg(arguments, hsize_t *);
+ unsigned *filter_mask = HDva_arg(arguments, unsigned *);
+ haddr_t *addr = HDva_arg(arguments, haddr_t *);
+ hsize_t *size = HDva_arg(arguments, hsize_t *);
+
+ dset = (H5D_t *)obj;
+ HDassert(dset);
+ HDassert(dset->shared);
+ HDassert(dset->shared->space);
+
+ /* When default dataspace is given, use the dataset's dataspace */
+ if(space_id == H5S_ALL)
+ space = dset->shared->space;
+ else /* otherwise, use the given space ID */
+ if(NULL == (space = (const H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a valid dataspace ID")
+
+ /* Make sure the dataset is chunked */
+ if(H5D_CHUNKED != dset->shared->layout.type)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a chunked dataset")
+
+ /* Call private function */
+ if(H5D__get_chunk_info(dset, space, chk_index, offset, filter_mask, addr, size) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk info by index")
+ break;
+ }
+
+ case H5VL_NATIVE_DATASET_GET_CHUNK_INFO_BY_COORD:
+ { /* H5Dget_chunk_info_by_coord */
+ hsize_t *offset = HDva_arg(arguments, hsize_t *);
+ unsigned *filter_mask = HDva_arg(arguments, unsigned *);
+ haddr_t *addr = HDva_arg(arguments, haddr_t *);
+ hsize_t *size = HDva_arg(arguments, hsize_t *);
+
+ dset = (H5D_t *)obj;
+ HDassert(dset);
+ HDassert(dset->shared);
+
+ /* Make sure the dataset is chunked */
+ if(H5D_CHUNKED != dset->shared->layout.type)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a chunked dataset")
+
+ /* Call private function */
+ if(H5D__get_chunk_info_by_coord(dset, offset, filter_mask, addr, size) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk info by its logical coordinates")
+
+ break;
+ }
+
+ case H5VL_NATIVE_DATASET_CHUNK_READ:
+ { /* H5Dread_chunk */
+ const hsize_t *offset = HDva_arg(arguments, hsize_t *);
+ uint32_t *filters = HDva_arg(arguments, uint32_t *);
+ void *buf = HDva_arg(arguments, void *);
+ hsize_t offset_copy[H5O_LAYOUT_NDIMS]; /* Internal copy of chunk offset */
+
+ dset = (H5D_t *)obj;
+
+ /* Check arguments */
+ if(NULL == dset->oloc.file)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dataset is not associated with a file")
+ if(H5D_CHUNKED != dset->shared->layout.type)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a chunked dataset")
+
+ /* Copy the user's offset array so we can be sure it's terminated properly.
+ * (we don't want to mess with the user's buffer).
+ */
+ if(H5D__get_offset_copy(dset, offset, offset_copy) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "failure to copy offset array")
+
+ /* Read the raw chunk */
+ if(H5D__chunk_direct_read(dset, offset_copy, filters, buf) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read unprocessed chunk data")
+
+ break;
+ }
+
+ case H5VL_NATIVE_DATASET_CHUNK_WRITE:
+ { /* H5Dwrite_chunk */
+ uint32_t filters = HDva_arg(arguments, uint32_t);
+ const hsize_t *offset = HDva_arg(arguments, const hsize_t *);
+ uint32_t data_size_32 = HDva_arg(arguments, uint32_t);
+ const void *buf = HDva_arg(arguments, const void *);
+ hsize_t offset_copy[H5O_LAYOUT_NDIMS]; /* Internal copy of chunk offset */
+
+ dset = (H5D_t *)obj;
+
+ /* Check arguments */
+ if(NULL == dset->oloc.file)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dataset is not associated with a file")
+ if(H5D_CHUNKED != dset->shared->layout.type)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a chunked dataset")
+
+ /* Copy the user's offset array so we can be sure it's terminated properly.
+ * (we don't want to mess with the user's buffer).
+ */
+ if(H5D__get_offset_copy(dset, offset, offset_copy) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "failure to copy offset array")
+
+ /* Write chunk */
+ if(H5D__chunk_direct_write(dset, filters, offset_copy, data_size_32, buf) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write unprocessed chunk data")
+
+ break;
+ }
+
+ default:
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "invalid optional operation")
+ } /* end switch */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_dataset_optional() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_dataset_close
+ *
+ * Purpose: Handles the dataset close callback
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL (dataset will not be closed)
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL__native_dataset_close(void *dset, hid_t H5_ATTR_UNUSED dxpl_id,
+ void H5_ATTR_UNUSED **req)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ if(H5D_close((H5D_t*)dset) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTDEC, FAIL, "can't close dataset")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_dataset_close() */
+
diff --git a/src/H5VLnative_datatype.c b/src/H5VLnative_datatype.c
new file mode 100644
index 0000000..3c9463d
--- /dev/null
+++ b/src/H5VLnative_datatype.c
@@ -0,0 +1,265 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Purpose: Datatype callbacks for the native VOL connector
+ *
+ */
+
+#define H5T_FRIEND /* Suppress error about including H5Tpkg */
+
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Gprivate.h" /* Groups */
+#include "H5Iprivate.h" /* IDs */
+#include "H5Oprivate.h" /* Object headers */
+#include "H5Pprivate.h" /* Property lists */
+#include "H5Tpkg.h" /* Datatypes */
+#include "H5VLprivate.h" /* Virtual Object Layer */
+
+#include "H5VLnative_private.h" /* Native VOL connector */
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_datatype_commit
+ *
+ * Purpose: Handles the datatype commit callback
+ *
+ * Return: Success: datatype pointer
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VL__native_datatype_commit(void *obj, const H5VL_loc_params_t *loc_params, const char *name,
+ hid_t type_id, hid_t lcpl_id, hid_t tcpl_id, hid_t H5_ATTR_UNUSED tapl_id,
+ hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req)
+{
+ H5G_loc_t loc; /* Location to commit datatype */
+ H5T_t *dt; /* Datatype for ID */
+ H5T_t *type = NULL; /* copy of the original type which will be committed */
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* check arguments */
+ if(H5G_loc_real(obj, loc_params->obj_type, &loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file or file object")
+
+ if(NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a datatype")
+
+ /* Check arguments. We cannot commit an immutable type because H5Tclose()
+ * normally fails on such types (try H5Tclose(H5T_NATIVE_INT)) but closing
+ * a named type should always succeed.
+ */
+ if(H5T_STATE_NAMED == dt->shared->state || H5T_STATE_OPEN == dt->shared->state)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "datatype is already committed")
+ if(H5T_STATE_IMMUTABLE == dt->shared->state)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "datatype is immutable")
+
+ /* Check for a "sensible" datatype to store on disk */
+ if(H5T_is_sensible(dt) <= 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "datatype is not sensible")
+
+ /* Copy the datatype - the copied one will be the type that is
+ * committed, and attached to original datatype above the VOL
+ * layer
+ */
+ if(NULL == (type = H5T_copy(dt, H5T_COPY_TRANSIENT)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy");
+
+ /* Commit the datatype */
+ if(NULL != name) {
+ /* H5Tcommit */
+ if(H5T__commit_named(&loc, name, type, lcpl_id, tcpl_id) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to commit datatype")
+ } /* end if */
+ else {
+ /* H5Tcommit_anon */
+ if(H5T__commit_anon(loc.oloc->file, type, tcpl_id) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to commit datatype")
+ } /* end else */
+
+ ret_value = (void *)type;
+
+done:
+ if(NULL == ret_value && type)
+ H5T_close(type);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_datatype_commit() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_datatype_open
+ *
+ * Purpose: Handles the datatype open callback
+ *
+ * Return: Success: datatype pointer
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VL__native_datatype_open(void *obj, const H5VL_loc_params_t *loc_params, const char *name,
+ hid_t H5_ATTR_UNUSED tapl_id, hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req)
+{
+ H5T_t *type = NULL; /* Datatype opened in file */
+ H5G_loc_t loc; /* Group location of object to open */
+ void *ret_value = NULL;
+
+ FUNC_ENTER_PACKAGE
+
+ if(H5G_loc_real(obj, loc_params->obj_type, &loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file or file object")
+
+ /* Open the datatype */
+ if(NULL == (type = H5T__open_name(&loc, name)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to open named datatype")
+
+ type->vol_obj = NULL;
+
+ ret_value = (void *)type;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_datatype_open() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_datatype_get
+ *
+ * Purpose: Handles the datatype get callback
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL__native_datatype_get(void *obj, H5VL_datatype_get_t get_type,
+ hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req, va_list arguments)
+{
+ H5T_t *dt = (H5T_t *)obj;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ switch (get_type) {
+ case H5VL_DATATYPE_GET_BINARY:
+ {
+ ssize_t *nalloc = HDva_arg(arguments, ssize_t *);
+ void *buf = HDva_arg(arguments, void *);
+ size_t size = HDva_arg(arguments, size_t);
+
+ if(H5T_encode(dt, (unsigned char *)buf, &size) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't determine serialized length of datatype")
+
+ *nalloc = (ssize_t) size;
+ break;
+ }
+
+ /* H5Tget_create_plist */
+ case H5VL_DATATYPE_GET_TCPL:
+ {
+ hid_t *ret_id = HDva_arg(arguments, hid_t *);
+
+ if(H5I_INVALID_HID == (*ret_id = H5T__get_create_plist(dt)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "can't get object creation info");
+
+ break;
+ }
+
+ default:
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't get this type of information from datatype")
+ } /* end switch */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_datatype_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_datatype_specific
+ *
+ * Purpose: Handles the datatype specific callback
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL__native_datatype_specific(void *obj, H5VL_datatype_specific_t specific_type,
+ hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req, va_list arguments)
+{
+ H5T_t *dt = (H5T_t *)obj;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ switch(specific_type) {
+ case H5VL_DATATYPE_FLUSH:
+ {
+ hid_t type_id = HDva_arg(arguments, hid_t);
+
+ /* To flush metadata and invoke flush callback if there is */
+ if(H5O_flush_common(&dt->oloc, type_id) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFLUSH, FAIL, "unable to flush datatype")
+
+ break;
+ }
+
+ case H5VL_DATATYPE_REFRESH:
+ {
+ hid_t type_id = HDva_arg(arguments, hid_t);
+
+ /* Call private function to refresh datatype object */
+ if((H5O_refresh_metadata(type_id, dt->oloc)) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTLOAD, FAIL, "unable to refresh datatype")
+
+ break;
+ }
+
+ default:
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "invalid specific operation")
+ } /* end switch */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_datatype_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_datatype_close
+ *
+ * Purpose: Handles the datatype close callback
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL (datatype will not be closed)
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL__native_datatype_close(void *dt, hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ if(H5T_close((H5T_t*)dt) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "can't close datatype")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_datatype_close() */
+
diff --git a/src/H5VLnative_file.c b/src/H5VLnative_file.c
new file mode 100644
index 0000000..0decc62
--- /dev/null
+++ b/src/H5VLnative_file.c
@@ -0,0 +1,881 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Purpose: File callbacks for the native VOL connector
+ *
+ */
+
+#define H5F_FRIEND /* Suppress error about including H5Fpkg */
+
+#include "H5private.h" /* Generic Functions */
+#include "H5ACprivate.h" /* Metadata cache */
+#include "H5Cprivate.h" /* Cache */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fpkg.h" /* Files */
+#include "H5Gprivate.h" /* Groups */
+#include "H5Iprivate.h" /* IDs */
+#include "H5MFprivate.h" /* File memory management */
+#include "H5Pprivate.h" /* Property lists */
+#include "H5PBprivate.h" /* Page buffering */
+#include "H5VLprivate.h" /* Virtual Object Layer */
+
+#include "H5VLnative_private.h" /* Native VOL connector */
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_file_create
+ *
+ * Purpose: Handles the file create callback
+ *
+ * Return: Success: file pointer
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VL__native_file_create(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id,
+ hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req)
+{
+ H5F_t *new_file = NULL;
+ void *ret_value = NULL;
+
+ FUNC_ENTER_PACKAGE
+
+ /* Adjust bit flags by turning on the creation bit and making sure that
+ * the EXCL or TRUNC bit is set. All newly-created files are opened for
+ * reading and writing.
+ */
+ if(0 == (flags & (H5F_ACC_EXCL|H5F_ACC_TRUNC)))
+ flags |= H5F_ACC_EXCL; /* default */
+ flags |= H5F_ACC_RDWR | H5F_ACC_CREAT;
+
+ /* Create the file */
+ if(NULL == (new_file = H5F_open(name, flags, fcpl_id, fapl_id)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to create file")
+ new_file->id_exists = TRUE;
+
+ ret_value = (void *)new_file;
+
+done:
+ if(NULL == ret_value && new_file)
+ if(H5F__close(new_file) < 0)
+ HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, NULL, "problems closing file")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_file_create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_file_open
+ *
+ * Purpose: Handles the file open callback
+ *
+ * Return: Success: file pointer
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VL__native_file_open(const char *name, unsigned flags, hid_t fapl_id,
+ hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req)
+{
+ H5F_t *new_file = NULL;
+ void *ret_value = NULL;
+
+ FUNC_ENTER_PACKAGE
+
+ /* Open the file */
+ if(NULL == (new_file = H5F_open(name, flags, H5P_FILE_CREATE_DEFAULT, fapl_id)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file")
+ new_file->id_exists = TRUE;
+
+ ret_value = (void *)new_file;
+
+done:
+ if(NULL == ret_value && new_file && H5F_try_close(new_file, NULL) < 0)
+ HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, NULL, "problems closing file")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_file_open() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_file_get
+ *
+ * Purpose: Handles the file get callback
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL__native_file_get(void *obj, H5VL_file_get_t get_type,
+ hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req, va_list arguments)
+{
+ H5F_t *f = NULL; /* File struct */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ switch(get_type) {
+ /* "get container info" */
+ case H5VL_FILE_GET_CONT_INFO:
+ {
+ H5VL_file_cont_info_t *info = HDva_arg(arguments, H5VL_file_cont_info_t *);
+
+ /* Retrieve the file's container info */
+ if(H5F__get_cont_info((H5F_t *)obj, info) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get file container info")
+
+ break;
+ }
+
+ /* H5Fget_access_plist */
+ case H5VL_FILE_GET_FAPL:
+ {
+ H5P_genplist_t *new_plist; /* New property list */
+ hid_t *plist_id = HDva_arg(arguments, hid_t *);
+
+ f = (H5F_t *)obj;
+
+ /* Retrieve the file's access property list */
+ if((*plist_id = H5F_get_access_plist(f, TRUE)) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get file access property list")
+
+ if(NULL == (new_plist = (H5P_genplist_t *)H5I_object(*plist_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
+ break;
+ }
+
+ /* H5Fget_create_plist */
+ case H5VL_FILE_GET_FCPL:
+ {
+ H5P_genplist_t *plist; /* Property list */
+ hid_t *plist_id = HDva_arg(arguments, hid_t *);
+
+ f = (H5F_t *)obj;
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(f->shared->fcpl_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
+
+ /* Create the property list object to return */
+ if((*plist_id = H5P_copy_plist(plist, TRUE)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "unable to copy file creation properties")
+
+ break;
+ }
+
+ /* H5Fget_intent */
+ case H5VL_FILE_GET_INTENT:
+ {
+ unsigned *intent_flags = HDva_arg(arguments, unsigned *);
+
+ f = (H5F_t *)obj;
+
+ /* HDF5 uses some flags internally that users don't know about.
+ * Simplify things for them so that they only get either H5F_ACC_RDWR
+ * or H5F_ACC_RDONLY and any SWMR flags.
+ */
+ if(H5F_INTENT(f) & H5F_ACC_RDWR) {
+ *intent_flags = H5F_ACC_RDWR;
+
+ /* Check for SWMR write access on the file */
+ if(H5F_INTENT(f) & H5F_ACC_SWMR_WRITE)
+ *intent_flags |= H5F_ACC_SWMR_WRITE;
+ } /* end if */
+ else {
+ *intent_flags = H5F_ACC_RDONLY;
+
+ /* Check for SWMR read access on the file */
+ if(H5F_INTENT(f) & H5F_ACC_SWMR_READ)
+ *intent_flags |= H5F_ACC_SWMR_READ;
+ } /* end else */
+
+ break;
+ }
+
+ /* H5Fget_fileno */
+ case H5VL_FILE_GET_FILENO:
+ {
+ unsigned long *fileno = HDva_arg(arguments, unsigned long *);
+ unsigned long my_fileno = 0;
+
+ f = (H5F_t *)obj;
+ H5F_GET_FILENO(f, my_fileno);
+ *fileno = my_fileno; /* sigh */
+
+ break;
+ }
+
+ /* H5Fget_name */
+ case H5VL_FILE_GET_NAME:
+ {
+ H5I_type_t type = (H5I_type_t)HDva_arg(arguments, int); /* enum work-around */
+ size_t size = HDva_arg(arguments, size_t);
+ char *name = HDva_arg(arguments, char *);
+ ssize_t *ret = HDva_arg(arguments, ssize_t *);
+ size_t len;
+
+ if(NULL == (f = H5F__get_file(obj, type)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+
+ len = HDstrlen(H5F_OPEN_NAME(f));
+
+ if(name) {
+ HDstrncpy(name, H5F_OPEN_NAME(f), MIN(len + 1,size));
+ if(len >= size)
+ name[size-1]='\0';
+ } /* end if */
+
+ /* Set the return value for the API call */
+ *ret = (ssize_t)len;
+ break;
+ }
+
+ /* H5Fget_obj_count */
+ case H5VL_FILE_GET_OBJ_COUNT:
+ {
+ unsigned types = HDva_arg(arguments, unsigned);
+ ssize_t *ret = HDva_arg(arguments, ssize_t *);
+ size_t obj_count = 0; /* Number of opened objects */
+
+ f = (H5F_t *)obj;
+ /* Perform the query */
+ if(H5F_get_obj_count(f, types, TRUE, &obj_count) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "H5F_get_obj_count failed")
+
+ /* Set the return value */
+ *ret = (ssize_t)obj_count;
+ break;
+ }
+
+ /* H5Fget_obj_ids */
+ case H5VL_FILE_GET_OBJ_IDS:
+ {
+ unsigned types = HDva_arg(arguments, unsigned);
+ size_t max_objs = HDva_arg(arguments, size_t);
+ hid_t *oid_list = HDva_arg(arguments, hid_t *);
+ ssize_t *ret = HDva_arg(arguments, ssize_t *);
+ size_t obj_count = 0; /* Number of opened objects */
+
+ f = (H5F_t *)obj;
+ /* Perform the query */
+ if(H5F_get_obj_ids(f, types, max_objs, oid_list, TRUE, &obj_count) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "H5F_get_obj_ids failed")
+
+ /* Set the return value */
+ *ret = (ssize_t)obj_count;
+ break;
+ }
+
+ default:
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't get this type of information")
+ } /* end switch */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_file_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_file_specific
+ *
+ * Purpose: Handles the file specific callback
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL__native_file_specific(void *obj, H5VL_file_specific_t specific_type,
+ hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req, va_list arguments)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ switch(specific_type) {
+ /* H5Fflush */
+ case H5VL_FILE_FLUSH:
+ {
+ H5I_type_t type = (H5I_type_t)HDva_arg(arguments, int); /* enum work-around */
+ H5F_scope_t scope = (H5F_scope_t)HDva_arg(arguments, int); /* enum work-around */
+ H5F_t *f = NULL; /* File to flush */
+
+ /* Get the file for the object */
+ if(NULL == (f = H5F__get_file(obj, type)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+
+ /* Nothing to do if the file is read only. This determination is
+ * made at the shared open(2) flags level, implying that opening a
+ * file twice, once for read-only and once for read-write, and then
+ * calling H5Fflush() with the read-only handle, still causes data
+ * to be flushed.
+ */
+ if(H5F_ACC_RDWR & H5F_INTENT(f)) {
+ /* Flush other files, depending on scope */
+ if(H5F_SCOPE_GLOBAL == scope) {
+ /* Call the flush routine for mounted file hierarchies */
+ if(H5F_flush_mounts(f) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush mounted file hierarchy")
+ } /* end if */
+ else {
+ /* Call the flush routine, for this file */
+ if(H5F__flush(f) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush file's cached information")
+ } /* end else */
+ } /* end if */
+ break;
+ }
+
+ /* H5Freopen */
+ case H5VL_FILE_REOPEN:
+ {
+ void **ret = HDva_arg(arguments, void **);
+ H5F_t *new_file = NULL;
+
+ /* Reopen the file through the VOL connector */
+ if(NULL == (new_file = H5F__reopen((H5F_t *)obj)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to reopen file")
+ new_file->id_exists = TRUE;
+
+ *ret = (void *)new_file;
+ break;
+ }
+
+ /* H5Fmount */
+ case H5VL_FILE_MOUNT:
+ {
+ H5I_type_t type = (H5I_type_t)HDva_arg(arguments, int); /* enum work-around */
+ const char *name = HDva_arg(arguments, const char *);
+ H5F_t *child = HDva_arg(arguments, H5F_t *);
+ hid_t plist_id = HDva_arg(arguments, hid_t);
+ H5G_loc_t loc;
+
+ if(H5G_loc_real(obj, type, &loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+
+ /* Do the mount */
+ if(H5F__mount(&loc, name, child, plist_id) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "unable to mount file")
+
+ break;
+ }
+
+ /* H5Funmount */
+ case H5VL_FILE_UNMOUNT:
+ {
+ H5I_type_t type = (H5I_type_t)HDva_arg(arguments, int); /* enum work-around */
+ const char *name = HDva_arg(arguments, const char *);
+ H5G_loc_t loc;
+
+ if(H5G_loc_real(obj, type, &loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+
+ /* Unmount */
+ if(H5F__unmount(&loc, name) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "unable to unmount file")
+
+ break;
+ }
+
+ /* H5Fis_accessible */
+ case H5VL_FILE_IS_ACCESSIBLE:
+ {
+ hid_t fapl_id = HDva_arg(arguments, hid_t);
+ const char *name = HDva_arg(arguments, const char *);
+ htri_t *ret = HDva_arg(arguments, htri_t *);
+
+ /* Call private routine */
+ if((*ret = H5F__is_hdf5(name, fapl_id)) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "error in HDF5 file check")
+ break;
+ }
+
+ /* H5Fdelete */
+ case H5VL_FILE_DELETE:
+ {
+ HGOTO_ERROR(H5E_FILE, H5E_UNSUPPORTED, FAIL, "H5Fdelete() is currently not supported in the native VOL connector")
+ break;
+ }
+
+ default:
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "invalid specific operation")
+ } /* end switch */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_file_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_file_optional
+ *
+ * Purpose: Handles the file optional callback
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL__native_file_optional(void *obj, hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req, va_list arguments)
+{
+ H5F_t *f = NULL; /* File */
+ H5VL_native_file_optional_t optional_type = HDva_arg(arguments, H5VL_native_file_optional_t);
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ f = (H5F_t *)obj;
+ switch(optional_type) {
+ /* H5Fget_filesize */
+ case H5VL_NATIVE_FILE_GET_SIZE:
+ {
+ haddr_t max_eof_eoa; /* Maximum of the EOA & EOF */
+ haddr_t base_addr; /* Base address for the file */
+ hsize_t *size = HDva_arg(arguments, hsize_t *);
+
+ /* Go get the actual file size */
+ if(H5F__get_max_eof_eoa(f, &max_eof_eoa) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "file can't get max eof/eoa ")
+
+ base_addr = H5FD_get_base_addr(f->shared->lf);
+
+ if(size)
+ *size = (hsize_t)(max_eof_eoa + base_addr); /* Convert relative base address for file to absolute address */
+
+ break;
+ }
+
+ /* H5Fget_file_image */
+ case H5VL_NATIVE_FILE_GET_FILE_IMAGE:
+ {
+ void *buf_ptr = HDva_arg(arguments, void *);
+ ssize_t *ret = HDva_arg(arguments, ssize_t *);
+ size_t buf_len = HDva_arg(arguments, size_t );
+
+ /* Do the actual work */
+ if((*ret = H5F__get_file_image(f, buf_ptr, buf_len)) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "get file image failed")
+ break;
+ }
+
+ /* H5Fget_freespace */
+ case H5VL_NATIVE_FILE_GET_FREE_SPACE:
+ {
+ hsize_t tot_space; /* Amount of free space in the file */
+ hssize_t *ret = HDva_arg(arguments, hssize_t *);
+
+ /* Go get the actual amount of free space in the file */
+ if(H5MF_get_freespace(f, &tot_space, NULL) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to check free space for file")
+ *ret = (hssize_t)tot_space;
+ break;
+ }
+
+ /* H5Fget_free_sections */
+ case H5VL_NATIVE_FILE_GET_FREE_SECTIONS:
+ {
+ H5F_sect_info_t *sect_info = HDva_arg(arguments, H5F_sect_info_t *);
+ ssize_t *ret = HDva_arg(arguments, ssize_t *);
+ H5F_mem_t type = (H5F_mem_t)HDva_arg(arguments, int); /* enum work-around */
+ size_t nsects = HDva_arg(arguments, size_t);
+
+ /* Go get the free-space section information in the file */
+ if((*ret = H5MF_get_free_sections(f, type, nsects, sect_info)) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to check free space for file")
+ break;
+ }
+
+ /* H5Fget_info1/2 */
+ case H5VL_NATIVE_FILE_GET_INFO:
+ {
+ H5I_type_t type = (H5I_type_t)HDva_arg(arguments, int); /* enum work-around */
+ H5F_info2_t *finfo = HDva_arg(arguments, H5F_info2_t *);
+
+ /* Get the file struct. This call is careful to not return the file pointer
+ * for the top file in a mount hierarchy.
+ */
+ if(NULL == (f = H5F__get_file(obj, type)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "could not get a file struct")
+
+ /* Get the file info */
+ if(H5F__get_info(f, finfo) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to retrieve file info")
+
+ break;
+ }
+
+ /* H5Fget_mdc_config */
+ case H5VL_NATIVE_FILE_GET_MDC_CONF:
+ {
+ H5AC_cache_config_t *config_ptr = HDva_arg(arguments, H5AC_cache_config_t *);
+
+ /* Go get the resize configuration */
+ if(H5AC_get_cache_auto_resize_config(f->shared->cache, config_ptr) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5AC_get_cache_auto_resize_config() failed.")
+ break;
+ }
+
+ /* H5Fget_mdc_hit_rate */
+ case H5VL_NATIVE_FILE_GET_MDC_HR:
+ {
+ double *hit_rate_ptr = HDva_arg(arguments, double *);
+
+ /* Go get the current hit rate */
+ if(H5AC_get_cache_hit_rate(f->shared->cache, hit_rate_ptr) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5AC_get_cache_hit_rate() failed.")
+ break;
+ }
+
+ /* H5Fget_mdc_size */
+ case H5VL_NATIVE_FILE_GET_MDC_SIZE:
+ {
+ size_t *max_size_ptr = HDva_arg(arguments, size_t *);
+ size_t *min_clean_size_ptr = HDva_arg(arguments, size_t *);
+ size_t *cur_size_ptr = HDva_arg(arguments, size_t *);
+ int *cur_num_entries_ptr = HDva_arg(arguments, int *);
+ uint32_t cur_num_entries;
+
+ /* Go get the size data */
+ if(H5AC_get_cache_size(f->shared->cache, max_size_ptr, min_clean_size_ptr,
+ cur_size_ptr, &cur_num_entries) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5AC_get_cache_size() failed.")
+
+ if(cur_num_entries_ptr != NULL)
+ *cur_num_entries_ptr = (int)cur_num_entries;
+ break;
+ }
+
+ /* H5Fget_vfd_handle */
+ case H5VL_NATIVE_FILE_GET_VFD_HANDLE:
+ {
+ void **file_handle = HDva_arg(arguments, void **);
+ hid_t fapl_id = HDva_arg(arguments, hid_t);
+
+ /* Retrieve the VFD handle for the file */
+ if(H5F_get_vfd_handle(f, fapl_id, file_handle) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't retrieve VFD handle")
+ break;
+ }
+
+ /* H5Iget_file_id */
+ case H5VL_NATIVE_FILE_GET_FILE_ID:
+ {
+ H5I_type_t type = (H5I_type_t)HDva_arg(arguments, int); /* enum work-around */
+ hbool_t app_ref = (hbool_t)HDva_arg(arguments, int);
+ hid_t *file_id = HDva_arg(arguments, hid_t *);
+
+ if(NULL == (f = H5F__get_file(obj, type)))
+ HGOTO_ERROR(H5E_FILE, H5E_BADTYPE, FAIL, "not a file or file object")
+ if((*file_id = H5F__get_file_id(f, app_ref)) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get file ID")
+ break;
+ }
+
+ /* H5Fclear_elink_file_cache */
+ case H5VL_NATIVE_FILE_CLEAR_ELINK_CACHE:
+ {
+ /* Release the EFC */
+ if(f->shared->efc)
+ if(H5F__efc_release(f->shared->efc) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't release external file cache")
+ break;
+ }
+
+ /* H5Freset_mdc_hit_rate_stats */
+ case H5VL_NATIVE_FILE_RESET_MDC_HIT_RATE:
+ {
+ /* Reset the hit rate statistic */
+ if(H5AC_reset_cache_hit_rate_stats(f->shared->cache) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "can't reset cache hit rate")
+ break;
+ }
+
+ /* H5Fset_mdc_config */
+ case H5VL_NATIVE_FILE_SET_MDC_CONFIG:
+ {
+ H5AC_cache_config_t *config_ptr = HDva_arg(arguments, H5AC_cache_config_t *);
+
+ /* set the resize configuration */
+ if(H5AC_set_cache_auto_resize_config(f->shared->cache, config_ptr) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "H5AC_set_cache_auto_resize_config() failed")
+ break;
+ }
+
+ /* H5Fget_metadata_read_retry_info */
+ case H5VL_NATIVE_FILE_GET_METADATA_READ_RETRY_INFO:
+ {
+ H5F_retry_info_t *info = HDva_arg(arguments, H5F_retry_info_t *);
+
+ if(H5F_get_metadata_read_retry_info(f, info) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "can't get metadata read retry info")
+
+ break;
+ }
+
+ /* H5Fstart_swmr_write */
+ case H5VL_NATIVE_FILE_START_SWMR_WRITE:
+ {
+ if(H5F__start_swmr_write(f) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "can't start SWMR write")
+
+ break;
+ }
+
+ /* H5Fstart_mdc_logging */
+ case H5VL_NATIVE_FILE_START_MDC_LOGGING:
+ {
+ /* Call mdc logging function */
+ if(H5C_start_logging(f->shared->cache) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_LOGGING, FAIL, "unable to start mdc logging")
+
+ break;
+ }
+
+ /* H5Fstop_mdc_logging */
+ case H5VL_NATIVE_FILE_STOP_MDC_LOGGING:
+ {
+ /* Call mdc logging function */
+ if(H5C_stop_logging(f->shared->cache) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_LOGGING, FAIL, "unable to stop mdc logging")
+
+ break;
+ }
+
+ /* H5Fget_mdc_logging_status */
+ case H5VL_NATIVE_FILE_GET_MDC_LOGGING_STATUS:
+ {
+ hbool_t *is_enabled = HDva_arg(arguments, hbool_t *);
+ hbool_t *is_currently_logging = HDva_arg(arguments, hbool_t *);
+
+ /* Call mdc logging function */
+ if(H5C_get_logging_status(f->shared->cache, is_enabled, is_currently_logging) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_LOGGING, FAIL, "unable to get logging status")
+
+ break;
+ }
+
+ /* H5Fformat_convert */
+ case H5VL_NATIVE_FILE_FORMAT_CONVERT:
+ {
+ /* Convert the format */
+ if(H5F__format_convert(f) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCONVERT, FAIL, "can't convert file format")
+
+ break;
+ }
+
+ /* H5Freset_page_buffering_stats */
+ case H5VL_NATIVE_FILE_RESET_PAGE_BUFFERING_STATS:
+ {
+ /* Sanity check */
+ if(NULL == f->shared->pb_ptr)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "page buffering not enabled on file")
+
+ /* Reset the statistics */
+ if(H5PB_reset_stats(f->shared->pb_ptr) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't reset stats for page buffering")
+
+ break;
+ }
+
+ /* H5Fget_page_buffering_stats */
+ case H5VL_NATIVE_FILE_GET_PAGE_BUFFERING_STATS:
+ {
+ unsigned *accesses = HDva_arg(arguments, unsigned *);
+ unsigned *hits = HDva_arg(arguments, unsigned *);
+ unsigned *misses = HDva_arg(arguments, unsigned *);
+ unsigned *evictions = HDva_arg(arguments, unsigned *);
+ unsigned *bypasses = HDva_arg(arguments, unsigned *);
+
+ /* Sanity check */
+ if(NULL == f->shared->pb_ptr)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "page buffering not enabled on file")
+
+ /* Get the statistics */
+ if(H5PB_get_stats(f->shared->pb_ptr, accesses, hits, misses, evictions, bypasses) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't retrieve stats for page buffering")
+
+ break;
+ }
+
+ /* H5Fget_mdc_image_info */
+ case H5VL_NATIVE_FILE_GET_MDC_IMAGE_INFO:
+ {
+ haddr_t *image_addr = HDva_arg(arguments, haddr_t *);
+ hsize_t *image_len = HDva_arg(arguments, hsize_t *);
+
+ /* Go get the address and size of the cache image */
+ if(H5AC_get_mdc_image_info(f->shared->cache, image_addr, image_len) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't retrieve cache image info")
+
+ break;
+ }
+
+ /* H5Fget_eoa */
+ case H5VL_NATIVE_FILE_GET_EOA:
+ {
+ haddr_t *eoa = HDva_arg(arguments, haddr_t *);
+ haddr_t rel_eoa; /* Relative address of EOA */
+
+ /* Sanity check */
+ HDassert(eoa);
+
+ /* This routine will work only for drivers with this feature enabled.*/
+ /* We might introduce a new feature flag in the future */
+ if(!H5F_HAS_FEATURE(f, H5FD_FEAT_SUPPORTS_SWMR_IO))
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "must use a SWMR-compatible VFD for this public routine")
+
+ /* The real work */
+ if(HADDR_UNDEF == (rel_eoa = H5F_get_eoa(f, H5FD_MEM_DEFAULT)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "get_eoa request failed")
+
+ /* Set return value */
+ /* (Note compensating for base address subtraction in internal routine) */
+ *eoa = rel_eoa + H5F_get_base_addr(f);
+
+ break;
+ }
+
+ /* H5Fincrement_filesize */
+ case H5VL_NATIVE_FILE_INCR_FILESIZE:
+ {
+ hsize_t increment = HDva_arg(arguments, hsize_t);
+ haddr_t max_eof_eoa; /* Maximum of the relative EOA & EOF */
+
+ /* This public routine will work only for drivers with this feature enabled.*/
+ /* We might introduce a new feature flag in the future */
+ if(!H5F_HAS_FEATURE(f, H5FD_FEAT_SUPPORTS_SWMR_IO))
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "must use a SWMR-compatible VFD for this public routine")
+
+ /* Get the maximum of EOA and EOF */
+ if(H5F__get_max_eof_eoa(f, &max_eof_eoa) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "file can't get max eof/eoa ")
+
+ /* Set EOA to the maximum value + increment */
+ if(H5F__set_eoa(f, H5FD_MEM_DEFAULT, max_eof_eoa + increment) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "driver set_eoa request failed")
+
+ break;
+ }
+
+ /* H5Fset_latest_format, H5Fset_libver_bounds */
+ case H5VL_NATIVE_FILE_SET_LIBVER_BOUNDS:
+ {
+ H5F_libver_t low = (H5F_libver_t)HDva_arg(arguments, int); /* enum work-around */
+ H5F_libver_t high = (H5F_libver_t)HDva_arg(arguments, int); /* enum work-around */
+
+ /* Call internal set_libver_bounds function */
+ if(H5F__set_libver_bounds(f, low, high) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "cannot set low/high bounds")
+
+ break;
+ }
+
+ /* H5Fget_dset_no_attrs_hint */
+ case H5VL_NATIVE_FILE_GET_MIN_DSET_OHDR_FLAG:
+ {
+ hbool_t *minimize = HDva_arg(arguments, hbool_t *);
+ *minimize = H5F_GET_MIN_DSET_OHDR(f);
+ break;
+ }
+
+ /* H5Fset_dset_no_attrs_hint */
+ case H5VL_NATIVE_FILE_SET_MIN_DSET_OHDR_FLAG:
+ {
+ int minimize = HDva_arg(arguments, int);
+ if(H5F_set_min_dset_ohdr(f, (hbool_t)minimize) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "cannot set file's dataset object header minimization flag")
+ break;
+ }
+
+#ifdef H5_HAVE_PARALLEL
+ /* H5Fget_mpi_atomicity */
+ case H5VL_NATIVE_FILE_GET_MPI_ATOMICITY:
+ {
+ hbool_t *flag = (hbool_t *)HDva_arg(arguments, hbool_t *);
+ if (H5F_get_mpi_atomicity(f, flag) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "cannot get MPI atomicity");
+ break;
+ }
+
+ /* H5Fset_mpi_atomicity */
+ case H5VL_NATIVE_FILE_SET_MPI_ATOMICITY:
+ {
+ hbool_t flag = (hbool_t)HDva_arg(arguments, int);
+ if (H5F_set_mpi_atomicity(f, flag) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "cannot set MPI atomicity");
+ break;
+ }
+#endif /* H5_HAVE_PARALLEL */
+
+ default:
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "invalid optional operation")
+ } /* end switch */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_file_optional() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_file_close
+ *
+ * Purpose: Handles the file close callback
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL (file will not be closed)
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL__native_file_close(void *file, hid_t H5_ATTR_UNUSED dxpl_id,
+ void H5_ATTR_UNUSED **req)
+{
+ int nref;
+ H5F_t *f = (H5F_t *)file;
+ hid_t file_id = H5I_INVALID_HID;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* This routine should only be called when a file ID's ref count drops to zero */
+ HDassert(H5F_ID_EXISTS(f));
+
+ /* Flush file if this is the last reference to this id and we have write
+ * intent, unless it will be flushed by the "shared" file being closed.
+ * This is only necessary to replicate previous behaviour, and could be
+ * disabled by an option/property to improve performance.
+ */
+ if((H5F_NREFS(f) > 1) && (H5F_INTENT(f) & H5F_ACC_RDWR)) {
+ /* Get the file ID corresponding to the H5F_t struct */
+ if(H5I_find_id(f, H5I_FILE, &file_id) < 0 || H5I_INVALID_HID == file_id)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, FAIL, "invalid atom")
+
+ /* Get the number of references outstanding for this file ID */
+ if((nref = H5I_get_ref(file_id, FALSE)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, FAIL, "can't get ID ref count")
+ if(nref == 1)
+ if(H5F__flush(f) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush cache")
+ } /* end if */
+
+ /* Close the file */
+ if(H5F__close(f) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTDEC, FAIL, "can't close file")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_file_close() */
+
diff --git a/src/H5VLnative_group.c b/src/H5VLnative_group.c
new file mode 100644
index 0000000..b6bef7f
--- /dev/null
+++ b/src/H5VLnative_group.c
@@ -0,0 +1,353 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Purpose: Group callbacks for the native VOL connector
+ *
+ */
+
+#define H5G_FRIEND /* Suppress error about including H5Gpkg */
+
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Gpkg.h" /* Groups */
+#include "H5Iprivate.h" /* IDs */
+#include "H5Oprivate.h" /* Object headers */
+#include "H5Pprivate.h" /* Property lists */
+#include "H5VLprivate.h" /* Virtual Object Layer */
+
+#include "H5VLnative_private.h" /* Native VOL connector */
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_group_create
+ *
+ * Purpose: Handles the group create callback
+ *
+ * Return: Success: group pointer
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VL__native_group_create(void *obj, const H5VL_loc_params_t *loc_params, const char *name,
+ hid_t lcpl_id, hid_t gcpl_id, hid_t H5_ATTR_UNUSED gapl_id,
+ hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req)
+{
+ H5G_loc_t loc; /* Location to create group */
+ H5G_t *grp = NULL; /* New group created */
+ void *ret_value;
+
+ FUNC_ENTER_PACKAGE
+
+ /* Set up the location */
+ if(H5G_loc_real(obj, loc_params->obj_type, &loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file or file object")
+
+ /* if name is NULL then this is from H5Gcreate_anon */
+ if(name == NULL) {
+ H5G_obj_create_t gcrt_info; /* Information for group creation */
+
+ /* Set up group creation info */
+ gcrt_info.gcpl_id = gcpl_id;
+ gcrt_info.cache_type = H5G_NOTHING_CACHED;
+ HDmemset(&gcrt_info.cache, 0, sizeof(gcrt_info.cache));
+
+ /* Create the new group & get its ID */
+ if(NULL == (grp = H5G__create(loc.oloc->file, &gcrt_info)))
+ HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "unable to create group")
+ } /* end if */
+ /* otherwise it's from H5Gcreate */
+ else {
+ /* Create the new group & get its ID */
+ if(NULL == (grp = H5G__create_named(&loc, name, lcpl_id, gcpl_id)))
+ HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "unable to create group")
+ } /* end else */
+
+ ret_value = (void *)grp;
+
+done:
+ if(name == NULL) {
+ /* Release the group's object header, if it was created */
+ if(grp) {
+ H5O_loc_t *oloc; /* Object location for group */
+
+ /* Get the new group's object location */
+ if(NULL == (oloc = H5G_oloc(grp)))
+ HDONE_ERROR(H5E_SYM, H5E_CANTGET, NULL, "unable to get object location of group")
+
+ /* Decrement refcount on group's object header in memory */
+ if(H5O_dec_rc_by_loc(oloc) < 0)
+ HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "unable to decrement refcount on newly created object")
+ } /* end if */
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_group_create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_group_open
+ *
+ * Purpose: Handles the group open callback
+ *
+ * Return: Success: group pointer
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VL__native_group_open(void *obj, const H5VL_loc_params_t *loc_params, const char *name,
+ hid_t H5_ATTR_UNUSED gapl_id, hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req)
+{
+ H5G_loc_t loc; /* Location to open group */
+ H5G_t *grp = NULL; /* New group opend */
+ void *ret_value;
+
+ FUNC_ENTER_PACKAGE
+
+ /* Set up the location */
+ if(H5G_loc_real(obj, loc_params->obj_type, &loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file or file object")
+
+ /* Open the group */
+ if((grp = H5G__open_name(&loc, name)) == NULL)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, NULL, "unable to open group")
+
+ ret_value = (void *)grp;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_group_open() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_group_get
+ *
+ * Purpose: Handles the group get callback
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL__native_group_get(void *obj, H5VL_group_get_t get_type,
+ hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req, va_list arguments)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ switch(get_type) {
+ /* H5Gget_create_plist */
+ case H5VL_GROUP_GET_GCPL:
+ {
+ hid_t *new_gcpl_id = HDva_arg(arguments, hid_t *);
+ H5G_t *grp = (H5G_t *)obj;
+
+ if((*new_gcpl_id = H5G_get_create_plist(grp)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTGET, FAIL, "can't get creation property list for group")
+ break;
+ }
+
+ /* H5Gget_info */
+ case H5VL_GROUP_GET_INFO:
+ {
+ const H5VL_loc_params_t *loc_params = HDva_arg(arguments, const H5VL_loc_params_t *);
+ H5G_info_t *group_info = HDva_arg(arguments, H5G_info_t *);
+ H5G_loc_t loc;
+
+ if(H5G_loc_real(obj, loc_params->obj_type, &loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+
+ if(loc_params->type == H5VL_OBJECT_BY_SELF) {
+ /* H5Gget_info */
+
+ /* Retrieve the group's information */
+ if(H5G__obj_info(loc.oloc, group_info) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve group info")
+ } /* end if */
+ else if(loc_params->type == H5VL_OBJECT_BY_NAME) {
+ /* H5Gget_info_by_name */
+
+ /* Retrieve the group's information */
+ if(H5G__get_info_by_name(&loc, loc_params->loc_data.loc_by_name.name, group_info) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve group info")
+ } /* end else-if */
+ else if(loc_params->type == H5VL_OBJECT_BY_IDX) {
+ /* H5Gget_info_by_idx */
+
+ /* Retrieve the group's information */
+ if(H5G__get_info_by_idx(&loc, loc_params->loc_data.loc_by_idx.name, loc_params->loc_data.loc_by_idx.idx_type,
+ loc_params->loc_data.loc_by_idx.order, loc_params->loc_data.loc_by_idx.n, group_info) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve group info")
+ } /* end else-if */
+ else
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "unknown get info parameters")
+ break;
+ }
+
+ default:
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't get this type of information from group")
+ } /* end switch */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_group_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_group_specific
+ *
+ * Purpose: Handles the group specific callback
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL__native_group_specific(void *obj, H5VL_group_specific_t specific_type,
+ hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req, va_list arguments)
+{
+ H5G_t *grp = (H5G_t *)obj;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ switch(specific_type) {
+ case H5VL_GROUP_FLUSH:
+ {
+ hid_t group_id = HDva_arg(arguments, hid_t);
+
+ /* Flush object's metadata to file */
+ if(H5O_flush_common(&grp->oloc, group_id) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTFLUSH, FAIL, "unable to flush group")
+
+ break;
+ }
+
+ case H5VL_GROUP_REFRESH:
+ {
+ hid_t group_id = HDva_arg(arguments, hid_t);
+
+ /* Call private function to refresh group object */
+ if((H5O_refresh_metadata(group_id, grp->oloc)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, FAIL, "unable to refresh group")
+
+ break;
+ }
+
+ default:
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "invalid specific operation")
+ } /* end switch */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_group_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_group_optional
+ *
+ * Purpose: Handles the group optional callback
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL__native_group_optional(void *obj, hid_t H5_ATTR_UNUSED dxpl_id,
+ void H5_ATTR_UNUSED **req, va_list arguments)
+{
+ H5VL_native_group_optional_t optional_type;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ optional_type = HDva_arg(arguments, H5VL_native_group_optional_t);
+ switch(optional_type) {
+#ifndef H5_NO_DEPRECATED_SYMBOLS
+ /* H5Giterate (deprecated) */
+ case H5VL_NATIVE_GROUP_ITERATE_OLD:
+ {
+ const H5VL_loc_params_t *loc_params = HDva_arg(arguments, const H5VL_loc_params_t *);
+ hsize_t idx = HDva_arg(arguments, hsize_t);
+ hsize_t *last_obj = HDva_arg(arguments, hsize_t *);
+ const H5G_link_iterate_t *lnk_op = HDva_arg(arguments, const H5G_link_iterate_t *);
+ void *op_data = HDva_arg(arguments, void *);
+ H5G_loc_t grp_loc;
+
+ /* Get the location struct for the object */
+ if(H5G_loc_real(obj, loc_params->obj_type, &grp_loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+
+ /* Call the actual iteration routine */
+ if((ret_value = H5G_iterate(&grp_loc, loc_params->loc_data.loc_by_name.name, H5_INDEX_NAME, H5_ITER_INC, idx, last_obj, lnk_op, op_data)) < 0)
+ HERROR(H5E_VOL, H5E_BADITER, "error iterating over group's links");
+
+ break;
+ }
+
+ /* H5Gget_objinfo (deprecated) */
+ case H5VL_NATIVE_GROUP_GET_OBJINFO:
+ {
+ const H5VL_loc_params_t *loc_params = HDva_arg(arguments, const H5VL_loc_params_t *);
+ hbool_t follow_link = (hbool_t)HDva_arg(arguments, unsigned);
+ H5G_stat_t *statbuf = HDva_arg(arguments, H5G_stat_t *);
+ H5G_loc_t grp_loc;
+
+ /* Get the location struct for the object */
+ if(H5G_loc_real(obj, loc_params->obj_type, &grp_loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+
+ /* Call the actual group objinfo routine */
+ if(H5G__get_objinfo(&grp_loc, loc_params->loc_data.loc_by_name.name, follow_link, statbuf) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "cannot stat object")
+
+ break;
+ }
+#endif /* H5_NO_DEPRECATED_SYMBOLS */
+
+ default:
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "invalid optional operation")
+ } /* end switch */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_group_optional() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_group_close
+ *
+ * Purpose: Handles the group close callback
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL (group will not be closed)
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL__native_group_close(void *grp, hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ if(H5G_close((H5G_t *)grp) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close group")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_group_close() */
+
diff --git a/src/H5VLnative_link.c b/src/H5VLnative_link.c
new file mode 100644
index 0000000..5d5935d
--- /dev/null
+++ b/src/H5VLnative_link.c
@@ -0,0 +1,419 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Purpose: Link callbacks for the native VOL connector
+ *
+ */
+
+#define H5L_FRIEND /* Suppress error about including H5Lpkg */
+
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Gprivate.h" /* Groups */
+#include "H5Iprivate.h" /* IDs */
+#include "H5Lpkg.h" /* Links */
+#include "H5Pprivate.h" /* Property lists */
+#include "H5VLprivate.h" /* Virtual Object Layer */
+
+#include "H5VLnative_private.h" /* Native VOL connector */
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_link_create
+ *
+ * Purpose: Handles the link create callback
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL__native_link_create(H5VL_link_create_type_t create_type, void *obj,
+ const H5VL_loc_params_t *loc_params, hid_t lcpl_id, hid_t H5_ATTR_UNUSED lapl_id,
+ hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req, va_list arguments)
+{
+ H5P_genplist_t *plist; /* Property list pointer */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Get the plist structure */
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(lcpl_id)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID");
+
+ switch(create_type) {
+ case H5VL_LINK_CREATE_HARD:
+ {
+ H5G_loc_t cur_loc;
+ H5G_loc_t link_loc;
+ void *cur_obj = HDva_arg(arguments, void *);
+ H5VL_loc_params_t *cur_params = HDva_arg(arguments, H5VL_loc_params_t *);
+
+ if(NULL != cur_obj && H5G_loc_real(cur_obj, cur_params->obj_type, &cur_loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+ if(NULL != obj && H5G_loc_real(obj, loc_params->obj_type, &link_loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+
+ /* H5Lcreate_hard */
+ if(H5VL_OBJECT_BY_NAME == cur_params->type) {
+ H5G_loc_t *cur_loc_p, *link_loc_p;
+
+ /* Set up current & new location pointers */
+ cur_loc_p = &cur_loc;
+ link_loc_p = &link_loc;
+ if(NULL == cur_obj)
+ cur_loc_p = link_loc_p;
+ else if(NULL == obj)
+ link_loc_p = cur_loc_p;
+ else if(cur_loc_p->oloc->file != link_loc_p->oloc->file)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "source and destination should be in the same file.")
+
+ /* Create the link */
+ if((ret_value = H5L_create_hard(cur_loc_p, cur_params->loc_data.loc_by_name.name,
+ link_loc_p, loc_params->loc_data.loc_by_name.name, lcpl_id)) < 0)
+ HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "unable to create link")
+ } /* end if */
+ else { /* H5Olink */
+ /* Link to the object */
+ if(H5L_link(&link_loc, loc_params->loc_data.loc_by_name.name, &cur_loc, lcpl_id) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to create link")
+ } /* end else */
+ break;
+ }
+
+ case H5VL_LINK_CREATE_SOFT:
+ {
+ char *target_name = HDva_arg(arguments, char *);
+ H5G_loc_t link_loc; /* Group location for new link */
+
+ if(H5G_loc_real(obj, loc_params->obj_type, &link_loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+
+ /* Create the link */
+ if((ret_value = H5L_create_soft(target_name, &link_loc, loc_params->loc_data.loc_by_name.name, lcpl_id)) < 0)
+ HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "unable to create link")
+ break;
+ }
+
+ case H5VL_LINK_CREATE_UD:
+ {
+ H5G_loc_t link_loc; /* Group location for new link */
+ H5L_type_t link_type = (H5L_type_t)HDva_arg(arguments, int);
+ void *udata = HDva_arg(arguments, void *);
+ size_t udata_size = HDva_arg(arguments, size_t);
+
+ if(H5G_loc_real(obj, loc_params->obj_type, &link_loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+
+ /* Create link */
+ if(H5L__create_ud(&link_loc, loc_params->loc_data.loc_by_name.name, udata, udata_size, link_type, lcpl_id) < 0)
+ HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "unable to create link")
+ break;
+ }
+
+ default:
+ HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "invalid link creation call")
+ } /* end switch */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_link_create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_link_copy
+ *
+ * Purpose: Handles the link copy callback
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL__native_link_copy(void *src_obj, const H5VL_loc_params_t *loc_params1,
+ void *dst_obj, const H5VL_loc_params_t *loc_params2, hid_t lcpl_id,
+ hid_t H5_ATTR_UNUSED lapl_id, hid_t H5_ATTR_UNUSED dxpl_id,
+ void H5_ATTR_UNUSED **req)
+{
+ H5G_loc_t src_loc, *src_loc_p;
+ H5G_loc_t dst_loc, *dst_loc_p;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ if(NULL != src_obj && H5G_loc_real(src_obj, loc_params1->obj_type, &src_loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+ if(NULL != dst_obj && H5G_loc_real(dst_obj, loc_params2->obj_type, &dst_loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+
+ /* Set up src & dst location pointers */
+ src_loc_p = &src_loc;
+ dst_loc_p = &dst_loc;
+ if(NULL == src_obj)
+ src_loc_p = dst_loc_p;
+ else if(NULL == dst_obj)
+ dst_loc_p = src_loc_p;
+
+ /* Copy the link */
+ if(H5L_move(src_loc_p, loc_params1->loc_data.loc_by_name.name,
+ dst_loc_p, loc_params2->loc_data.loc_by_name.name,
+ TRUE, lcpl_id) < 0)
+ HGOTO_ERROR(H5E_LINK, H5E_CANTCOPY, FAIL, "unable to copy link")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_link_copy() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_link_move
+ *
+ * Purpose: Handles the link move callback
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL__native_link_move(void *src_obj, const H5VL_loc_params_t *loc_params1,
+ void *dst_obj, const H5VL_loc_params_t *loc_params2, hid_t lcpl_id,
+ hid_t H5_ATTR_UNUSED lapl_id, hid_t H5_ATTR_UNUSED dxpl_id,
+ void H5_ATTR_UNUSED **req)
+{
+ H5G_loc_t src_loc, *src_loc_p;
+ H5G_loc_t dst_loc, *dst_loc_p;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ if(NULL != src_obj && H5G_loc_real(src_obj, loc_params1->obj_type, &src_loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+ if(NULL != dst_obj && H5G_loc_real(dst_obj, loc_params2->obj_type, &dst_loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+
+ /* Set up src & dst location pointers */
+ src_loc_p = &src_loc;
+ dst_loc_p = &dst_loc;
+ if(NULL == src_obj)
+ src_loc_p = dst_loc_p;
+ else if(NULL == dst_obj)
+ dst_loc_p = src_loc_p;
+
+ /* Move the link */
+ if(H5L_move(src_loc_p, loc_params1->loc_data.loc_by_name.name,
+ dst_loc_p, loc_params2->loc_data.loc_by_name.name,
+ FALSE, lcpl_id) < 0)
+ HGOTO_ERROR(H5E_LINK, H5E_CANTMOVE, FAIL, "unable to move link")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_link_move() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_link_get
+ *
+ * Purpose: Handles the link get callback
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL__native_link_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_get_t get_type,
+ hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req, va_list arguments)
+{
+ H5G_loc_t loc;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ if(H5G_loc_real(obj, loc_params->obj_type, &loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+
+ switch(get_type) {
+ /* H5Lget_info/H5Lget_info_by_idx */
+ case H5VL_LINK_GET_INFO:
+ {
+ H5L_info_t *linfo = HDva_arg(arguments, H5L_info_t *);
+
+ /* Get the link information */
+ if(loc_params->type == H5VL_OBJECT_BY_NAME) { /* H5Lget_info */
+ if(H5L_get_info(&loc, loc_params->loc_data.loc_by_name.name, linfo) < 0)
+ HGOTO_ERROR(H5E_LINK, H5E_NOTFOUND, FAIL, "unable to get link info")
+ } /* end if */
+ else if(loc_params->type == H5VL_OBJECT_BY_IDX) { /* H5Lget_info_by_idx */
+ if(H5L_get_info_by_idx(&loc, loc_params->loc_data.loc_by_idx.name, loc_params->loc_data.loc_by_idx.idx_type,
+ loc_params->loc_data.loc_by_idx.order, loc_params->loc_data.loc_by_idx.n, linfo) < 0)
+ HGOTO_ERROR(H5E_LINK, H5E_NOTFOUND, FAIL, "unable to get link info")
+ } /* end else-if */
+ else
+ HGOTO_ERROR(H5E_LINK, H5E_NOTFOUND, FAIL, "unable to get link info")
+ break;
+ }
+
+ /* H5Lget_name_by_idx */
+ case H5VL_LINK_GET_NAME:
+ {
+ char *name = HDva_arg(arguments, char *);
+ size_t size = HDva_arg(arguments, size_t);
+ ssize_t *ret = HDva_arg(arguments, ssize_t *);
+
+ /* Get the link name */
+ if((*ret = H5L_get_name_by_idx(&loc, loc_params->loc_data.loc_by_idx.name, loc_params->loc_data.loc_by_idx.idx_type,
+ loc_params->loc_data.loc_by_idx.order, loc_params->loc_data.loc_by_idx.n, name, size)) < 0)
+ HGOTO_ERROR(H5E_LINK, H5E_NOTFOUND, FAIL, "unable to get link info")
+
+ break;
+ }
+
+ /* H5Lget_val/H5Lget_val_by_idx */
+ case H5VL_LINK_GET_VAL:
+ {
+ void *buf = HDva_arg(arguments, void *);
+ size_t size = HDva_arg(arguments, size_t);
+
+ /* Get the link information */
+ if(loc_params->type == H5VL_OBJECT_BY_NAME) { /* H5Lget_val */
+ if(H5L_get_val(&loc, loc_params->loc_data.loc_by_name.name, buf, size) < 0)
+ HGOTO_ERROR(H5E_LINK, H5E_NOTFOUND, FAIL, "unable to get link value")
+ }
+ else if(loc_params->type == H5VL_OBJECT_BY_IDX) { /* H5Lget_val_by_idx */
+
+ if(H5L_get_val_by_idx(&loc, loc_params->loc_data.loc_by_idx.name, loc_params->loc_data.loc_by_idx.idx_type,
+ loc_params->loc_data.loc_by_idx.order, loc_params->loc_data.loc_by_idx.n, buf, size) < 0)
+ HGOTO_ERROR(H5E_LINK, H5E_NOTFOUND, FAIL, "unable to get link val")
+ }
+ else
+ HGOTO_ERROR(H5E_LINK, H5E_NOTFOUND, FAIL, "unable to get link val")
+
+ break;
+ }
+
+ default:
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't get this type of information from link")
+ } /* end switch */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_link_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_link_specific
+ *
+ * Purpose: Handles the link specific callback
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL__native_link_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_specific_t specific_type,
+ hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req, va_list arguments)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ switch(specific_type) {
+ case H5VL_LINK_EXISTS:
+ {
+ htri_t *ret = HDva_arg(arguments, htri_t *);
+ H5G_loc_t loc;
+
+ if(H5G_loc_real(obj, loc_params->obj_type, &loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+
+ /* Check for the existence of the link */
+ if((*ret = H5L_exists(&loc, loc_params->loc_data.loc_by_name.name)) < 0)
+ HGOTO_ERROR(H5E_LINK, H5E_NOTFOUND, FAIL, "unable to specific link info")
+ break;
+ }
+
+ case H5VL_LINK_ITER:
+ {
+ H5G_loc_t loc;
+ hbool_t recursive = (hbool_t)HDva_arg(arguments, unsigned);
+ H5_index_t idx_type = (H5_index_t)HDva_arg(arguments, int); /* enum work-around */
+ H5_iter_order_t order = (H5_iter_order_t)HDva_arg(arguments, int); /* enum work-around */
+ hsize_t *idx_p = HDva_arg(arguments, hsize_t *);
+ H5L_iterate_t op = HDva_arg(arguments, H5L_iterate_t);
+ void *op_data = HDva_arg(arguments, void *);
+
+ /* Get the location */
+ if(H5G_loc_real(obj, loc_params->obj_type, &loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
+
+ /* Visit or iterate over the links */
+ if(loc_params->type == H5VL_OBJECT_BY_SELF) {
+ if(recursive) {
+ /* H5Lvisit */
+ if((ret_value = H5G_visit(&loc, ".", idx_type, order, op, op_data)) < 0)
+ HGOTO_ERROR(H5E_LINK, H5E_BADITER, FAIL, "link visitation failed")
+ } /* end if */
+ else {
+ /* H5Literate */
+ if((ret_value = H5L_iterate(&loc, ".", idx_type, order, idx_p, op, op_data)) < 0)
+ HGOTO_ERROR(H5E_LINK, H5E_BADITER, FAIL, "error iterating over links")
+ } /* end else */
+ } /* end if */
+ else if(loc_params->type == H5VL_OBJECT_BY_NAME) {
+ if(recursive) {
+ /* H5Lvisit_by_name */
+ if((ret_value = H5G_visit(&loc, loc_params->loc_data.loc_by_name.name, idx_type, order, op, op_data)) < 0)
+ HGOTO_ERROR(H5E_LINK, H5E_BADITER, FAIL, "link visitation failed")
+ } /* end if */
+ else {
+ /* H5Literate_by_name */
+ if((ret_value = H5L_iterate(&loc, loc_params->loc_data.loc_by_name.name, idx_type, order, idx_p, op, op_data)) < 0)
+ HGOTO_ERROR(H5E_LINK, H5E_BADITER, FAIL, "error iterating over links")
+ } /* end else */
+ } /* end else-if */
+ else
+ HGOTO_ERROR(H5E_LINK, H5E_UNSUPPORTED, FAIL, "unknown link iterate params")
+
+ break;
+ }
+
+ case H5VL_LINK_DELETE:
+ {
+ H5G_loc_t loc;
+
+ if(H5G_loc_real(obj, loc_params->obj_type, &loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+
+ /* Unlink */
+ if(loc_params->type == H5VL_OBJECT_BY_NAME) { /* H5Ldelete */
+ if(H5L_delete(&loc, loc_params->loc_data.loc_by_name.name) < 0)
+ HGOTO_ERROR(H5E_LINK, H5E_CANTDELETE, FAIL, "unable to delete link")
+ } /* end if */
+ else if(loc_params->type == H5VL_OBJECT_BY_IDX) { /* H5Ldelete_by_idx */
+ if(H5L_delete_by_idx(&loc, loc_params->loc_data.loc_by_idx.name, loc_params->loc_data.loc_by_idx.idx_type,
+ loc_params->loc_data.loc_by_idx.order, loc_params->loc_data.loc_by_idx.n) < 0)
+ HGOTO_ERROR(H5E_LINK, H5E_CANTDELETE, FAIL, "unable to delete link")
+ } /* end else-if */
+ else
+ HGOTO_ERROR(H5E_LINK, H5E_CANTDELETE, FAIL, "unable to delete link")
+ break;
+ }
+
+ default:
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "invalid specific operation")
+ } /* end switch */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_link_specific() */
+
diff --git a/src/H5VLnative_object.c b/src/H5VLnative_object.c
new file mode 100644
index 0000000..675d8cf
--- /dev/null
+++ b/src/H5VLnative_object.c
@@ -0,0 +1,511 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Purpose: Object callbacks for the native VOL connector
+ *
+ */
+
+#define H5O_FRIEND /* Suppress error about including H5Opkg */
+
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fprivate.h" /* Files */
+#include "H5Gprivate.h" /* Groups */
+#include "H5Iprivate.h" /* IDs */
+#include "H5Opkg.h" /* Object headers */
+#include "H5Pprivate.h" /* Property lists */
+#include "H5VLprivate.h" /* Virtual Object Layer */
+
+#include "H5VLnative_private.h" /* Native VOL connector */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_object_open
+ *
+ * Purpose: Handles the object open callback
+ *
+ * Return: Success: object pointer
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5VL__native_object_open(void *obj, const H5VL_loc_params_t *loc_params, H5I_type_t *opened_type,
+ hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req)
+{
+ H5G_loc_t loc;
+ void *ret_value = NULL;
+
+ FUNC_ENTER_PACKAGE
+
+ if(H5G_loc_real(obj, loc_params->obj_type, &loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file or file object")
+
+ switch(loc_params->type) {
+ case H5VL_OBJECT_BY_NAME:
+ {
+ /* Open the object */
+ if(NULL == (ret_value = H5O_open_name(&loc, loc_params->loc_data.loc_by_name.name, opened_type)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, NULL, "unable to open object by name")
+ break;
+ }
+
+ case H5VL_OBJECT_BY_IDX:
+ {
+ /* Open the object */
+ if(NULL == (ret_value = H5O_open_by_idx(&loc, loc_params->loc_data.loc_by_idx.name, loc_params->loc_data.loc_by_idx.idx_type,
+ loc_params->loc_data.loc_by_idx.order, loc_params->loc_data.loc_by_idx.n, opened_type)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, NULL, "unable to open object by index")
+ break;
+ }
+
+ case H5VL_OBJECT_BY_TOKEN:
+ {
+ const uint8_t *p = (const uint8_t *)loc_params->loc_data.loc_by_token.token;
+ haddr_t addr;
+
+ /* Decode token */
+ H5F_addr_decode(loc.oloc->file, &p, &addr);
+
+ /* Open the object */
+ if(NULL == (ret_value = H5O_open_by_addr(&loc, addr, opened_type)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, NULL, "unable to open object by address")
+ break;
+ }
+
+ case H5VL_OBJECT_BY_SELF:
+ default:
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, NULL, "unknown open parameters")
+ } /* end switch */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_object_open() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_object_copy
+ *
+ * Purpose: Handles the object copy callback
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL__native_object_copy(void *src_obj, const H5VL_loc_params_t *loc_params1, const char *src_name,
+ void *dst_obj, const H5VL_loc_params_t *loc_params2, const char *dst_name,
+ hid_t ocpypl_id, hid_t lcpl_id, hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req)
+{
+ H5G_loc_t src_loc; /* Source object group location */
+ H5G_loc_t dst_loc; /* Destination group location */
+ herr_t ret_value = FAIL;
+
+ FUNC_ENTER_PACKAGE
+
+ /* get location for objects */
+ if(H5G_loc_real(src_obj, loc_params1->obj_type, &src_loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+ if(H5G_loc_real(dst_obj, loc_params2->obj_type, &dst_loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+
+ /* Copy the object */
+ if((ret_value = H5O_copy(&src_loc, src_name, &dst_loc, dst_name, ocpypl_id, lcpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, FAIL, "unable to copy object")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_object_copy() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_object_get
+ *
+ * Purpose: Handles the object get callback
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL__native_object_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_get_t get_type,
+ hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req, va_list arguments)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+ H5G_loc_t loc; /* Location of group */
+
+ FUNC_ENTER_PACKAGE
+
+ if(H5G_loc_real(obj, loc_params->obj_type, &loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+
+ switch(get_type) {
+ /* Object name */
+ case H5VL_OBJECT_GET_NAME:
+ {
+ ssize_t *ret = HDva_arg(arguments, ssize_t *);
+ char *name = HDva_arg(arguments, char *);
+ size_t size = HDva_arg(arguments, size_t);
+
+ if(loc_params->type == H5VL_OBJECT_BY_SELF) {
+ /* Retrieve object's name */
+ if((*ret = H5G_get_name(&loc, name, size, NULL)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't retrieve object name")
+ } /* end if */
+ else if(loc_params->type == H5VL_OBJECT_BY_TOKEN) {
+ H5O_loc_t obj_oloc; /* Object location */
+ const uint8_t *p = (const uint8_t *)loc_params->loc_data.loc_by_token.token;
+
+ /* Initialize the object location */
+ H5O_loc_reset(&obj_oloc);
+ obj_oloc.file = loc.oloc->file;
+ /* Decode token */
+ H5F_addr_decode(obj_oloc.file, &p, &obj_oloc.addr);
+
+ /* Retrieve object's name */
+ if((*ret = H5G_get_name_by_addr(loc.oloc->file, &obj_oloc, name, size)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't determine object name")
+ } /* end else-if */
+ else
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "unknown get_name parameters")
+ break;
+ }
+
+ /* Object type */
+ case H5VL_OBJECT_GET_TYPE:
+ {
+ H5O_type_t *obj_type = HDva_arg(arguments, H5O_type_t *);
+
+ if(loc_params->type == H5VL_OBJECT_BY_TOKEN) {
+ H5O_loc_t obj_oloc; /* Object location */
+ unsigned rc; /* Reference count of object */
+ const uint8_t *p = (const uint8_t *)loc_params->loc_data.loc_by_token.token;
+
+ /* Initialize the object location */
+ H5O_loc_reset(&obj_oloc);
+ obj_oloc.file = loc.oloc->file;
+ /* Decode token */
+ H5F_addr_decode(obj_oloc.file, &p, &obj_oloc.addr);
+
+ /* Get the # of links for object, and its type */
+ /* (To check to make certain that this object hasn't been deleted) */
+ if(H5O_get_rc_and_type(&obj_oloc, &rc, obj_type) < 0 || 0 == rc)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_LINKCOUNT, FAIL, "dereferencing deleted object")
+ } else
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "unknown get_type parameters")
+ break;
+ }
+
+ default:
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't get this type of information from object")
+ } /* end switch */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_object_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_object_specific
+ *
+ * Purpose: Handles the object specific callback
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL__native_object_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_specific_t specific_type,
+ hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req, va_list arguments)
+{
+ H5G_loc_t loc;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ if(H5G_loc_real(obj, loc_params->obj_type, &loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+
+ switch(specific_type) {
+ /* H5Oincr_refcount / H5Odecr_refcount */
+ case H5VL_OBJECT_CHANGE_REF_COUNT:
+ {
+ int update_ref = HDva_arg(arguments, int);
+ H5O_loc_t *oloc = loc.oloc;
+
+ if(H5O_link(oloc, update_ref) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "modifying object link count failed")
+
+ break;
+ }
+
+ /* H5Oexists_by_name */
+ case H5VL_OBJECT_EXISTS:
+ {
+ htri_t *ret = HDva_arg(arguments, htri_t *);
+
+ if(loc_params->type == H5VL_OBJECT_BY_NAME) {
+ /* Check if the object exists */
+ if((*ret = H5G_loc_exists(&loc, loc_params->loc_data.loc_by_name.name)) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to determine if '%s' exists", loc_params->loc_data.loc_by_name.name)
+ } /* end if */
+ else
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "unknown object exists parameters")
+ break;
+ }
+
+ /* Lookup object */
+ case H5VL_OBJECT_LOOKUP:
+ {
+ void *token = va_arg(arguments, void *);
+
+ HDassert(token);
+
+ if(loc_params->type == H5VL_OBJECT_BY_NAME) {
+ H5G_loc_t obj_loc; /* Group hier. location of object */
+ H5G_name_t obj_path; /* Object group hier. path */
+ H5O_loc_t obj_oloc; /* Object object location */
+ uint8_t *p = (uint8_t *)token; /* Pointer to token */
+
+ /* Set up opened group location to fill in */
+ obj_loc.oloc = &obj_oloc;
+ obj_loc.path = &obj_path;
+ H5G_loc_reset(&obj_loc);
+
+ /* Find the object */
+ if(H5G_loc_find(&loc, loc_params->loc_data.loc_by_name.name, &obj_loc) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "object not found")
+
+ /* Encode token */
+ H5F_addr_encode(obj_oloc.file, &p, obj_loc.oloc->addr);
+
+ /* Release the object location */
+ if(H5G_loc_free(&obj_loc) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "can't free location")
+ } /* end if */
+ else
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "unknown object exists parameters")
+ break;
+ }
+
+ case H5VL_OBJECT_VISIT:
+ {
+ H5_index_t idx_type = (H5_index_t)HDva_arg(arguments, int); /* enum work-around */
+ H5_iter_order_t order = (H5_iter_order_t)HDva_arg(arguments, int); /* enum work-around */
+ H5O_iterate_t op = HDva_arg(arguments, H5O_iterate_t);
+ void *op_data = HDva_arg(arguments, void *);
+ unsigned fields = HDva_arg(arguments, unsigned);
+
+ /* Call internal object visitation routine */
+ if(loc_params->type == H5VL_OBJECT_BY_SELF) {
+ /* H5Ovisit */
+ if((ret_value = H5O__visit(&loc, ".", idx_type, order, op, op_data, fields)) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "object visitation failed")
+ } /* end if */
+ else if(loc_params->type == H5VL_OBJECT_BY_NAME) {
+ /* H5Ovisit_by_name */
+ if((ret_value = H5O__visit(&loc, loc_params->loc_data.loc_by_name.name, idx_type, order, op, op_data, fields)) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "object visitation failed")
+ } /* end else-if */
+ else
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "unknown object visit params");
+ break;
+ }
+
+ case H5VL_OBJECT_FLUSH:
+ {
+ hid_t oid = HDva_arg(arguments, hid_t);
+
+ /* Flush the object's metadata */
+ if(H5O_flush(loc.oloc, oid) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTFLUSH, FAIL, "unable to flush object")
+
+ break;
+ }
+
+ case H5VL_OBJECT_REFRESH:
+ {
+ hid_t oid = HDva_arg(arguments, hid_t);
+ H5O_loc_t *oloc = loc.oloc;
+
+ /* Refresh the metadata */
+ if(H5O_refresh_metadata(oid, *oloc) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to refresh object")
+
+ break;
+ }
+
+ default:
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't recognize this operation type")
+ } /* end switch */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_object_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__native_object_optional
+ *
+ * Purpose: Handles the object optional callback
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL__native_object_optional(void *obj, hid_t H5_ATTR_UNUSED dxpl_id,
+ void H5_ATTR_UNUSED **req, va_list arguments)
+{
+ H5VL_native_object_optional_t optional_type = HDva_arg(arguments, H5VL_native_object_optional_t);
+ H5VL_loc_params_t *loc_params = HDva_arg(arguments, H5VL_loc_params_t *);
+ H5G_loc_t loc; /* Location of group */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ if(H5G_loc_real(obj, loc_params->obj_type, &loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+
+ switch(optional_type) {
+ /* H5Oget_info / H5Oget_info_by_name / H5Oget_info_by_idx */
+ case H5VL_NATIVE_OBJECT_GET_INFO:
+ {
+ H5O_info_t *obj_info = HDva_arg(arguments, H5O_info_t *);
+ unsigned fields = HDva_arg(arguments, unsigned);
+
+ if(loc_params->type == H5VL_OBJECT_BY_SELF) { /* H5Oget_info */
+ /* Retrieve the object's information */
+ if(H5G_loc_info(&loc, ".", obj_info, fields) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "object not found")
+ } /* end if */
+ else if(loc_params->type == H5VL_OBJECT_BY_NAME) { /* H5Oget_info_by_name */
+ /* Retrieve the object's information */
+ if(H5G_loc_info(&loc, loc_params->loc_data.loc_by_name.name, obj_info, fields) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "object not found")
+ } /* end else-if */
+ else if(loc_params->type == H5VL_OBJECT_BY_IDX) { /* H5Oget_info_by_idx */
+ H5G_loc_t obj_loc; /* Location used to open group */
+ H5G_name_t obj_path; /* Opened object group hier. path */
+ H5O_loc_t obj_oloc; /* Opened object object location */
+
+ /* Set up opened group location to fill in */
+ obj_loc.oloc = &obj_oloc;
+ obj_loc.path = &obj_path;
+ H5G_loc_reset(&obj_loc);
+
+ /* Find the object's location, according to the order in the index */
+ if(H5G_loc_find_by_idx(&loc, loc_params->loc_data.loc_by_idx.name,
+ loc_params->loc_data.loc_by_idx.idx_type,
+ loc_params->loc_data.loc_by_idx.order,
+ loc_params->loc_data.loc_by_idx.n, &obj_loc/*out*/) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "group not found")
+
+ /* Retrieve the object's information */
+ if(H5O_get_info(obj_loc.oloc, obj_info, fields) < 0) {
+ H5G_loc_free(&obj_loc);
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't retrieve object info")
+ } /* end if */
+
+ /* Release the object location */
+ if(H5G_loc_free(&obj_loc) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "can't free location")
+ } /* end else-if */
+ else
+ HGOTO_ERROR(H5E_OHDR, H5E_UNSUPPORTED, FAIL, "unknown get info parameters")
+ break;
+ }
+
+ /* H5Oget_comment / H5Oget_comment_by_name */
+ case H5VL_NATIVE_OBJECT_GET_COMMENT:
+ {
+ char *comment = HDva_arg(arguments, char *);
+ size_t bufsize = HDva_arg(arguments, size_t);
+ ssize_t *ret = HDva_arg(arguments, ssize_t *);
+
+ /* Retrieve the object's comment */
+ if(loc_params->type == H5VL_OBJECT_BY_SELF) { /* H5Oget_comment */
+ if((*ret = H5G_loc_get_comment(&loc, ".", comment/*out*/, bufsize)) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "object not found")
+ } /* end if */
+ else if(loc_params->type == H5VL_OBJECT_BY_NAME) { /* H5Oget_comment_by_name */
+ if((*ret = H5G_loc_get_comment(&loc, loc_params->loc_data.loc_by_name.name, comment/*out*/, bufsize)) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "object not found")
+ } /* end else-if */
+ else
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "unknown set_coment parameters")
+ break;
+ }
+
+ /* H5Oset_comment */
+ case H5VL_NATIVE_OBJECT_SET_COMMENT:
+ {
+ const char *comment = HDva_arg(arguments, char *);
+
+ if(loc_params->type == H5VL_OBJECT_BY_SELF) { /* H5Oset_comment */
+ /* (Re)set the object's comment */
+ if(H5G_loc_set_comment(&loc, ".", comment) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "object not found")
+ } /* end if */
+ else if(loc_params->type == H5VL_OBJECT_BY_NAME) { /* H5Oset_comment_by_name */
+ /* (Re)set the object's comment */
+ if(H5G_loc_set_comment(&loc, loc_params->loc_data.loc_by_name.name, comment) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "object not found")
+ } /* end else-if */
+ else
+ HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "unknown set_coment parameters")
+ break;
+ }
+
+ /* H5Odisable_mdc_flushes */
+ case H5VL_NATIVE_OBJECT_DISABLE_MDC_FLUSHES:
+ {
+ H5O_loc_t *oloc = loc.oloc;
+
+ if (H5O_disable_mdc_flushes(oloc) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTCORK, FAIL, "unable to cork the metadata cache");
+
+ break;
+ }
+
+ /* H5Oenable_mdc_flushes */
+ case H5VL_NATIVE_OBJECT_ENABLE_MDC_FLUSHES:
+ {
+ H5O_loc_t *oloc = loc.oloc;
+
+ if (H5O_enable_mdc_flushes(oloc) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTUNCORK, FAIL, "unable to uncork the metadata cache");
+
+ break;
+ }
+
+ /* H5Oare_mdc_flushes_disabled */
+ case H5VL_NATIVE_OBJECT_ARE_MDC_FLUSHES_DISABLED:
+ {
+ H5O_loc_t *oloc = loc.oloc;
+ hbool_t *are_disabled = (hbool_t *)HDva_arg(arguments, hbool_t *);
+
+ if (H5O_are_mdc_flushes_disabled(oloc, are_disabled) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to determine metadata cache cork status");
+
+ break;
+ }
+
+ default:
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't perform this operation on object");
+ } /* end switch */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__native_object_optional() */
+
diff --git a/src/H5VLnative_private.h b/src/H5VLnative_private.h
new file mode 100644
index 0000000..5ed0b1f
--- /dev/null
+++ b/src/H5VLnative_private.h
@@ -0,0 +1,114 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Purpose: The private header file for the native VOL connector.
+ */
+
+#ifndef _H5VLnative_private_H
+#define _H5VLnative_private_H
+
+/* Private headers needed by this file */
+#include "H5VLnative.h" /* Native VOL connector */
+
+
+/**************************/
+/* Library Private Macros */
+/**************************/
+
+
+/****************************/
+/* Library Private Typedefs */
+/****************************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/******************************/
+/* Library Private Prototypes */
+/******************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Attribute callbacks */
+H5_DLL void *H5VL__native_attr_create(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_name, hid_t type_id, hid_t space_id, hid_t acpl_id, hid_t aapl_id, hid_t dxpl_id, void **req);
+void *H5VL__native_attr_open(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_name, hid_t aapl_id, hid_t dxpl_id, void **req);
+H5_DLL herr_t H5VL__native_attr_read(void *attr, hid_t dtype_id, void *buf, hid_t dxpl_id, void **req);
+H5_DLL herr_t H5VL__native_attr_write(void *attr, hid_t dtype_id, const void *buf, hid_t dxpl_id, void **req);
+H5_DLL herr_t H5VL__native_attr_get(void *obj, H5VL_attr_get_t get_type, hid_t dxpl_id, void **req, va_list arguments);
+H5_DLL herr_t H5VL__native_attr_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_attr_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments);
+H5_DLL herr_t H5VL__native_attr_optional(void *obj, hid_t dxpl_id, void **req, va_list arguments);
+H5_DLL herr_t H5VL__native_attr_close(void *attr, hid_t dxpl_id, void **req);
+
+/* Dataset callbacks */
+H5_DLL void *H5VL__native_dataset_create(void *obj, const H5VL_loc_params_t *loc_params, const char *name, hid_t lcpl_id, hid_t type_id, hid_t space_id, hid_t dcpl_id, 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_get(void *dset, H5VL_dataset_get_t get_type, hid_t dxpl_id, void **req, va_list arguments);
+H5_DLL herr_t H5VL__native_dataset_specific(void *dset, H5VL_dataset_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments);
+H5_DLL herr_t H5VL__native_dataset_optional(void *dset, hid_t dxpl_id, void **req, va_list arguments);
+H5_DLL herr_t H5VL__native_dataset_close(void *dset, hid_t dxpl_id, void **req);
+
+/* File callbacks */
+H5_DLL void *H5VL__native_file_create(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t dxpl_id, void **req);
+H5_DLL void *H5VL__native_file_open(const char *name, unsigned flags, hid_t fapl_id, hid_t dxpl_id, void **req);
+H5_DLL herr_t H5VL__native_file_get(void *file, H5VL_file_get_t get_type, hid_t dxpl_id, void **req, va_list arguments);
+H5_DLL herr_t H5VL__native_file_specific(void *file, H5VL_file_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments);
+H5_DLL herr_t H5VL__native_file_optional(void *file, hid_t dxpl_id, void **req, va_list arguments);
+H5_DLL herr_t H5VL__native_file_close(void *file, hid_t dxpl_id, void **req);
+
+/* Group callbacks */
+H5_DLL void *H5VL__native_group_create(void *obj, const H5VL_loc_params_t *loc_params, const char *name, hid_t lcpl_id, hid_t gcpl_id, hid_t gapl_id, hid_t dxpl_id, void **req);
+H5_DLL void *H5VL__native_group_open(void *obj, const H5VL_loc_params_t *loc_params, const char *name, hid_t gapl_id, hid_t dxpl_id, void **req);
+H5_DLL herr_t H5VL__native_group_get(void *obj, H5VL_group_get_t get_type, hid_t dxpl_id, void **req, va_list arguments);
+H5_DLL herr_t H5VL__native_group_specific(void *obj, H5VL_group_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments);
+H5_DLL herr_t H5VL__native_group_optional(void *obj, hid_t dxpl_id, void **req, va_list arguments);
+H5_DLL herr_t H5VL__native_group_close(void *grp, hid_t dxpl_id, void **req);
+
+/* Link callbacks */
+H5_DLL herr_t H5VL__native_link_create(H5VL_link_create_type_t create_type, void *obj, const H5VL_loc_params_t *loc_params, hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id, void **req, va_list arguments);
+H5_DLL herr_t H5VL__native_link_copy(void *src_obj, const H5VL_loc_params_t *loc_params1, void *dst_obj, const H5VL_loc_params_t *loc_params2, hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id, void **req);
+H5_DLL herr_t H5VL__native_link_move(void *src_obj, const H5VL_loc_params_t *loc_params1, void *dst_obj, const H5VL_loc_params_t *loc_params2, hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id, void **req);
+H5_DLL herr_t H5VL__native_link_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_get_t get_type, hid_t dxpl_id, void **req, va_list arguments);
+H5_DLL herr_t H5VL__native_link_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments);
+
+/* Object callbacks */
+H5_DLL void *H5VL__native_object_open(void *obj, const H5VL_loc_params_t *loc_params, H5I_type_t *opened_type, hid_t dxpl_id, void **req);
+H5_DLL herr_t H5VL__native_object_copy(void *src_obj, const H5VL_loc_params_t *loc_params1, const char *src_name, void *dst_obj, const H5VL_loc_params_t *loc_params2, const char *dst_name, hid_t ocpypl_id, hid_t lcpl_id, hid_t dxpl_id, void **req);
+H5_DLL herr_t H5VL__native_object_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_get_t get_type, hid_t dxpl_id, void **req, va_list arguments);
+H5_DLL herr_t H5VL__native_object_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments);
+H5_DLL herr_t H5VL__native_object_optional(void *obj, hid_t dxpl_id, void **req, va_list arguments);
+
+/* Datatype callbacks */
+H5_DLL void *H5VL__native_datatype_commit(void *obj, const H5VL_loc_params_t *loc_params, const char *name, hid_t type_id, hid_t lcpl_id, hid_t tcpl_id, hid_t tapl_id, hid_t dxpl_id, void **req);
+H5_DLL void *H5VL__native_datatype_open(void *obj, const H5VL_loc_params_t *loc_params, const char *name, hid_t tapl_id, hid_t dxpl_id, void **req);
+H5_DLL herr_t H5VL__native_datatype_get(void *dt, H5VL_datatype_get_t get_type, hid_t dxpl_id, void **req, va_list arguments);
+H5_DLL herr_t H5VL__native_datatype_specific(void *dt, H5VL_datatype_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments);
+H5_DLL herr_t H5VL__native_datatype_close(void *dt, hid_t dxpl_id, void **req);
+
+/* Blob callbacks */
+H5_DLL herr_t H5VL__native_blob_put(void *obj, const void *buf, size_t size, void *blob_id, void *ctx);
+H5_DLL herr_t H5VL__native_blob_get(void *obj, const void *blob_id, void *buf, size_t *size, void *ctx);
+H5_DLL herr_t H5VL__native_blob_specific(void *obj, void *blob_id, H5VL_blob_specific_t specific_type, va_list arguments);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _H5VLnative_private_H */
+
diff --git a/src/H5VLpassthru.c b/src/H5VLpassthru.c
new file mode 100644
index 0000000..85c2211
--- /dev/null
+++ b/src/H5VLpassthru.c
@@ -0,0 +1,2928 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Purpose: This is a "pass through" VOL connector, which forwards each
+ * VOL callback to an underlying connector.
+ *
+ * It is designed as an example VOL connector for developers to
+ * use when creating new connectors, especially connectors that
+ * are outside of the HDF5 library. As such, it should _NOT_
+ * include _any_ private HDF5 header files. This connector should
+ * therefore only make public HDF5 API calls and use standard C /
+ * POSIX calls.
+ *
+ * Note that the HDF5 error stack must be preserved on code paths
+ * that could be invoked when the underlying VOL connector's
+ * callback can fail.
+ *
+ */
+
+
+/* Header files needed */
+/* Do NOT include private HDF5 files here! */
+#include <assert.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Public HDF5 file */
+#include "hdf5.h"
+
+/* This connector's header */
+#include "H5VLpassthru.h"
+
+
+/**********/
+/* Macros */
+/**********/
+
+/* Whether to display log messge when callback is invoked */
+/* (Uncomment to enable) */
+/* #define ENABLE_PASSTHRU_LOGGING */
+
+/* Hack for missing va_copy() in old Visual Studio editions
+ * (from H5win2_defs.h - used on VS2012 and earlier)
+ */
+#if defined(_WIN32) && defined(_MSC_VER) && (_MSC_VER < 1800)
+#define va_copy(D,S) ((D) = (S))
+#endif
+
+/************/
+/* Typedefs */
+/************/
+
+/* The pass through VOL info object */
+typedef struct H5VL_pass_through_t {
+ hid_t under_vol_id; /* ID for underlying VOL connector */
+ void *under_object; /* Info object for underlying VOL connector */
+} H5VL_pass_through_t;
+
+/* The pass through VOL wrapper context */
+typedef struct H5VL_pass_through_wrap_ctx_t {
+ hid_t under_vol_id; /* VOL ID for under VOL */
+ void *under_wrap_ctx; /* Object wrapping context for under VOL */
+} H5VL_pass_through_wrap_ctx_t;
+
+
+/********************* */
+/* Function prototypes */
+/********************* */
+
+/* Helper routines */
+static herr_t H5VL_pass_through_file_specific_reissue(void *obj, hid_t connector_id,
+ H5VL_file_specific_t specific_type, hid_t dxpl_id, void **req, ...);
+static herr_t H5VL_pass_through_request_specific_reissue(void *obj, hid_t connector_id,
+ H5VL_request_specific_t specific_type, ...);
+static herr_t H5VL_pass_through_link_create_reissue(H5VL_link_create_type_t create_type,
+ void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id,
+ hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id, void **req, ...);
+static H5VL_pass_through_t *H5VL_pass_through_new_obj(void *under_obj,
+ hid_t under_vol_id);
+static herr_t H5VL_pass_through_free_obj(H5VL_pass_through_t *obj);
+
+/* "Management" callbacks */
+static herr_t H5VL_pass_through_init(hid_t vipl_id);
+static herr_t H5VL_pass_through_term(void);
+
+/* VOL info callbacks */
+static void *H5VL_pass_through_info_copy(const void *info);
+static herr_t H5VL_pass_through_info_cmp(int *cmp_value, const void *info1, const void *info2);
+static herr_t H5VL_pass_through_info_free(void *info);
+static herr_t H5VL_pass_through_info_to_str(const void *info, char **str);
+static herr_t H5VL_pass_through_str_to_info(const char *str, void **info);
+
+/* VOL object wrap / retrieval callbacks */
+static void *H5VL_pass_through_get_object(const void *obj);
+static herr_t H5VL_pass_through_get_wrap_ctx(const void *obj, void **wrap_ctx);
+static void *H5VL_pass_through_wrap_object(void *obj, H5I_type_t obj_type,
+ void *wrap_ctx);
+static void *H5VL_pass_through_unwrap_object(void *obj);
+static herr_t H5VL_pass_through_free_wrap_ctx(void *obj);
+
+/* Attribute callbacks */
+static void *H5VL_pass_through_attr_create(void *obj, const H5VL_loc_params_t *loc_params, const char *name, hid_t type_id, hid_t space_id, hid_t acpl_id, hid_t aapl_id, hid_t dxpl_id, void **req);
+static void *H5VL_pass_through_attr_open(void *obj, const H5VL_loc_params_t *loc_params, const char *name, hid_t aapl_id, hid_t dxpl_id, void **req);
+static herr_t H5VL_pass_through_attr_read(void *attr, hid_t mem_type_id, void *buf, hid_t dxpl_id, void **req);
+static herr_t H5VL_pass_through_attr_write(void *attr, hid_t mem_type_id, const void *buf, hid_t dxpl_id, void **req);
+static herr_t H5VL_pass_through_attr_get(void *obj, H5VL_attr_get_t get_type, hid_t dxpl_id, void **req, va_list arguments);
+static herr_t H5VL_pass_through_attr_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_attr_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments);
+static herr_t H5VL_pass_through_attr_optional(void *obj, hid_t dxpl_id, void **req, va_list arguments);
+static herr_t H5VL_pass_through_attr_close(void *attr, hid_t dxpl_id, void **req);
+
+/* Dataset callbacks */
+static void *H5VL_pass_through_dataset_create(void *obj, const H5VL_loc_params_t *loc_params, const char *name, hid_t lcpl_id, hid_t type_id, hid_t space_id, 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_get(void *dset, H5VL_dataset_get_t get_type, hid_t dxpl_id, void **req, va_list arguments);
+static herr_t H5VL_pass_through_dataset_specific(void *obj, H5VL_dataset_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments);
+static herr_t H5VL_pass_through_dataset_optional(void *obj, hid_t dxpl_id, void **req, va_list arguments);
+static herr_t H5VL_pass_through_dataset_close(void *dset, hid_t dxpl_id, void **req);
+
+/* Datatype callbacks */
+static void *H5VL_pass_through_datatype_commit(void *obj, const H5VL_loc_params_t *loc_params, const char *name, hid_t type_id, hid_t lcpl_id, hid_t tcpl_id, hid_t tapl_id, hid_t dxpl_id, void **req);
+static void *H5VL_pass_through_datatype_open(void *obj, const H5VL_loc_params_t *loc_params, const char *name, hid_t tapl_id, hid_t dxpl_id, void **req);
+static herr_t H5VL_pass_through_datatype_get(void *dt, H5VL_datatype_get_t get_type, hid_t dxpl_id, void **req, va_list arguments);
+static herr_t H5VL_pass_through_datatype_specific(void *obj, H5VL_datatype_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments);
+static herr_t H5VL_pass_through_datatype_optional(void *obj, hid_t dxpl_id, void **req, va_list arguments);
+static herr_t H5VL_pass_through_datatype_close(void *dt, hid_t dxpl_id, void **req);
+
+/* File callbacks */
+static void *H5VL_pass_through_file_create(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t dxpl_id, void **req);
+static void *H5VL_pass_through_file_open(const char *name, unsigned flags, hid_t fapl_id, hid_t dxpl_id, void **req);
+static herr_t H5VL_pass_through_file_get(void *file, H5VL_file_get_t get_type, hid_t dxpl_id, void **req, va_list arguments);
+static herr_t H5VL_pass_through_file_specific(void *file, H5VL_file_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments);
+static herr_t H5VL_pass_through_file_optional(void *file, hid_t dxpl_id, void **req, va_list arguments);
+static herr_t H5VL_pass_through_file_close(void *file, hid_t dxpl_id, void **req);
+
+/* Group callbacks */
+static void *H5VL_pass_through_group_create(void *obj, const H5VL_loc_params_t *loc_params, const char *name, hid_t lcpl_id, hid_t gcpl_id, hid_t gapl_id, hid_t dxpl_id, void **req);
+static void *H5VL_pass_through_group_open(void *obj, const H5VL_loc_params_t *loc_params, const char *name, hid_t gapl_id, hid_t dxpl_id, void **req);
+static herr_t H5VL_pass_through_group_get(void *obj, H5VL_group_get_t get_type, hid_t dxpl_id, void **req, va_list arguments);
+static herr_t H5VL_pass_through_group_specific(void *obj, H5VL_group_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments);
+static herr_t H5VL_pass_through_group_optional(void *obj, hid_t dxpl_id, void **req, va_list arguments);
+static herr_t H5VL_pass_through_group_close(void *grp, hid_t dxpl_id, void **req);
+
+/* Link callbacks */
+static herr_t H5VL_pass_through_link_create(H5VL_link_create_type_t create_type, void *obj, const H5VL_loc_params_t *loc_params, hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id, void **req, va_list arguments);
+static herr_t H5VL_pass_through_link_copy(void *src_obj, const H5VL_loc_params_t *loc_params1, void *dst_obj, const H5VL_loc_params_t *loc_params2, hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id, void **req);
+static herr_t H5VL_pass_through_link_move(void *src_obj, const H5VL_loc_params_t *loc_params1, void *dst_obj, const H5VL_loc_params_t *loc_params2, hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id, void **req);
+static herr_t H5VL_pass_through_link_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_get_t get_type, hid_t dxpl_id, void **req, va_list arguments);
+static herr_t H5VL_pass_through_link_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments);
+static herr_t H5VL_pass_through_link_optional(void *obj, hid_t dxpl_id, void **req, va_list arguments);
+
+/* Object callbacks */
+static void *H5VL_pass_through_object_open(void *obj, const H5VL_loc_params_t *loc_params, H5I_type_t *opened_type, hid_t dxpl_id, void **req);
+static herr_t H5VL_pass_through_object_copy(void *src_obj, const H5VL_loc_params_t *src_loc_params, const char *src_name, void *dst_obj, const H5VL_loc_params_t *dst_loc_params, const char *dst_name, hid_t ocpypl_id, hid_t lcpl_id, hid_t dxpl_id, void **req);
+static herr_t H5VL_pass_through_object_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_get_t get_type, hid_t dxpl_id, void **req, va_list arguments);
+static herr_t H5VL_pass_through_object_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments);
+static herr_t H5VL_pass_through_object_optional(void *obj, hid_t dxpl_id, void **req, va_list arguments);
+
+/* Async request callbacks */
+static herr_t H5VL_pass_through_request_wait(void *req, uint64_t timeout, H5ES_status_t *status);
+static herr_t H5VL_pass_through_request_notify(void *obj, H5VL_request_notify_t cb, void *ctx);
+static herr_t H5VL_pass_through_request_cancel(void *req);
+static herr_t H5VL_pass_through_request_specific(void *req, H5VL_request_specific_t specific_type, va_list arguments);
+static herr_t H5VL_pass_through_request_optional(void *req, va_list arguments);
+static herr_t H5VL_pass_through_request_free(void *req);
+
+/* Blob callbacks */
+static herr_t H5VL_pass_through_blob_put(void *obj, const void *buf, size_t size, void *blob_id, void *ctx);
+static herr_t H5VL_pass_through_blob_get(void *obj, const void *blob_id, void *buf, size_t *size, void *ctx);
+static herr_t H5VL_pass_through_blob_specific(void *obj, void *blob_id, H5VL_blob_specific_t specific_type, va_list arguments);
+
+
+/*******************/
+/* Local variables */
+/*******************/
+
+/* Pass through VOL connector class struct */
+static const H5VL_class_t H5VL_pass_through_g = {
+ H5VL_PASSTHRU_VERSION, /* version */
+ (H5VL_class_value_t)H5VL_PASSTHRU_VALUE, /* value */
+ H5VL_PASSTHRU_NAME, /* name */
+ 0, /* capability flags */
+ H5VL_pass_through_init, /* initialize */
+ H5VL_pass_through_term, /* terminate */
+ { /* info_cls */
+ sizeof(H5VL_pass_through_info_t), /* size */
+ H5VL_pass_through_info_copy, /* copy */
+ H5VL_pass_through_info_cmp, /* compare */
+ H5VL_pass_through_info_free, /* free */
+ H5VL_pass_through_info_to_str, /* to_str */
+ H5VL_pass_through_str_to_info /* from_str */
+ },
+ { /* wrap_cls */
+ H5VL_pass_through_get_object, /* get_object */
+ H5VL_pass_through_get_wrap_ctx, /* get_wrap_ctx */
+ H5VL_pass_through_wrap_object, /* wrap_object */
+ H5VL_pass_through_unwrap_object, /* unwrap_object */
+ H5VL_pass_through_free_wrap_ctx /* free_wrap_ctx */
+ },
+ { /* attribute_cls */
+ H5VL_pass_through_attr_create, /* create */
+ H5VL_pass_through_attr_open, /* open */
+ H5VL_pass_through_attr_read, /* read */
+ H5VL_pass_through_attr_write, /* write */
+ H5VL_pass_through_attr_get, /* get */
+ H5VL_pass_through_attr_specific, /* specific */
+ H5VL_pass_through_attr_optional, /* optional */
+ H5VL_pass_through_attr_close /* close */
+ },
+ { /* dataset_cls */
+ H5VL_pass_through_dataset_create, /* create */
+ H5VL_pass_through_dataset_open, /* open */
+ H5VL_pass_through_dataset_read, /* read */
+ H5VL_pass_through_dataset_write, /* write */
+ H5VL_pass_through_dataset_get, /* get */
+ H5VL_pass_through_dataset_specific, /* specific */
+ H5VL_pass_through_dataset_optional, /* optional */
+ H5VL_pass_through_dataset_close /* close */
+ },
+ { /* datatype_cls */
+ H5VL_pass_through_datatype_commit, /* commit */
+ H5VL_pass_through_datatype_open, /* open */
+ H5VL_pass_through_datatype_get, /* get_size */
+ H5VL_pass_through_datatype_specific, /* specific */
+ H5VL_pass_through_datatype_optional, /* optional */
+ H5VL_pass_through_datatype_close /* close */
+ },
+ { /* file_cls */
+ H5VL_pass_through_file_create, /* create */
+ H5VL_pass_through_file_open, /* open */
+ H5VL_pass_through_file_get, /* get */
+ H5VL_pass_through_file_specific, /* specific */
+ H5VL_pass_through_file_optional, /* optional */
+ H5VL_pass_through_file_close /* close */
+ },
+ { /* group_cls */
+ H5VL_pass_through_group_create, /* create */
+ H5VL_pass_through_group_open, /* open */
+ H5VL_pass_through_group_get, /* get */
+ H5VL_pass_through_group_specific, /* specific */
+ H5VL_pass_through_group_optional, /* optional */
+ H5VL_pass_through_group_close /* close */
+ },
+ { /* link_cls */
+ H5VL_pass_through_link_create, /* create */
+ H5VL_pass_through_link_copy, /* copy */
+ H5VL_pass_through_link_move, /* move */
+ H5VL_pass_through_link_get, /* get */
+ H5VL_pass_through_link_specific, /* specific */
+ H5VL_pass_through_link_optional /* optional */
+ },
+ { /* object_cls */
+ H5VL_pass_through_object_open, /* open */
+ H5VL_pass_through_object_copy, /* copy */
+ H5VL_pass_through_object_get, /* get */
+ H5VL_pass_through_object_specific, /* specific */
+ H5VL_pass_through_object_optional /* optional */
+ },
+ { /* request_cls */
+ H5VL_pass_through_request_wait, /* wait */
+ H5VL_pass_through_request_notify, /* notify */
+ H5VL_pass_through_request_cancel, /* cancel */
+ H5VL_pass_through_request_specific, /* specific */
+ H5VL_pass_through_request_optional, /* optional */
+ H5VL_pass_through_request_free /* free */
+ },
+ { /* blob_cls */
+ H5VL_pass_through_blob_put, /* put */
+ H5VL_pass_through_blob_get, /* get */
+ H5VL_pass_through_blob_specific, /* specific */
+ NULL /* optional */
+ },
+ NULL /* optional */
+};
+
+/* The connector identification number, initialized at runtime */
+static hid_t H5VL_PASSTHRU_g = H5I_INVALID_HID;
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__pass_through_new_obj
+ *
+ * Purpose: Create a new pass through object for an underlying object
+ *
+ * Return: Success: Pointer to the new pass through object
+ * Failure: NULL
+ *
+ * Programmer: Quincey Koziol
+ * Monday, December 3, 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5VL_pass_through_t *
+H5VL_pass_through_new_obj(void *under_obj, hid_t under_vol_id)
+{
+ H5VL_pass_through_t *new_obj;
+
+ new_obj = (H5VL_pass_through_t *)calloc(1, sizeof(H5VL_pass_through_t));
+ new_obj->under_object = under_obj;
+ new_obj->under_vol_id = under_vol_id;
+ H5Iinc_ref(new_obj->under_vol_id);
+
+ return new_obj;
+} /* end H5VL__pass_through_new_obj() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__pass_through_free_obj
+ *
+ * Purpose: Release a pass through object
+ *
+ * Note: Take care to preserve the current HDF5 error stack
+ * when calling HDF5 API calls.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ * Programmer: Quincey Koziol
+ * Monday, December 3, 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_free_obj(H5VL_pass_through_t *obj)
+{
+ hid_t err_id;
+
+ err_id = H5Eget_current_stack();
+
+ H5Idec_ref(obj->under_vol_id);
+
+ H5Eset_current_stack(err_id);
+
+ free(obj);
+
+ return 0;
+} /* end H5VL__pass_through_free_obj() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_register
+ *
+ * Purpose: Register the pass-through VOL connector and retrieve an ID
+ * for it.
+ *
+ * Return: Success: The ID for the pass-through VOL connector
+ * Failure: -1
+ *
+ * Programmer: Quincey Koziol
+ * Wednesday, November 28, 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5VL_pass_through_register(void)
+{
+ /* Singleton register the pass-through VOL connector ID */
+ if(H5VL_PASSTHRU_g < 0)
+ H5VL_PASSTHRU_g = H5VLregister_connector(&H5VL_pass_through_g, H5P_DEFAULT);
+
+ return H5VL_PASSTHRU_g;
+} /* end H5VL_pass_through_register() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_init
+ *
+ * Purpose: Initialize this VOL connector, performing any necessary
+ * operations for the connector that will apply to all containers
+ * accessed with the connector.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_init(hid_t vipl_id)
+{
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL INIT\n");
+#endif
+
+ /* Shut compiler up about unused parameter */
+ vipl_id = vipl_id;
+
+ return 0;
+} /* end H5VL_pass_through_init() */
+
+
+/*---------------------------------------------------------------------------
+ * Function: H5VL_pass_through_term
+ *
+ * Purpose: Terminate this VOL connector, performing any necessary
+ * operations for the connector that release connector-wide
+ * resources (usually created / initialized with the 'init'
+ * callback).
+ *
+ * Return: Success: 0
+ * Failure: (Can't fail)
+ *
+ *---------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_term(void)
+{
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL TERM\n");
+#endif
+
+ /* Reset VOL ID */
+ H5VL_PASSTHRU_g = H5I_INVALID_HID;
+
+ return 0;
+} /* end H5VL_pass_through_term() */
+
+
+/*---------------------------------------------------------------------------
+ * Function: H5VL_pass_through_info_copy
+ *
+ * Purpose: Duplicate the connector's info object.
+ *
+ * Returns: Success: New connector info object
+ * Failure: NULL
+ *
+ *---------------------------------------------------------------------------
+ */
+static void *
+H5VL_pass_through_info_copy(const void *_info)
+{
+ const H5VL_pass_through_info_t *info = (const H5VL_pass_through_info_t *)_info;
+ H5VL_pass_through_info_t *new_info;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL INFO Copy\n");
+#endif
+
+ /* Allocate new VOL info struct for the pass through connector */
+ new_info = (H5VL_pass_through_info_t *)calloc(1, sizeof(H5VL_pass_through_info_t));
+
+ /* Increment reference count on underlying VOL ID, and copy the VOL info */
+ new_info->under_vol_id = info->under_vol_id;
+ H5Iinc_ref(new_info->under_vol_id);
+ if(info->under_vol_info)
+ H5VLcopy_connector_info(new_info->under_vol_id, &(new_info->under_vol_info), info->under_vol_info);
+
+ return new_info;
+} /* end H5VL_pass_through_info_copy() */
+
+
+/*---------------------------------------------------------------------------
+ * Function: H5VL_pass_through_info_cmp
+ *
+ * Purpose: Compare two of the connector's info objects, setting *cmp_value,
+ * following the same rules as strcmp().
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *---------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_info_cmp(int *cmp_value, const void *_info1, const void *_info2)
+{
+ const H5VL_pass_through_info_t *info1 = (const H5VL_pass_through_info_t *)_info1;
+ const H5VL_pass_through_info_t *info2 = (const H5VL_pass_through_info_t *)_info2;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL INFO Compare\n");
+#endif
+
+ /* Sanity checks */
+ assert(info1);
+ assert(info2);
+
+ /* Initialize comparison value */
+ *cmp_value = 0;
+
+ /* Compare under VOL connector classes */
+ H5VLcmp_connector_cls(cmp_value, info1->under_vol_id, info2->under_vol_id);
+ if(*cmp_value != 0)
+ return 0;
+
+ /* Compare under VOL connector info objects */
+ H5VLcmp_connector_info(cmp_value, info1->under_vol_id, info1->under_vol_info, info2->under_vol_info);
+ if(*cmp_value != 0)
+ return 0;
+
+ return 0;
+} /* end H5VL_pass_through_info_cmp() */
+
+
+/*---------------------------------------------------------------------------
+ * Function: H5VL_pass_through_info_free
+ *
+ * Purpose: Release an info object for the connector.
+ *
+ * Note: Take care to preserve the current HDF5 error stack
+ * when calling HDF5 API calls.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *---------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_info_free(void *_info)
+{
+ H5VL_pass_through_info_t *info = (H5VL_pass_through_info_t *)_info;
+ hid_t err_id;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL INFO Free\n");
+#endif
+
+ err_id = H5Eget_current_stack();
+
+ /* Release underlying VOL ID and info */
+ if(info->under_vol_info)
+ H5VLfree_connector_info(info->under_vol_id, info->under_vol_info);
+ H5Idec_ref(info->under_vol_id);
+
+ H5Eset_current_stack(err_id);
+
+ /* Free pass through info object itself */
+ free(info);
+
+ return 0;
+} /* end H5VL_pass_through_info_free() */
+
+
+/*---------------------------------------------------------------------------
+ * Function: H5VL_pass_through_info_to_str
+ *
+ * Purpose: Serialize an info object for this connector into a string
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *---------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_info_to_str(const void *_info, char **str)
+{
+ const H5VL_pass_through_info_t *info = (const H5VL_pass_through_info_t *)_info;
+ H5VL_class_value_t under_value = (H5VL_class_value_t)-1;
+ char *under_vol_string = NULL;
+ size_t under_vol_str_len = 0;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL INFO To String\n");
+#endif
+
+ /* Get value and string for underlying VOL connector */
+ H5VLget_value(info->under_vol_id, &under_value);
+ H5VLconnector_info_to_str(info->under_vol_info, info->under_vol_id, &under_vol_string);
+
+ /* Determine length of underlying VOL info string */
+ if(under_vol_string)
+ under_vol_str_len = strlen(under_vol_string);
+
+ /* Allocate space for our info */
+ *str = (char *)H5allocate_memory(32 + under_vol_str_len, (hbool_t)0);
+ assert(*str);
+
+ /* Encode our info
+ * Normally we'd use snprintf() here for a little extra safety, but that
+ * call had problems on Windows until recently. So, to be as platform-independent
+ * as we can, we're using sprintf() instead.
+ */
+ sprintf(*str, "under_vol=%u;under_info={%s}", (unsigned)under_value, (under_vol_string ? under_vol_string : ""));
+
+ return 0;
+} /* end H5VL_pass_through_info_to_str() */
+
+
+/*---------------------------------------------------------------------------
+ * Function: H5VL_pass_through_str_to_info
+ *
+ * Purpose: Deserialize a string into an info object for this connector.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *---------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_str_to_info(const char *str, void **_info)
+{
+ H5VL_pass_through_info_t *info;
+ unsigned under_vol_value;
+ const char *under_vol_info_start, *under_vol_info_end;
+ hid_t under_vol_id;
+ void *under_vol_info = NULL;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL INFO String To Info\n");
+#endif
+
+ /* Retrieve the underlying VOL connector value and info */
+ sscanf(str, "under_vol=%u;", &under_vol_value);
+ under_vol_id = H5VLregister_connector_by_value((H5VL_class_value_t)under_vol_value, H5P_DEFAULT);
+ under_vol_info_start = strchr(str, '{');
+ under_vol_info_end = strrchr(str, '}');
+ assert(under_vol_info_end > under_vol_info_start);
+ if(under_vol_info_end != (under_vol_info_start + 1)) {
+ char *under_vol_info_str;
+
+ under_vol_info_str = (char *)malloc((size_t)(under_vol_info_end - under_vol_info_start));
+ memcpy(under_vol_info_str, under_vol_info_start + 1, (size_t)((under_vol_info_end - under_vol_info_start) - 1));
+ *(under_vol_info_str + (under_vol_info_end - under_vol_info_start)) = '\0';
+
+ H5VLconnector_str_to_info(under_vol_info_str, under_vol_id, &under_vol_info);
+
+ free(under_vol_info_str);
+ } /* end else */
+
+ /* Allocate new pass-through VOL connector info and set its fields */
+ info = (H5VL_pass_through_info_t *)calloc(1, sizeof(H5VL_pass_through_info_t));
+ info->under_vol_id = under_vol_id;
+ info->under_vol_info = under_vol_info;
+
+ /* Set return value */
+ *_info = info;
+
+ return 0;
+} /* end H5VL_pass_through_str_to_info() */
+
+
+/*---------------------------------------------------------------------------
+ * Function: H5VL_pass_through_get_object
+ *
+ * Purpose: Retrieve the 'data' for a VOL object.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *---------------------------------------------------------------------------
+ */
+static void *
+H5VL_pass_through_get_object(const void *obj)
+{
+ const H5VL_pass_through_t *o = (const H5VL_pass_through_t *)obj;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL Get object\n");
+#endif
+
+ return H5VLget_object(o->under_object, o->under_vol_id);
+} /* end H5VL_pass_through_get_object() */
+
+
+/*---------------------------------------------------------------------------
+ * Function: H5VL_pass_through_get_wrap_ctx
+ *
+ * Purpose: Retrieve a "wrapper context" for an object
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *---------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_get_wrap_ctx(const void *obj, void **wrap_ctx)
+{
+ const H5VL_pass_through_t *o = (const H5VL_pass_through_t *)obj;
+ H5VL_pass_through_wrap_ctx_t *new_wrap_ctx;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL WRAP CTX Get\n");
+#endif
+
+ /* Allocate new VOL object wrapping context for the pass through connector */
+ new_wrap_ctx = (H5VL_pass_through_wrap_ctx_t *)calloc(1, sizeof(H5VL_pass_through_wrap_ctx_t));
+
+ /* Increment reference count on underlying VOL ID, and copy the VOL info */
+ new_wrap_ctx->under_vol_id = o->under_vol_id;
+ H5Iinc_ref(new_wrap_ctx->under_vol_id);
+ H5VLget_wrap_ctx(o->under_object, o->under_vol_id, &new_wrap_ctx->under_wrap_ctx);
+
+ /* Set wrap context to return */
+ *wrap_ctx = new_wrap_ctx;
+
+ return 0;
+} /* end H5VL_pass_through_get_wrap_ctx() */
+
+
+/*---------------------------------------------------------------------------
+ * Function: H5VL_pass_through_wrap_object
+ *
+ * Purpose: Use a "wrapper context" to wrap a data object
+ *
+ * Return: Success: Pointer to wrapped object
+ * Failure: NULL
+ *
+ *---------------------------------------------------------------------------
+ */
+static void *
+H5VL_pass_through_wrap_object(void *obj, H5I_type_t obj_type, void *_wrap_ctx)
+{
+ H5VL_pass_through_wrap_ctx_t *wrap_ctx = (H5VL_pass_through_wrap_ctx_t *)_wrap_ctx;
+ H5VL_pass_through_t *new_obj;
+ void *under;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL WRAP Object\n");
+#endif
+
+ /* Wrap the object with the underlying VOL */
+ under = H5VLwrap_object(obj, obj_type, wrap_ctx->under_vol_id, wrap_ctx->under_wrap_ctx);
+ if(under)
+ new_obj = H5VL_pass_through_new_obj(under, wrap_ctx->under_vol_id);
+ else
+ new_obj = NULL;
+
+ return new_obj;
+} /* end H5VL_pass_through_wrap_object() */
+
+
+/*---------------------------------------------------------------------------
+ * Function: H5VL_pass_through_unwrap_object
+ *
+ * Purpose: Unwrap a wrapped object, discarding the wrapper, but returning
+ * underlying object.
+ *
+ * Return: Success: Pointer to unwrapped object
+ * Failure: NULL
+ *
+ *---------------------------------------------------------------------------
+ */
+static void *
+H5VL_pass_through_unwrap_object(void *obj)
+{
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
+ void *under;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL UNWRAP Object\n");
+#endif
+
+ /* Unrap the object with the underlying VOL */
+ under = H5VLunwrap_object(o->under_object, o->under_vol_id);
+
+ if(under)
+ H5VL_pass_through_free_obj(o);
+
+ return under;
+} /* end H5VL_pass_through_unwrap_object() */
+
+
+/*---------------------------------------------------------------------------
+ * Function: H5VL_pass_through_free_wrap_ctx
+ *
+ * Purpose: Release a "wrapper context" for an object
+ *
+ * Note: Take care to preserve the current HDF5 error stack
+ * when calling HDF5 API calls.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *---------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_free_wrap_ctx(void *_wrap_ctx)
+{
+ H5VL_pass_through_wrap_ctx_t *wrap_ctx = (H5VL_pass_through_wrap_ctx_t *)_wrap_ctx;
+ hid_t err_id;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL WRAP CTX Free\n");
+#endif
+
+ err_id = H5Eget_current_stack();
+
+ /* Release underlying VOL ID and wrap context */
+ if(wrap_ctx->under_wrap_ctx)
+ H5VLfree_wrap_ctx(wrap_ctx->under_wrap_ctx, wrap_ctx->under_vol_id);
+ H5Idec_ref(wrap_ctx->under_vol_id);
+
+ H5Eset_current_stack(err_id);
+
+ /* Free pass through wrap context object itself */
+ free(wrap_ctx);
+
+ return 0;
+} /* end H5VL_pass_through_free_wrap_ctx() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_attr_create
+ *
+ * Purpose: Creates an attribute on an object.
+ *
+ * Return: Success: Pointer to attribute object
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5VL_pass_through_attr_create(void *obj, const H5VL_loc_params_t *loc_params,
+ const char *name, hid_t type_id, hid_t space_id, hid_t acpl_id,
+ hid_t aapl_id, hid_t dxpl_id, void **req)
+{
+ H5VL_pass_through_t *attr;
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
+ void *under;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL ATTRIBUTE Create\n");
+#endif
+
+ under = H5VLattr_create(o->under_object, loc_params, o->under_vol_id, name, type_id, space_id, acpl_id, aapl_id, dxpl_id, req);
+ if(under) {
+ attr = H5VL_pass_through_new_obj(under, o->under_vol_id);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
+ } /* end if */
+ else
+ attr = NULL;
+
+ return (void*)attr;
+} /* end H5VL_pass_through_attr_create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_attr_open
+ *
+ * Purpose: Opens an attribute on an object.
+ *
+ * Return: Success: Pointer to attribute object
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5VL_pass_through_attr_open(void *obj, const H5VL_loc_params_t *loc_params,
+ const char *name, hid_t aapl_id, hid_t dxpl_id, void **req)
+{
+ H5VL_pass_through_t *attr;
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
+ void *under;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL ATTRIBUTE Open\n");
+#endif
+
+ under = H5VLattr_open(o->under_object, loc_params, o->under_vol_id, name, aapl_id, dxpl_id, req);
+ if(under) {
+ attr = H5VL_pass_through_new_obj(under, o->under_vol_id);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
+ } /* end if */
+ else
+ attr = NULL;
+
+ return (void *)attr;
+} /* end H5VL_pass_through_attr_open() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_attr_read
+ *
+ * Purpose: Reads data from attribute.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_attr_read(void *attr, hid_t mem_type_id, void *buf,
+ hid_t dxpl_id, void **req)
+{
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)attr;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL ATTRIBUTE Read\n");
+#endif
+
+ ret_value = H5VLattr_read(o->under_object, o->under_vol_id, mem_type_id, buf, dxpl_id, req);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
+
+ return ret_value;
+} /* end H5VL_pass_through_attr_read() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_attr_write
+ *
+ * Purpose: Writes data to attribute.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_attr_write(void *attr, hid_t mem_type_id, const void *buf,
+ hid_t dxpl_id, void **req)
+{
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)attr;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL ATTRIBUTE Write\n");
+#endif
+
+ ret_value = H5VLattr_write(o->under_object, o->under_vol_id, mem_type_id, buf, dxpl_id, req);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
+
+ return ret_value;
+} /* end H5VL_pass_through_attr_write() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_attr_get
+ *
+ * Purpose: Gets information about an attribute
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_attr_get(void *obj, H5VL_attr_get_t get_type, hid_t dxpl_id,
+ void **req, va_list arguments)
+{
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL ATTRIBUTE Get\n");
+#endif
+
+ ret_value = H5VLattr_get(o->under_object, o->under_vol_id, get_type, dxpl_id, req, arguments);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
+
+ return ret_value;
+} /* end H5VL_pass_through_attr_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_attr_specific
+ *
+ * Purpose: Specific operation on attribute
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_attr_specific(void *obj, const H5VL_loc_params_t *loc_params,
+ H5VL_attr_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments)
+{
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL ATTRIBUTE Specific\n");
+#endif
+
+ ret_value = H5VLattr_specific(o->under_object, loc_params, o->under_vol_id, specific_type, dxpl_id, req, arguments);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
+
+ return ret_value;
+} /* end H5VL_pass_through_attr_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_attr_optional
+ *
+ * Purpose: Perform a connector-specific operation on an attribute
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_attr_optional(void *obj, hid_t dxpl_id, void **req,
+ va_list arguments)
+{
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL ATTRIBUTE Optional\n");
+#endif
+
+ ret_value = H5VLattr_optional(o->under_object, o->under_vol_id, dxpl_id, req, arguments);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
+
+ return ret_value;
+} /* end H5VL_pass_through_attr_optional() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_attr_close
+ *
+ * Purpose: Closes an attribute.
+ *
+ * Return: Success: 0
+ * Failure: -1, attr not closed.
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_attr_close(void *attr, hid_t dxpl_id, void **req)
+{
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)attr;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL ATTRIBUTE Close\n");
+#endif
+
+ ret_value = H5VLattr_close(o->under_object, o->under_vol_id, dxpl_id, req);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
+
+ /* Release our wrapper, if underlying attribute was closed */
+ if(ret_value >= 0)
+ H5VL_pass_through_free_obj(o);
+
+ return ret_value;
+} /* end H5VL_pass_through_attr_close() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_dataset_create
+ *
+ * Purpose: Creates a dataset in a container
+ *
+ * Return: Success: Pointer to a dataset object
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5VL_pass_through_dataset_create(void *obj, const H5VL_loc_params_t *loc_params,
+ const char *name, hid_t lcpl_id, hid_t type_id, hid_t space_id,
+ hid_t dcpl_id, hid_t dapl_id, hid_t dxpl_id, void **req)
+{
+ H5VL_pass_through_t *dset;
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
+ void *under;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL DATASET Create\n");
+#endif
+
+ under = H5VLdataset_create(o->under_object, loc_params, o->under_vol_id, name, lcpl_id, type_id, space_id, dcpl_id, dapl_id, dxpl_id, req);
+ if(under) {
+ dset = H5VL_pass_through_new_obj(under, o->under_vol_id);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
+ } /* end if */
+ else
+ dset = NULL;
+
+ return (void *)dset;
+} /* end H5VL_pass_through_dataset_create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_dataset_open
+ *
+ * Purpose: Opens a dataset in a container
+ *
+ * Return: Success: Pointer to a dataset object
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+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)
+{
+ H5VL_pass_through_t *dset;
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
+ void *under;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL DATASET Open\n");
+#endif
+
+ under = H5VLdataset_open(o->under_object, loc_params, o->under_vol_id, name, dapl_id, dxpl_id, req);
+ if(under) {
+ dset = H5VL_pass_through_new_obj(under, o->under_vol_id);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
+ } /* end if */
+ else
+ dset = NULL;
+
+ return (void *)dset;
+} /* end H5VL_pass_through_dataset_open() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_dataset_read
+ *
+ * Purpose: Reads data elements from a dataset into a buffer.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+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_t *o = (H5VL_pass_through_t *)dset;
+ 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);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
+
+ return ret_value;
+} /* end H5VL_pass_through_dataset_read() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_dataset_write
+ *
+ * Purpose: Writes data elements from a buffer into a dataset.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+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_t *o = (H5VL_pass_through_t *)dset;
+ 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);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
+
+ return ret_value;
+} /* end H5VL_pass_through_dataset_write() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_dataset_get
+ *
+ * Purpose: Gets information about a dataset
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_dataset_get(void *dset, H5VL_dataset_get_t get_type,
+ hid_t dxpl_id, void **req, va_list arguments)
+{
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)dset;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL DATASET Get\n");
+#endif
+
+ ret_value = H5VLdataset_get(o->under_object, o->under_vol_id, get_type, dxpl_id, req, arguments);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
+
+ return ret_value;
+} /* end H5VL_pass_through_dataset_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_dataset_specific
+ *
+ * Purpose: Specific operation on a dataset
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_dataset_specific(void *obj, H5VL_dataset_specific_t specific_type,
+ hid_t dxpl_id, void **req, va_list arguments)
+{
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
+ hid_t under_vol_id;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL H5Dspecific\n");
+#endif
+
+ // Save copy of underlying VOL connector ID and prov helper, in case of
+ // refresh destroying the current object
+ under_vol_id = o->under_vol_id;
+
+ ret_value = H5VLdataset_specific(o->under_object, o->under_vol_id, specific_type, dxpl_id, req, arguments);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, under_vol_id);
+
+ return ret_value;
+} /* end H5VL_pass_through_dataset_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_dataset_optional
+ *
+ * Purpose: Perform a connector-specific operation on a dataset
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_dataset_optional(void *obj, hid_t dxpl_id, void **req,
+ va_list arguments)
+{
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL DATASET Optional\n");
+#endif
+
+ ret_value = H5VLdataset_optional(o->under_object, o->under_vol_id, dxpl_id, req, arguments);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
+
+ return ret_value;
+} /* end H5VL_pass_through_dataset_optional() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_dataset_close
+ *
+ * Purpose: Closes a dataset.
+ *
+ * Return: Success: 0
+ * Failure: -1, dataset not closed.
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_dataset_close(void *dset, hid_t dxpl_id, void **req)
+{
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)dset;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL DATASET Close\n");
+#endif
+
+ ret_value = H5VLdataset_close(o->under_object, o->under_vol_id, dxpl_id, req);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
+
+ /* Release our wrapper, if underlying dataset was closed */
+ if(ret_value >= 0)
+ H5VL_pass_through_free_obj(o);
+
+ return ret_value;
+} /* end H5VL_pass_through_dataset_close() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_datatype_commit
+ *
+ * Purpose: Commits a datatype inside a container.
+ *
+ * Return: Success: Pointer to datatype object
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5VL_pass_through_datatype_commit(void *obj, const H5VL_loc_params_t *loc_params,
+ const char *name, hid_t type_id, hid_t lcpl_id, hid_t tcpl_id, hid_t tapl_id,
+ hid_t dxpl_id, void **req)
+{
+ H5VL_pass_through_t *dt;
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
+ void *under;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL DATATYPE Commit\n");
+#endif
+
+ under = H5VLdatatype_commit(o->under_object, loc_params, o->under_vol_id, name, type_id, lcpl_id, tcpl_id, tapl_id, dxpl_id, req);
+ if(under) {
+ dt = H5VL_pass_through_new_obj(under, o->under_vol_id);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
+ } /* end if */
+ else
+ dt = NULL;
+
+ return (void *)dt;
+} /* end H5VL_pass_through_datatype_commit() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_datatype_open
+ *
+ * Purpose: Opens a named datatype inside a container.
+ *
+ * Return: Success: Pointer to datatype object
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5VL_pass_through_datatype_open(void *obj, const H5VL_loc_params_t *loc_params,
+ const char *name, hid_t tapl_id, hid_t dxpl_id, void **req)
+{
+ H5VL_pass_through_t *dt;
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
+ void *under;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL DATATYPE Open\n");
+#endif
+
+ under = H5VLdatatype_open(o->under_object, loc_params, o->under_vol_id, name, tapl_id, dxpl_id, req);
+ if(under) {
+ dt = H5VL_pass_through_new_obj(under, o->under_vol_id);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
+ } /* end if */
+ else
+ dt = NULL;
+
+ return (void *)dt;
+} /* end H5VL_pass_through_datatype_open() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_datatype_get
+ *
+ * Purpose: Get information about a datatype
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_datatype_get(void *dt, H5VL_datatype_get_t get_type,
+ hid_t dxpl_id, void **req, va_list arguments)
+{
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)dt;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL DATATYPE Get\n");
+#endif
+
+ ret_value = H5VLdatatype_get(o->under_object, o->under_vol_id, get_type, dxpl_id, req, arguments);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
+
+ return ret_value;
+} /* end H5VL_pass_through_datatype_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_datatype_specific
+ *
+ * Purpose: Specific operations for datatypes
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_datatype_specific(void *obj, H5VL_datatype_specific_t specific_type,
+ hid_t dxpl_id, void **req, va_list arguments)
+{
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
+ hid_t under_vol_id;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL DATATYPE Specific\n");
+#endif
+
+ // Save copy of underlying VOL connector ID and prov helper, in case of
+ // refresh destroying the current object
+ under_vol_id = o->under_vol_id;
+
+ ret_value = H5VLdatatype_specific(o->under_object, o->under_vol_id, specific_type, dxpl_id, req, arguments);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, under_vol_id);
+
+ return ret_value;
+} /* end H5VL_pass_through_datatype_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_datatype_optional
+ *
+ * Purpose: Perform a connector-specific operation on a datatype
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_datatype_optional(void *obj, hid_t dxpl_id, void **req,
+ va_list arguments)
+{
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL DATATYPE Optional\n");
+#endif
+
+ ret_value = H5VLdatatype_optional(o->under_object, o->under_vol_id, dxpl_id, req, arguments);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
+
+ return ret_value;
+} /* end H5VL_pass_through_datatype_optional() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_datatype_close
+ *
+ * Purpose: Closes a datatype.
+ *
+ * Return: Success: 0
+ * Failure: -1, datatype not closed.
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_datatype_close(void *dt, hid_t dxpl_id, void **req)
+{
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)dt;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL DATATYPE Close\n");
+#endif
+
+ assert(o->under_object);
+
+ ret_value = H5VLdatatype_close(o->under_object, o->under_vol_id, dxpl_id, req);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
+
+ /* Release our wrapper, if underlying datatype was closed */
+ if(ret_value >= 0)
+ H5VL_pass_through_free_obj(o);
+
+ return ret_value;
+} /* end H5VL_pass_through_datatype_close() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_file_create
+ *
+ * Purpose: Creates a container using this connector
+ *
+ * Return: Success: Pointer to a file object
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5VL_pass_through_file_create(const char *name, unsigned flags, hid_t fcpl_id,
+ hid_t fapl_id, hid_t dxpl_id, void **req)
+{
+ H5VL_pass_through_info_t *info;
+ H5VL_pass_through_t *file;
+ hid_t under_fapl_id;
+ void *under;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL FILE Create\n");
+#endif
+
+ /* Get copy of our VOL info from FAPL */
+ H5Pget_vol_info(fapl_id, (void **)&info);
+
+ /* Copy the FAPL */
+ under_fapl_id = H5Pcopy(fapl_id);
+
+ /* Set the VOL ID and info for the underlying FAPL */
+ H5Pset_vol(under_fapl_id, info->under_vol_id, info->under_vol_info);
+
+ /* Open the file with the underlying VOL connector */
+ under = H5VLfile_create(name, flags, fcpl_id, under_fapl_id, dxpl_id, req);
+ if(under) {
+ file = H5VL_pass_through_new_obj(under, info->under_vol_id);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, info->under_vol_id);
+ } /* end if */
+ else
+ file = NULL;
+
+ /* Close underlying FAPL */
+ H5Pclose(under_fapl_id);
+
+ /* Release copy of our VOL info */
+ H5VL_pass_through_info_free(info);
+
+ return (void *)file;
+} /* end H5VL_pass_through_file_create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_file_open
+ *
+ * Purpose: Opens a container created with this connector
+ *
+ * Return: Success: Pointer to a file object
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5VL_pass_through_file_open(const char *name, unsigned flags, hid_t fapl_id,
+ hid_t dxpl_id, void **req)
+{
+ H5VL_pass_through_info_t *info;
+ H5VL_pass_through_t *file;
+ hid_t under_fapl_id;
+ void *under;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL FILE Open\n");
+#endif
+
+ /* Get copy of our VOL info from FAPL */
+ H5Pget_vol_info(fapl_id, (void **)&info);
+
+ /* Copy the FAPL */
+ under_fapl_id = H5Pcopy(fapl_id);
+
+ /* Set the VOL ID and info for the underlying FAPL */
+ H5Pset_vol(under_fapl_id, info->under_vol_id, info->under_vol_info);
+
+ /* Open the file with the underlying VOL connector */
+ under = H5VLfile_open(name, flags, under_fapl_id, dxpl_id, req);
+ if(under) {
+ file = H5VL_pass_through_new_obj(under, info->under_vol_id);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, info->under_vol_id);
+ } /* end if */
+ else
+ file = NULL;
+
+ /* Close underlying FAPL */
+ H5Pclose(under_fapl_id);
+
+ /* Release copy of our VOL info */
+ H5VL_pass_through_info_free(info);
+
+ return (void *)file;
+} /* end H5VL_pass_through_file_open() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_file_get
+ *
+ * Purpose: Get info about a file
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_file_get(void *file, H5VL_file_get_t get_type, hid_t dxpl_id,
+ void **req, va_list arguments)
+{
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)file;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL FILE Get\n");
+#endif
+
+ ret_value = H5VLfile_get(o->under_object, o->under_vol_id, get_type, dxpl_id, req, arguments);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
+
+ return ret_value;
+} /* end H5VL_pass_through_file_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_file_specific_reissue
+ *
+ * Purpose: Re-wrap vararg arguments into a va_list and reissue the
+ * file specific callback to the underlying VOL connector.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_file_specific_reissue(void *obj, hid_t connector_id,
+ H5VL_file_specific_t specific_type, hid_t dxpl_id, void **req, ...)
+{
+ va_list arguments;
+ herr_t ret_value;
+
+ va_start(arguments, req);
+ ret_value = H5VLfile_specific(obj, connector_id, specific_type, dxpl_id, req, arguments);
+ va_end(arguments);
+
+ return ret_value;
+} /* end H5VL_pass_through_file_specific_reissue() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_file_specific
+ *
+ * Purpose: Specific operation on file
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_file_specific(void *file, H5VL_file_specific_t specific_type,
+ hid_t dxpl_id, void **req, va_list arguments)
+{
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)file;
+ hid_t under_vol_id = -1;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL FILE Specific\n");
+#endif
+
+ /* Unpack arguments to get at the child file pointer when mounting a file */
+ if(specific_type == H5VL_FILE_MOUNT) {
+ H5I_type_t loc_type;
+ const char *name;
+ H5VL_pass_through_t *child_file;
+ hid_t plist_id;
+
+ /* Retrieve parameters for 'mount' operation, so we can unwrap the child file */
+ loc_type = (H5I_type_t)va_arg(arguments, int); /* enum work-around */
+ name = va_arg(arguments, const char *);
+ child_file = (H5VL_pass_through_t *)va_arg(arguments, void *);
+ plist_id = va_arg(arguments, hid_t);
+
+ /* Keep the correct underlying VOL ID for possible async request token */
+ under_vol_id = o->under_vol_id;
+
+ /* Re-issue 'file specific' call, using the unwrapped pieces */
+ ret_value = H5VL_pass_through_file_specific_reissue(o->under_object, o->under_vol_id, specific_type, dxpl_id, req, (int)loc_type, name, child_file->under_object, plist_id);
+ } /* end if */
+ else if(specific_type == H5VL_FILE_IS_ACCESSIBLE || specific_type == H5VL_FILE_DELETE) {
+ H5VL_pass_through_info_t *info;
+ hid_t fapl_id, under_fapl_id;
+ const char *name;
+ htri_t *ret;
+
+ /* Get the arguments for the 'is accessible' check */
+ fapl_id = va_arg(arguments, hid_t);
+ name = va_arg(arguments, const char *);
+ ret = va_arg(arguments, htri_t *);
+
+ /* Get copy of our VOL info from FAPL */
+ H5Pget_vol_info(fapl_id, (void **)&info);
+
+ /* Copy the FAPL */
+ under_fapl_id = H5Pcopy(fapl_id);
+
+ /* Set the VOL ID and info for the underlying FAPL */
+ H5Pset_vol(under_fapl_id, info->under_vol_id, info->under_vol_info);
+
+ /* Keep the correct underlying VOL ID for possible async request token */
+ under_vol_id = info->under_vol_id;
+
+ /* Re-issue 'file specific' call */
+ ret_value = H5VL_pass_through_file_specific_reissue(NULL, info->under_vol_id, specific_type, dxpl_id, req, under_fapl_id, name, ret);
+
+ /* Close underlying FAPL */
+ H5Pclose(under_fapl_id);
+
+ /* Release copy of our VOL info */
+ H5VL_pass_through_info_free(info);
+ } /* end else-if */
+ else {
+ va_list my_arguments;
+
+ /* Make a copy of the argument list for later, if reopening */
+ if(specific_type == H5VL_FILE_REOPEN)
+ va_copy(my_arguments, arguments);
+
+ /* Keep the correct underlying VOL ID for possible async request token */
+ under_vol_id = o->under_vol_id;
+
+ ret_value = H5VLfile_specific(o->under_object, o->under_vol_id, specific_type, dxpl_id, req, arguments);
+
+ /* Wrap file struct pointer, if we reopened one */
+ if(specific_type == H5VL_FILE_REOPEN) {
+ if(ret_value >= 0) {
+ void **ret = va_arg(my_arguments, void **);
+
+ if(ret && *ret)
+ *ret = H5VL_pass_through_new_obj(*ret, o->under_vol_id);
+ } /* end if */
+
+ /* Finish use of copied vararg list */
+ va_end(my_arguments);
+ } /* end if */
+ } /* end else */
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, under_vol_id);
+
+ return ret_value;
+} /* end H5VL_pass_through_file_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_file_optional
+ *
+ * Purpose: Perform a connector-specific operation on a file
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_file_optional(void *file, hid_t dxpl_id, void **req,
+ va_list arguments)
+{
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)file;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL File Optional\n");
+#endif
+
+ ret_value = H5VLfile_optional(o->under_object, o->under_vol_id, dxpl_id, req, arguments);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
+
+ return ret_value;
+} /* end H5VL_pass_through_file_optional() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_file_close
+ *
+ * Purpose: Closes a file.
+ *
+ * Return: Success: 0
+ * Failure: -1, file not closed.
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_file_close(void *file, hid_t dxpl_id, void **req)
+{
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)file;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL FILE Close\n");
+#endif
+
+ ret_value = H5VLfile_close(o->under_object, o->under_vol_id, dxpl_id, req);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
+
+ /* Release our wrapper, if underlying file was closed */
+ if(ret_value >= 0)
+ H5VL_pass_through_free_obj(o);
+
+ return ret_value;
+} /* end H5VL_pass_through_file_close() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_group_create
+ *
+ * Purpose: Creates a group inside a container
+ *
+ * Return: Success: Pointer to a group object
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5VL_pass_through_group_create(void *obj, const H5VL_loc_params_t *loc_params,
+ const char *name, hid_t lcpl_id, hid_t gcpl_id, hid_t gapl_id,
+ hid_t dxpl_id, void **req)
+{
+ H5VL_pass_through_t *group;
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
+ void *under;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL GROUP Create\n");
+#endif
+
+ under = H5VLgroup_create(o->under_object, loc_params, o->under_vol_id, name, lcpl_id, gcpl_id, gapl_id, dxpl_id, req);
+ if(under) {
+ group = H5VL_pass_through_new_obj(under, o->under_vol_id);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
+ } /* end if */
+ else
+ group = NULL;
+
+ return (void *)group;
+} /* end H5VL_pass_through_group_create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_group_open
+ *
+ * Purpose: Opens a group inside a container
+ *
+ * Return: Success: Pointer to a group object
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5VL_pass_through_group_open(void *obj, const H5VL_loc_params_t *loc_params,
+ const char *name, hid_t gapl_id, hid_t dxpl_id, void **req)
+{
+ H5VL_pass_through_t *group;
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
+ void *under;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL GROUP Open\n");
+#endif
+
+ under = H5VLgroup_open(o->under_object, loc_params, o->under_vol_id, name, gapl_id, dxpl_id, req);
+ if(under) {
+ group = H5VL_pass_through_new_obj(under, o->under_vol_id);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
+ } /* end if */
+ else
+ group = NULL;
+
+ return (void *)group;
+} /* end H5VL_pass_through_group_open() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_group_get
+ *
+ * Purpose: Get info about a group
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_group_get(void *obj, H5VL_group_get_t get_type, hid_t dxpl_id,
+ void **req, va_list arguments)
+{
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL GROUP Get\n");
+#endif
+
+ ret_value = H5VLgroup_get(o->under_object, o->under_vol_id, get_type, dxpl_id, req, arguments);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
+
+ return ret_value;
+} /* end H5VL_pass_through_group_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_group_specific
+ *
+ * Purpose: Specific operation on a group
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_group_specific(void *obj, H5VL_group_specific_t specific_type,
+ hid_t dxpl_id, void **req, va_list arguments)
+{
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
+ hid_t under_vol_id;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL GROUP Specific\n");
+#endif
+
+ // Save copy of underlying VOL connector ID and prov helper, in case of
+ // refresh destroying the current object
+ under_vol_id = o->under_vol_id;
+
+ ret_value = H5VLgroup_specific(o->under_object, o->under_vol_id, specific_type, dxpl_id, req, arguments);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, under_vol_id);
+
+ return ret_value;
+} /* end H5VL_pass_through_group_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_group_optional
+ *
+ * Purpose: Perform a connector-specific operation on a group
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_group_optional(void *obj, hid_t dxpl_id, void **req,
+ va_list arguments)
+{
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL GROUP Optional\n");
+#endif
+
+ ret_value = H5VLgroup_optional(o->under_object, o->under_vol_id, dxpl_id, req, arguments);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
+
+ return ret_value;
+} /* end H5VL_pass_through_group_optional() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_group_close
+ *
+ * Purpose: Closes a group.
+ *
+ * Return: Success: 0
+ * Failure: -1, group not closed.
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_group_close(void *grp, hid_t dxpl_id, void **req)
+{
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)grp;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL H5Gclose\n");
+#endif
+
+ ret_value = H5VLgroup_close(o->under_object, o->under_vol_id, dxpl_id, req);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
+
+ /* Release our wrapper, if underlying file was closed */
+ if(ret_value >= 0)
+ H5VL_pass_through_free_obj(o);
+
+ return ret_value;
+} /* end H5VL_pass_through_group_close() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_link_create_reissue
+ *
+ * Purpose: Re-wrap vararg arguments into a va_list and reissue the
+ * link create callback to the underlying VOL connector.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_link_create_reissue(H5VL_link_create_type_t create_type,
+ void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id,
+ hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id, void **req, ...)
+{
+ va_list arguments;
+ herr_t ret_value;
+
+ va_start(arguments, req);
+ ret_value = H5VLlink_create(create_type, obj, loc_params, connector_id, lcpl_id, lapl_id, dxpl_id, req, arguments);
+ va_end(arguments);
+
+ return ret_value;
+} /* end H5VL_pass_through_link_create_reissue() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_link_create
+ *
+ * Purpose: Creates a hard / soft / UD / external link.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_link_create(H5VL_link_create_type_t create_type, void *obj,
+ const H5VL_loc_params_t *loc_params, hid_t lcpl_id, hid_t lapl_id,
+ hid_t dxpl_id, void **req, va_list arguments)
+{
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
+ hid_t under_vol_id = -1;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL LINK Create\n");
+#endif
+
+ /* Try to retrieve the "under" VOL id */
+ if(o)
+ under_vol_id = o->under_vol_id;
+
+ /* Fix up the link target object for hard link creation */
+ if(H5VL_LINK_CREATE_HARD == create_type) {
+ void *cur_obj;
+ H5VL_loc_params_t *cur_params;
+
+ /* Retrieve the object & loc params for the link target */
+ cur_obj = va_arg(arguments, void *);
+ cur_params = va_arg(arguments, H5VL_loc_params_t *);
+
+ /* If it's a non-NULL pointer, find the 'under object' and re-set the property */
+ if(cur_obj) {
+ /* Check if we still need the "under" VOL ID */
+ if(under_vol_id < 0)
+ under_vol_id = ((H5VL_pass_through_t *)cur_obj)->under_vol_id;
+
+ /* Set the object for the link target */
+ cur_obj = ((H5VL_pass_through_t *)cur_obj)->under_object;
+ } /* end if */
+
+ /* Re-issue 'link create' call, using the unwrapped pieces */
+ ret_value = H5VL_pass_through_link_create_reissue(create_type, (o ? o->under_object : NULL), loc_params, under_vol_id, lcpl_id, lapl_id, dxpl_id, req, cur_obj, cur_params);
+ } /* end if */
+ else
+ ret_value = H5VLlink_create(create_type, (o ? o->under_object : NULL), loc_params, under_vol_id, lcpl_id, lapl_id, dxpl_id, req, arguments);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, under_vol_id);
+
+ return ret_value;
+} /* end H5VL_pass_through_link_create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_link_copy
+ *
+ * Purpose: Renames an object within an HDF5 container and copies it to a new
+ * group. The original name SRC is unlinked from the group graph
+ * and then inserted with the new name DST (which can specify a
+ * new path for the object) as an atomic operation. The names
+ * are interpreted relative to SRC_LOC_ID and
+ * DST_LOC_ID, which are either file IDs or group ID.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_link_copy(void *src_obj, const H5VL_loc_params_t *loc_params1,
+ void *dst_obj, const H5VL_loc_params_t *loc_params2, hid_t lcpl_id,
+ hid_t lapl_id, hid_t dxpl_id, void **req)
+{
+ H5VL_pass_through_t *o_src = (H5VL_pass_through_t *)src_obj;
+ H5VL_pass_through_t *o_dst = (H5VL_pass_through_t *)dst_obj;
+ hid_t under_vol_id = -1;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL LINK Copy\n");
+#endif
+
+ /* Retrieve the "under" VOL id */
+ if(o_src)
+ under_vol_id = o_src->under_vol_id;
+ else if(o_dst)
+ under_vol_id = o_dst->under_vol_id;
+ assert(under_vol_id > 0);
+
+ ret_value = H5VLlink_copy((o_src ? o_src->under_object : NULL), loc_params1, (o_dst ? o_dst->under_object : NULL), loc_params2, under_vol_id, lcpl_id, lapl_id, dxpl_id, req);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, under_vol_id);
+
+ return ret_value;
+} /* end H5VL_pass_through_link_copy() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_link_move
+ *
+ * Purpose: Moves a link within an HDF5 file to a new group. The original
+ * name SRC is unlinked from the group graph
+ * and then inserted with the new name DST (which can specify a
+ * new path for the object) as an atomic operation. The names
+ * are interpreted relative to SRC_LOC_ID and
+ * DST_LOC_ID, which are either file IDs or group ID.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_link_move(void *src_obj, const H5VL_loc_params_t *loc_params1,
+ void *dst_obj, const H5VL_loc_params_t *loc_params2, hid_t lcpl_id,
+ hid_t lapl_id, hid_t dxpl_id, void **req)
+{
+ H5VL_pass_through_t *o_src = (H5VL_pass_through_t *)src_obj;
+ H5VL_pass_through_t *o_dst = (H5VL_pass_through_t *)dst_obj;
+ hid_t under_vol_id = -1;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL LINK Move\n");
+#endif
+
+ /* Retrieve the "under" VOL id */
+ if(o_src)
+ under_vol_id = o_src->under_vol_id;
+ else if(o_dst)
+ under_vol_id = o_dst->under_vol_id;
+ assert(under_vol_id > 0);
+
+ ret_value = H5VLlink_move((o_src ? o_src->under_object : NULL), loc_params1, (o_dst ? o_dst->under_object : NULL), loc_params2, under_vol_id, lcpl_id, lapl_id, dxpl_id, req);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, under_vol_id);
+
+ return ret_value;
+} /* end H5VL_pass_through_link_move() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_link_get
+ *
+ * Purpose: Get info about a link
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_link_get(void *obj, const H5VL_loc_params_t *loc_params,
+ H5VL_link_get_t get_type, hid_t dxpl_id, void **req, va_list arguments)
+{
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL LINK Get\n");
+#endif
+
+ ret_value = H5VLlink_get(o->under_object, loc_params, o->under_vol_id, get_type, dxpl_id, req, arguments);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
+
+ return ret_value;
+} /* end H5VL_pass_through_link_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_link_specific
+ *
+ * Purpose: Specific operation on a link
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_link_specific(void *obj, const H5VL_loc_params_t *loc_params,
+ H5VL_link_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments)
+{
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL LINK Specific\n");
+#endif
+
+ ret_value = H5VLlink_specific(o->under_object, loc_params, o->under_vol_id, specific_type, dxpl_id, req, arguments);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
+
+ return ret_value;
+} /* end H5VL_pass_through_link_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_link_optional
+ *
+ * Purpose: Perform a connector-specific operation on a link
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_link_optional(void *obj, hid_t dxpl_id, void **req,
+ va_list arguments)
+{
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL LINK Optional\n");
+#endif
+
+ ret_value = H5VLlink_optional(o->under_object, o->under_vol_id, dxpl_id, req, arguments);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
+
+ return ret_value;
+} /* end H5VL_pass_through_link_optional() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_object_open
+ *
+ * Purpose: Opens an object inside a container.
+ *
+ * Return: Success: Pointer to object
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5VL_pass_through_object_open(void *obj, const H5VL_loc_params_t *loc_params,
+ H5I_type_t *opened_type, hid_t dxpl_id, void **req)
+{
+ H5VL_pass_through_t *new_obj;
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
+ void *under;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL OBJECT Open\n");
+#endif
+
+ under = H5VLobject_open(o->under_object, loc_params, o->under_vol_id, opened_type, dxpl_id, req);
+ if(under) {
+ new_obj = H5VL_pass_through_new_obj(under, o->under_vol_id);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
+ } /* end if */
+ else
+ new_obj = NULL;
+
+ return (void *)new_obj;
+} /* end H5VL_pass_through_object_open() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_object_copy
+ *
+ * Purpose: Copies an object inside a container.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_object_copy(void *src_obj, const H5VL_loc_params_t *src_loc_params,
+ const char *src_name, void *dst_obj, const H5VL_loc_params_t *dst_loc_params,
+ const char *dst_name, hid_t ocpypl_id, hid_t lcpl_id, hid_t dxpl_id,
+ void **req)
+{
+ H5VL_pass_through_t *o_src = (H5VL_pass_through_t *)src_obj;
+ H5VL_pass_through_t *o_dst = (H5VL_pass_through_t *)dst_obj;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL OBJECT Copy\n");
+#endif
+
+ ret_value = H5VLobject_copy(o_src->under_object, src_loc_params, src_name, o_dst->under_object, dst_loc_params, dst_name, o_src->under_vol_id, ocpypl_id, lcpl_id, dxpl_id, req);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, o_src->under_vol_id);
+
+ return ret_value;
+} /* end H5VL_pass_through_object_copy() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_object_get
+ *
+ * Purpose: Get info about an object
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_object_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_get_t get_type, hid_t dxpl_id, void **req, va_list arguments)
+{
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL OBJECT Get\n");
+#endif
+
+ ret_value = H5VLobject_get(o->under_object, loc_params, o->under_vol_id, get_type, dxpl_id, req, arguments);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
+
+ return ret_value;
+} /* end H5VL_pass_through_object_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_object_specific
+ *
+ * Purpose: Specific operation on an object
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_object_specific(void *obj, const H5VL_loc_params_t *loc_params,
+ H5VL_object_specific_t specific_type, hid_t dxpl_id, void **req,
+ va_list arguments)
+{
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
+ hid_t under_vol_id;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL OBJECT Specific\n");
+#endif
+
+ // Save copy of underlying VOL connector ID and prov helper, in case of
+ // refresh destroying the current object
+ under_vol_id = o->under_vol_id;
+
+ ret_value = H5VLobject_specific(o->under_object, loc_params, o->under_vol_id, specific_type, dxpl_id, req, arguments);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, under_vol_id);
+
+ return ret_value;
+} /* end H5VL_pass_through_object_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_object_optional
+ *
+ * Purpose: Perform a connector-specific operation for an object
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_object_optional(void *obj, hid_t dxpl_id, void **req,
+ va_list arguments)
+{
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL OBJECT Optional\n");
+#endif
+
+ ret_value = H5VLobject_optional(o->under_object, o->under_vol_id, dxpl_id, req, arguments);
+
+ /* Check for async request */
+ if(req && *req)
+ *req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
+
+ return ret_value;
+} /* end H5VL_pass_through_object_optional() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_request_wait
+ *
+ * Purpose: Wait (with a timeout) for an async operation to complete
+ *
+ * Note: Releases the request if the operation has completed and the
+ * connector callback succeeds
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_request_wait(void *obj, uint64_t timeout,
+ H5ES_status_t *status)
+{
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL REQUEST Wait\n");
+#endif
+
+ ret_value = H5VLrequest_wait(o->under_object, o->under_vol_id, timeout, status);
+
+ if(ret_value >= 0 && *status != H5ES_STATUS_IN_PROGRESS)
+ H5VL_pass_through_free_obj(o);
+
+ return ret_value;
+} /* end H5VL_pass_through_request_wait() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_request_notify
+ *
+ * Purpose: Registers a user callback to be invoked when an asynchronous
+ * operation completes
+ *
+ * Note: Releases the request, if connector callback succeeds
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_request_notify(void *obj, H5VL_request_notify_t cb, void *ctx)
+{
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL REQUEST Wait\n");
+#endif
+
+ ret_value = H5VLrequest_notify(o->under_object, o->under_vol_id, cb, ctx);
+
+ if(ret_value >= 0)
+ H5VL_pass_through_free_obj(o);
+
+ return ret_value;
+} /* end H5VL_pass_through_request_notify() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_request_cancel
+ *
+ * Purpose: Cancels an asynchronous operation
+ *
+ * Note: Releases the request, if connector callback succeeds
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_request_cancel(void *obj)
+{
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL REQUEST Cancel\n");
+#endif
+
+ ret_value = H5VLrequest_cancel(o->under_object, o->under_vol_id);
+
+ if(ret_value >= 0)
+ H5VL_pass_through_free_obj(o);
+
+ return ret_value;
+} /* end H5VL_pass_through_request_cancel() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_request_specific_reissue
+ *
+ * Purpose: Re-wrap vararg arguments into a va_list and reissue the
+ * request specific callback to the underlying VOL connector.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_request_specific_reissue(void *obj, hid_t connector_id,
+ H5VL_request_specific_t specific_type, ...)
+{
+ va_list arguments;
+ herr_t ret_value;
+
+ va_start(arguments, specific_type);
+ ret_value = H5VLrequest_specific(obj, connector_id, specific_type, arguments);
+ va_end(arguments);
+
+ return ret_value;
+} /* end H5VL_pass_through_request_specific_reissue() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_request_specific
+ *
+ * Purpose: Specific operation on a request
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_request_specific(void *obj, H5VL_request_specific_t specific_type,
+ va_list arguments)
+{
+ herr_t ret_value = -1;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL REQUEST Specific\n");
+#endif
+
+ if(H5VL_REQUEST_WAITANY == specific_type ||
+ H5VL_REQUEST_WAITSOME == specific_type ||
+ H5VL_REQUEST_WAITALL == specific_type) {
+ va_list tmp_arguments;
+ size_t req_count;
+
+ /* Sanity check */
+ assert(obj == NULL);
+
+ /* Get enough info to call the underlying connector */
+ va_copy(tmp_arguments, arguments);
+ req_count = va_arg(tmp_arguments, size_t);
+
+ /* Can only use a request to invoke the underlying VOL connector when there's >0 requests */
+ if(req_count > 0) {
+ void **req_array;
+ void **under_req_array;
+ uint64_t timeout;
+ H5VL_pass_through_t *o;
+ size_t u; /* Local index variable */
+
+ /* Get the request array */
+ req_array = va_arg(tmp_arguments, void **);
+
+ /* Get a request to use for determining the underlying VOL connector */
+ o = (H5VL_pass_through_t *)req_array[0];
+
+ /* Create array of underlying VOL requests */
+ under_req_array = (void **)malloc(req_count * sizeof(void **));
+ for(u = 0; u < req_count; u++)
+ under_req_array[u] = ((H5VL_pass_through_t *)req_array[u])->under_object;
+
+ /* Remove the timeout value from the vararg list (it's used in all the calls below) */
+ timeout = va_arg(tmp_arguments, uint64_t);
+
+ /* Release requests that have completed */
+ if(H5VL_REQUEST_WAITANY == specific_type) {
+ size_t *index; /* Pointer to the index of completed request */
+ H5ES_status_t *status; /* Pointer to the request's status */
+
+ /* Retrieve the remaining arguments */
+ index = va_arg(tmp_arguments, size_t *);
+ assert(*index <= req_count);
+ status = va_arg(tmp_arguments, H5ES_status_t *);
+
+ /* Reissue the WAITANY 'request specific' call */
+ ret_value = H5VL_pass_through_request_specific_reissue(o->under_object, o->under_vol_id, specific_type, req_count, under_req_array, timeout, index, status);
+
+ /* Release the completed request, if it completed */
+ if(ret_value >= 0 && *status != H5ES_STATUS_IN_PROGRESS) {
+ H5VL_pass_through_t *tmp_o;
+
+ tmp_o = (H5VL_pass_through_t *)req_array[*index];
+ H5VL_pass_through_free_obj(tmp_o);
+ } /* end if */
+ } /* end if */
+ else if(H5VL_REQUEST_WAITSOME == specific_type) {
+ size_t *outcount; /* # of completed requests */
+ unsigned *array_of_indices; /* Array of indices for completed requests */
+ H5ES_status_t *array_of_statuses; /* Array of statuses for completed requests */
+
+ /* Retrieve the remaining arguments */
+ outcount = va_arg(tmp_arguments, size_t *);
+ assert(*outcount <= req_count);
+ array_of_indices = va_arg(tmp_arguments, unsigned *);
+ array_of_statuses = va_arg(tmp_arguments, H5ES_status_t *);
+
+ /* Reissue the WAITSOME 'request specific' call */
+ ret_value = H5VL_pass_through_request_specific_reissue(o->under_object, o->under_vol_id, specific_type, req_count, under_req_array, timeout, outcount, array_of_indices, array_of_statuses);
+
+ /* If any requests completed, release them */
+ if(ret_value >= 0 && *outcount > 0) {
+ unsigned *idx_array; /* Array of indices of completed requests */
+
+ /* Retrieve the array of completed request indices */
+ idx_array = va_arg(tmp_arguments, unsigned *);
+
+ /* Release the completed requests */
+ for(u = 0; u < *outcount; u++) {
+ H5VL_pass_through_t *tmp_o;
+
+ tmp_o = (H5VL_pass_through_t *)req_array[idx_array[u]];
+ H5VL_pass_through_free_obj(tmp_o);
+ } /* end for */
+ } /* end if */
+ } /* end else-if */
+ else { /* H5VL_REQUEST_WAITALL == specific_type */
+ H5ES_status_t *array_of_statuses; /* Array of statuses for completed requests */
+
+ /* Retrieve the remaining arguments */
+ array_of_statuses = va_arg(tmp_arguments, H5ES_status_t *);
+
+ /* Reissue the WAITALL 'request specific' call */
+ ret_value = H5VL_pass_through_request_specific_reissue(o->under_object, o->under_vol_id, specific_type, req_count, under_req_array, timeout, array_of_statuses);
+
+ /* Release the completed requests */
+ if(ret_value >= 0) {
+ for(u = 0; u < req_count; u++) {
+ if(array_of_statuses[u] != H5ES_STATUS_IN_PROGRESS) {
+ H5VL_pass_through_t *tmp_o;
+
+ tmp_o = (H5VL_pass_through_t *)req_array[u];
+ H5VL_pass_through_free_obj(tmp_o);
+ } /* end if */
+ } /* end for */
+ } /* end if */
+ } /* end else */
+
+ /* Release array of requests for underlying connector */
+ free(under_req_array);
+ } /* end if */
+
+ /* Finish use of copied vararg list */
+ va_end(tmp_arguments);
+ } /* end if */
+ else
+ assert(0 && "Unknown 'specific' operation");
+
+ return ret_value;
+} /* end H5VL_pass_through_request_specific() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_request_optional
+ *
+ * Purpose: Perform a connector-specific operation for a request
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_request_optional(void *obj, va_list arguments)
+{
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL REQUEST Optional\n");
+#endif
+
+ ret_value = H5VLrequest_optional(o->under_object, o->under_vol_id, arguments);
+
+ return ret_value;
+} /* end H5VL_pass_through_request_optional() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_request_free
+ *
+ * Purpose: Releases a request, allowing the operation to complete without
+ * application tracking
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL_pass_through_request_free(void *obj)
+{
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL REQUEST Free\n");
+#endif
+
+ ret_value = H5VLrequest_free(o->under_object, o->under_vol_id);
+
+ if(ret_value >= 0)
+ H5VL_pass_through_free_obj(o);
+
+ return ret_value;
+} /* end H5VL_pass_through_request_free() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_blob_put
+ *
+ * Purpose: Handles the blob 'put' callback
+ *
+ * Return: SUCCEED / FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_pass_through_blob_put(void *obj, const void *buf, size_t size,
+ void *blob_id, void *ctx)
+{
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL BLOB Put\n");
+#endif
+
+ ret_value = H5VLblob_put(o->under_object, o->under_vol_id, buf, size,
+ blob_id, ctx);
+
+ return ret_value;
+} /* end H5VL_pass_through_blob_put() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_blob_get
+ *
+ * Purpose: Handles the blob 'get' callback
+ *
+ * Return: SUCCEED / FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_pass_through_blob_get(void *obj, const void *blob_id, void *buf,
+ size_t *size, void *ctx)
+{
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL BLOB Get\n");
+#endif
+
+ ret_value = H5VLblob_get(o->under_object, o->under_vol_id, blob_id, buf,
+ size, ctx);
+
+ return ret_value;
+} /* end H5VL_pass_through_blob_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_pass_through_blob_specific
+ *
+ * Purpose: Handles the blob 'specific' callback
+ *
+ * Return: SUCCEED / FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_pass_through_blob_specific(void *obj, void *blob_id,
+ H5VL_blob_specific_t specific_type, va_list arguments)
+{
+ H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj;
+ herr_t ret_value;
+
+#ifdef ENABLE_PASSTHRU_LOGGING
+ printf("------- PASS THROUGH VOL BLOB Specific\n");
+#endif
+
+ ret_value = H5VLblob_specific(o->under_object, o->under_vol_id, blob_id,
+ specific_type, arguments);
+
+ return ret_value;
+} /* end H5VL_pass_through_blob_specific() */
diff --git a/src/H5B2public.h b/src/H5VLpassthru.h
index 6e0b964..d145bcd 100644
--- a/src/H5B2public.h
+++ b/src/H5VLpassthru.h
@@ -1,6 +1,5 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* 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 *
@@ -11,42 +10,40 @@
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-/*-------------------------------------------------------------------------
- *
- * Created: H5B2public.h
- * Jan 31 2005
- * Quincey Koziol <koziol@ncsa.uiuc.edu>
- *
- * Purpose: Public declarations for the v2 B-tree package.
- *
- *-------------------------------------------------------------------------
+/*
+ * Purpose: The public header file for the pass-through VOL connector.
*/
-#ifndef _H5B2public_H
-#define _H5B2public_H
+#ifndef _H5VLpassthru_H
+#define _H5VLpassthru_H
/* Public headers needed by this file */
-#include "H5public.h"
+#include "H5VLpublic.h" /* Virtual Object Layer */
-/*****************/
-/* Public Macros */
-/*****************/
+/* Identifier for the pass-through VOL connector */
+#define H5VL_PASSTHRU (H5VL_pass_through_register())
-/*******************/
-/* Public Typedefs */
-/*******************/
+/* Characteristics of the pass-through VOL connector */
+#define H5VL_PASSTHRU_NAME "pass_through"
+#define H5VL_PASSTHRU_VALUE 505 /* VOL connector ID */
+#define H5VL_PASSTHRU_VERSION 0
+
+/* Pass-through VOL connector info */
+typedef struct H5VL_pass_through_info_t {
+ hid_t under_vol_id; /* VOL ID for under VOL */
+ void *under_vol_info; /* VOL info for under VOL */
+} H5VL_pass_through_info_t;
-/**********************************/
-/* Public API Function Prototypes */
-/**********************************/
#ifdef __cplusplus
extern "C" {
#endif
+H5_DLL hid_t H5VL_pass_through_register(void);
+
#ifdef __cplusplus
}
#endif
-#endif /* _H5B2public_H */
+#endif /* _H5VLpassthru_H */
diff --git a/src/H5VLpkg.h b/src/H5VLpkg.h
new file mode 100644
index 0000000..69e51c2
--- /dev/null
+++ b/src/H5VLpkg.h
@@ -0,0 +1,63 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Purpose: This file contains declarations which are visible only within
+ * the H5VL package. Source files outside the H5VL package should
+ * include H5VLprivate.h instead.
+ */
+
+#if !(defined H5VL_FRIEND || defined H5VL_MODULE)
+#error "Do not include this file outside the H5VL package!"
+#endif
+
+#ifndef _H5VLpkg_H
+#define _H5VLpkg_H
+
+/* Get package's private header */
+#include "H5VLprivate.h" /* Generic Functions */
+
+/* Other private headers needed by this file */
+
+
+/**************************/
+/* Package Private Macros */
+/**************************/
+
+
+/****************************/
+/* Package Private Typedefs */
+/****************************/
+
+
+/*****************************/
+/* Package Private Variables */
+/*****************************/
+
+
+/******************************/
+/* Package Private Prototypes */
+/******************************/
+H5_DLL hid_t H5VL__register_connector(const H5VL_class_t *cls, hbool_t app_ref,
+ hid_t vipl_id);
+H5_DLL hid_t H5VL__register_connector_by_name(const char *name, hbool_t app_ref,
+ hid_t vipl_id);
+H5_DLL hid_t H5VL__register_connector_by_value(H5VL_class_value_t value,
+ hbool_t app_ref, hid_t vipl_id);
+H5_DLL htri_t H5VL__is_connector_registered(const char *name);
+H5_DLL hid_t H5VL__get_connector_id(const char *name, hbool_t is_api);
+H5_DLL herr_t H5VL__connector_str_to_info(const char *str, hid_t connector_id,
+ void **info);
+H5_DLL ssize_t H5VL__get_connector_name(hid_t id, char *name/*out*/, size_t size);
+
+#endif /* _H5VLpkg_H */
+
diff --git a/src/H5VLprivate.h b/src/H5VLprivate.h
new file mode 100644
index 0000000..2889524
--- /dev/null
+++ b/src/H5VLprivate.h
@@ -0,0 +1,205 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#ifndef _H5VLprivate_H
+#define _H5VLprivate_H
+
+/* Include package's public header */
+#include "H5VLpublic.h" /* Generic Functions */
+
+/* Private headers needed by this file */
+
+
+/**************************/
+/* Library Private Macros */
+/**************************/
+
+
+/****************************/
+/* Library Private Typedefs */
+/****************************/
+
+/* Internal struct to track VOL connector information for objects */
+typedef struct H5VL_t {
+ const H5VL_class_t *cls; /* Pointer to connector class struct */
+ int64_t nrefs; /* Number of references by objects using this struct */
+ hid_t id; /* Identifier for the VOL connector */
+} H5VL_t;
+
+/* Internal vol object structure returned to the API */
+typedef struct H5VL_object_t {
+ void *data; /* Pointer to connector-managed data for this object */
+ H5VL_t *connector; /* Pointer to VOL connector struct */
+} H5VL_object_t;
+
+/* Internal structure to hold the connector ID & info for FAPLs */
+typedef struct H5VL_connector_prop_t {
+ hid_t connector_id; /* VOL connector's ID */
+ void *connector_info; /* VOL connector info, for open callbacks */
+} H5VL_connector_prop_t;
+
+/* Which kind of VOL connector field to use for searching */
+typedef enum H5VL_get_connector_kind_t {
+ H5VL_GET_CONNECTOR_BY_NAME, /* Name field is set */
+ H5VL_GET_CONNECTOR_BY_VALUE /* Value field is set */
+} H5VL_get_connector_kind_t;
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/******************************/
+/* Library Private Prototypes */
+/******************************/
+
+/* Utility functions */
+H5_DLL herr_t H5VL_init_phase1(void);
+H5_DLL herr_t H5VL_init_phase2(void);
+H5_DLL herr_t H5VL_cmp_connector_cls(int *cmp_value, const H5VL_class_t *cls1, const H5VL_class_t *cls2);
+H5_DLL herr_t H5VL_conn_copy(H5VL_connector_prop_t *value);
+H5_DLL herr_t H5VL_conn_free(const H5VL_connector_prop_t *info);
+
+/* Functions that deal with VOL connectors */
+H5_DLL hid_t H5VL_register_connector(const void *cls, hbool_t app_ref, hid_t vipl_id);
+
+/* NOTE: The object and ID functions below deal in VOL objects (i.e.;
+ * H5VL_object_t). Similar non-VOL calls exist in H5Iprivate.h. Use
+ * the H5VL calls with objects that go through the VOL, such as
+ * datasets and groups, and the H5I calls with objects
+ * that do not, such as property lists and dataspaces. Datatypes
+ * are can be either named, where they will use the VOL, or not,
+ * and thus require special treatment. See the datatype docs for
+ * how to handle this.
+ */
+
+/* Functions that manipulate VOL objects */
+H5_DLL void *H5VL_object(hid_t id);
+H5_DLL void *H5VL_object_data(const H5VL_object_t *vol_obj);
+H5_DLL void *H5VL_object_unwrap(const H5VL_object_t *vol_obj);
+H5_DLL void *H5VL_object_verify(hid_t id, H5I_type_t obj_type);
+H5_DLL H5VL_object_t *H5VL_vol_object(hid_t id);
+H5_DLL herr_t H5VL_free_object(H5VL_object_t *obj);
+
+/* Functions that wrap / unwrap VOL objects */
+H5_DLL herr_t H5VL_get_wrap_ctx(const H5VL_class_t *connector, void *obj,
+ void **wrap_ctx);
+H5_DLL void * H5VL_wrap_object(const H5VL_class_t *connector, void *wrap_ctx,
+ void *obj, H5I_type_t obj_type);
+H5_DLL void * H5VL_unwrap_object(const H5VL_class_t *connector, void *obj);
+H5_DLL herr_t H5VL_free_wrap_ctx(const H5VL_class_t *connector, void *wrap_ctx);
+H5_DLL herr_t H5VL_set_vol_wrapper(void *obj, H5VL_t *vol_connector);
+H5_DLL herr_t H5VL_inc_vol_wrapper(void *vol_wrap_ctx);
+H5_DLL herr_t H5VL_dec_vol_wrapper(void *vol_wrap_ctx);
+H5_DLL herr_t H5VL_reset_vol_wrapper(void);
+
+/* Library state functions */
+H5_DLL herr_t H5VL_retrieve_lib_state(void **state);
+H5_DLL herr_t H5VL_restore_lib_state(const void *state);
+H5_DLL herr_t H5VL_reset_lib_state(void);
+H5_DLL herr_t H5VL_free_lib_state(void *state);
+
+/* ID registration functions */
+H5_DLL hid_t H5VL_register(H5I_type_t type, void *object, H5VL_t *vol_connector, hbool_t app_ref);
+H5_DLL hid_t H5VL_wrap_register(H5I_type_t type, void *obj, hbool_t app_ref);
+H5_DLL hid_t H5VL_register_using_vol_id(H5I_type_t type, void *obj, hid_t connector_id, hbool_t app_ref);
+H5_DLL herr_t H5VL_register_using_existing_id(H5I_type_t type, void *object, H5VL_t *vol_connector, hbool_t app_ref, hid_t existing_id);
+
+/**********************************
+ * VOL connector callback wrappers
+ *********************************/
+
+/* Connector "management" functions */
+H5_DLL int H5VL_copy_connector_info(const H5VL_class_t *connector, void **dst_info,
+ const void *src_info);
+H5_DLL herr_t H5VL_cmp_connector_info(const H5VL_class_t *connector, int *cmp_value,
+ const void *info1, const void *info2);
+H5_DLL herr_t H5VL_free_connector_info(hid_t connector_id, void *info);
+
+/* Attribute functions */
+H5_DLL void *H5VL_attr_create(const H5VL_object_t *vol_obj, const H5VL_loc_params_t *loc_params, const char *attr_name, hid_t type_id, hid_t space_id, hid_t acpl_id, hid_t aapl_id, hid_t dxpl_id, void **req);
+H5_DLL void *H5VL_attr_open(const H5VL_object_t *vol_obj, const H5VL_loc_params_t *loc_params, const char *name, hid_t aapl_id, hid_t dxpl_id, void **req);
+H5_DLL herr_t H5VL_attr_read(const H5VL_object_t *vol_obj, hid_t dtype_id, void *buf, hid_t dxpl_id, void **req);
+H5_DLL herr_t H5VL_attr_write(const H5VL_object_t *vol_obj, hid_t dtype_id, const void *buf, hid_t dxpl_id, void **req);
+H5_DLL herr_t H5VL_attr_get(const H5VL_object_t *vol_obj, H5VL_attr_get_t get_type, hid_t dxpl_id, void **req, ...);
+H5_DLL herr_t H5VL_attr_specific(const H5VL_object_t *vol_obj, const H5VL_loc_params_t *loc_params, H5VL_attr_specific_t specific_type, hid_t dxpl_id, void **req, ...);
+H5_DLL herr_t H5VL_attr_optional(const H5VL_object_t *vol_obj, hid_t dxpl_id, void **req, ...);
+H5_DLL herr_t H5VL_attr_close(const H5VL_object_t *vol_obj, hid_t dxpl_id, void **req);
+
+/* Dataset functions */
+H5_DLL void *H5VL_dataset_create(const H5VL_object_t *vol_obj, const H5VL_loc_params_t *loc_params, const char *name, hid_t lcpl_id, hid_t type_id, hid_t space_id, 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 plist_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 plist_id, const void *buf, void **req);
+H5_DLL herr_t H5VL_dataset_get(const H5VL_object_t *vol_obj, H5VL_dataset_get_t get_type, hid_t dxpl_id, void **req, ...);
+H5_DLL herr_t H5VL_dataset_specific(const H5VL_object_t *cls, H5VL_dataset_specific_t specific_type, hid_t dxpl_id, void **req, ...);
+H5_DLL herr_t H5VL_dataset_optional(const H5VL_object_t *vol_obj, hid_t dxpl_id, void **req, ...);
+H5_DLL herr_t H5VL_dataset_close(const H5VL_object_t *vol_obj, hid_t dxpl_id, void **req);
+
+/* File functions */
+H5_DLL void *H5VL_file_create(const H5VL_connector_prop_t *connector_prop, const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t dxpl_id, void **req);
+H5_DLL void *H5VL_file_open(const H5VL_connector_prop_t *connector_prop, const char *name, unsigned flags, hid_t fapl_id, hid_t dxpl_id, void **req);
+H5_DLL herr_t H5VL_file_get(const H5VL_object_t *vol_obj, H5VL_file_get_t get_type, hid_t dxpl_id, void **req, ...);
+H5_DLL herr_t H5VL_file_specific(const H5VL_object_t *vol_obj, H5VL_file_specific_t specific_type, hid_t dxpl_id, void **req, ...);
+H5_DLL herr_t H5VL_file_optional(const H5VL_object_t *vol_obj, hid_t dxpl_id, void **req, ...);
+H5_DLL herr_t H5VL_file_close(const H5VL_object_t *vol_obj, hid_t dxpl_id, void **req);
+
+/* Group functions */
+H5_DLL void *H5VL_group_create(const H5VL_object_t *vol_obj, const H5VL_loc_params_t *loc_params, const char *name, hid_t lcpl_id, hid_t gcpl_id, hid_t gapl_id, hid_t dxpl_id, void **req);
+H5_DLL void *H5VL_group_open(const H5VL_object_t *vol_obj, const H5VL_loc_params_t *loc_params, const char *name, hid_t gapl_id, hid_t dxpl_id, void **req);
+H5_DLL herr_t H5VL_group_get(const H5VL_object_t *vol_obj, H5VL_group_get_t get_type, hid_t dxpl_id, void **req, ...);
+H5_DLL herr_t H5VL_group_specific(const H5VL_object_t *vol_obj, H5VL_group_specific_t specific_type, hid_t dxpl_id, void **req, ...);
+H5_DLL herr_t H5VL_group_optional(const H5VL_object_t *vol_obj, hid_t dxpl_id, void **req, ...);
+H5_DLL herr_t H5VL_group_close(const H5VL_object_t *vol_obj, hid_t dxpl_id, void **req);
+
+/* Link functions */
+H5_DLL herr_t H5VL_link_create(H5VL_link_create_type_t create_type, const H5VL_object_t *vol_obj, const H5VL_loc_params_t *loc_params, hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id, void **req, ...);
+H5_DLL herr_t H5VL_link_copy(const H5VL_object_t *src_vol_obj, const H5VL_loc_params_t *loc_params1, const H5VL_object_t *dst_vol_obj, const H5VL_loc_params_t *loc_params2, hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id, void **req);
+H5_DLL herr_t H5VL_link_move(const H5VL_object_t *src_vol_obj, const H5VL_loc_params_t *loc_params1, const H5VL_object_t *dst_vol_obj, const H5VL_loc_params_t *loc_params2, hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id, void **req);
+H5_DLL herr_t H5VL_link_get(const H5VL_object_t *vol_obj, const H5VL_loc_params_t *loc_params, H5VL_link_get_t get_type, hid_t dxpl_id, void **req, ...);
+H5_DLL herr_t H5VL_link_specific(const H5VL_object_t *vol_obj, const H5VL_loc_params_t *loc_params, H5VL_link_specific_t specific_type, hid_t dxpl_id, void **req, ...);
+H5_DLL herr_t H5VL_link_optional(const H5VL_object_t *vol_obj, hid_t dxpl_id, void **req, ...);
+
+/* Object functions */
+H5_DLL void *H5VL_object_open(const H5VL_object_t *vol_obj, const H5VL_loc_params_t *params, H5I_type_t *opened_type, hid_t dxpl_id, void **req);
+H5_DLL herr_t H5VL_object_copy(const H5VL_object_t *src_obj, const H5VL_loc_params_t *src_loc_params, const char *src_name, const H5VL_object_t *dst_obj, const H5VL_loc_params_t *dst_loc_params, const char *dst_name, hid_t ocpypl_id, hid_t lcpl_id, hid_t dxpl_id, void **req);
+H5_DLL herr_t H5VL_object_get(const H5VL_object_t *vol_obj, const H5VL_loc_params_t *loc_params, H5VL_object_get_t get_type, hid_t dxpl_id, void **req, ...);
+H5_DLL herr_t H5VL_object_specific(const H5VL_object_t *vol_obj, const H5VL_loc_params_t *loc_params, H5VL_object_specific_t specific_type, hid_t dxpl_id, void **req, ...);
+H5_DLL herr_t H5VL_object_optional(const H5VL_object_t *vol_obj, hid_t dxpl_id, void **req, ...);
+
+/* Datatype functions */
+H5_DLL void *H5VL_datatype_commit(const H5VL_object_t *vol_obj, const H5VL_loc_params_t *loc_params, const char *name, hid_t type_id, hid_t lcpl_id, hid_t tcpl_id, hid_t tapl_id, hid_t dxpl_id, void **req);
+H5_DLL void *H5VL_datatype_open(const H5VL_object_t *vol_obj, const H5VL_loc_params_t *loc_params, const char *name, hid_t tapl_id, hid_t dxpl_id, void **req);
+H5_DLL herr_t H5VL_datatype_get(const H5VL_object_t *vol_obj, H5VL_datatype_get_t get_type, hid_t dxpl_id, void **req, ...);
+H5_DLL herr_t H5VL_datatype_specific(const H5VL_object_t *vol_obj, H5VL_datatype_specific_t specific_type, hid_t dxpl_id, void **req, ...);
+H5_DLL herr_t H5VL_datatype_optional(const H5VL_object_t *vol_obj, hid_t dxpl_id, void **req, ...);
+H5_DLL herr_t H5VL_datatype_close(const H5VL_object_t *vol_obj, hid_t dxpl_id, void **req);
+
+/* Asynchronous functions */
+H5_DLL herr_t H5VL_request_wait(const H5VL_object_t *vol_obj, uint64_t timeout, H5ES_status_t *status);
+H5_DLL herr_t H5VL_request_notify(const H5VL_object_t *vol_obj, H5VL_request_notify_t cb, void *ctx);
+H5_DLL herr_t H5VL_request_cancel(const H5VL_object_t *vol_obj);
+H5_DLL herr_t H5VL_request_specific(const H5VL_object_t *vol_obj, H5VL_request_specific_t specific_type, ...);
+H5_DLL herr_t H5VL_request_optional(const H5VL_object_t *vol_obj, ...);
+H5_DLL herr_t H5VL_request_free(const H5VL_object_t *vol_obj);
+
+/* Blob functions */
+H5_DLL herr_t H5VL_blob_put(const H5VL_object_t *vol_obj, const void *buf, size_t size, void *blob_id, void *ctx);
+H5_DLL herr_t H5VL_blob_get(const H5VL_object_t *vol_obj, const void *blob_id, void *buf, size_t *size, void *ctx);
+H5_DLL herr_t H5VL_blob_specific(const H5VL_object_t *vol_obj, void *blob_id, H5VL_blob_specific_t specific_type, ...);
+
+/* Generic functions */
+H5_DLL herr_t H5VL_optional(const H5VL_object_t *vol_obj, hid_t dxpl_id,void **req, ...);
+
+#endif /* _H5VLprivate_H */
+
diff --git a/src/H5VLpublic.h b/src/H5VLpublic.h
new file mode 100644
index 0000000..12448b6
--- /dev/null
+++ b/src/H5VLpublic.h
@@ -0,0 +1,77 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * This file contains public declarations for the H5VL (VOL) module.
+ */
+
+#ifndef _H5VLpublic_H
+#define _H5VLpublic_H
+
+/* Public headers needed by this file */
+#include "H5public.h" /* Generic Functions */
+#include "H5Ipublic.h" /* IDs */
+
+/* Semi-public headers mainly for VOL connector authors */
+#include "H5VLconnector.h"
+#include "H5VLconnector_passthru.h"
+
+
+/*****************/
+/* Public Macros */
+/*****************/
+
+/* VOL connector identifier values
+ * These are H5VL_class_value_t values, NOT hid_t values!
+ */
+#define H5_VOL_INVALID (-1) /* Invalid ID for VOL connector iD */
+#define H5_VOL_NATIVE 0 /* Native HDF5 file format VOL connector */
+#define H5_VOL_RESERVED 256 /* VOL connector IDs below this value are reserved for library use */
+#define H5_VOL_MAX 65535 /* Maximum VOL connector ID */
+
+
+/*******************/
+/* Public Typedefs */
+/*******************/
+
+/********************/
+/* Public Variables */
+/********************/
+
+/*********************/
+/* Public Prototypes */
+/*********************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* The H5VL types uses in the API calls are not opaque - they are defined in
+ * H5VLconnector.h, which is included at the top of this file.
+ */
+
+H5_DLL hid_t H5VLregister_connector(const H5VL_class_t *cls, hid_t vipl_id);
+H5_DLL hid_t H5VLregister_connector_by_name(const char *connector_name, hid_t vipl_id);
+H5_DLL hid_t H5VLregister_connector_by_value(H5VL_class_value_t connector_value, hid_t vipl_id);
+H5_DLL htri_t H5VLis_connector_registered(const char *name);
+H5_DLL hid_t H5VLget_connector_id(const char *name);
+H5_DLL ssize_t H5VLget_connector_name(hid_t id, char *name/*out*/, size_t size);
+H5_DLL herr_t H5VLclose(hid_t connector_id);
+H5_DLL herr_t H5VLunregister_connector(hid_t connector_id);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _H5VLpublic_H */
+
diff --git a/src/H5VM.c b/src/H5VM.c
index 4c0b837..f78da96 100644
--- a/src/H5VM.c
+++ b/src/H5VM.c
@@ -19,6 +19,7 @@
#include "H5private.h"
#include "H5Eprivate.h"
+#include "H5MMprivate.h" /* Memory management */
#include "H5Oprivate.h"
#include "H5VMprivate.h"
@@ -732,7 +733,7 @@ H5VM_stride_copy(unsigned n, hsize_t elmt_size, const hsize_t *size,
/* Copy an element */
H5_CHECK_OVERFLOW(elmt_size,hsize_t,size_t);
- HDmemcpy(dst, src, (size_t)elmt_size); /*lint !e671 The elmt_size will be OK */
+ H5MM_memcpy(dst, src, (size_t)elmt_size); /*lint !e671 The elmt_size will be OK */
/* Decrement indices and advance pointers */
for (j=(int)(n-1), carry=TRUE; j>=0 && carry; --j) {
@@ -749,7 +750,7 @@ H5VM_stride_copy(unsigned n, hsize_t elmt_size, const hsize_t *size,
}
} else {
H5_CHECK_OVERFLOW(elmt_size,hsize_t,size_t);
- HDmemcpy (dst, src, (size_t)elmt_size); /*lint !e671 The elmt_size will be OK */
+ H5MM_memcpy (dst, src, (size_t)elmt_size); /*lint !e671 The elmt_size will be OK */
}
FUNC_LEAVE_NOAPI(SUCCEED)
@@ -801,7 +802,7 @@ H5VM_stride_copy_s(unsigned n, hsize_t elmt_size, const hsize_t *size,
/* Copy an element */
H5_CHECK_OVERFLOW(elmt_size,hsize_t,size_t);
- HDmemcpy(dst, src, (size_t)elmt_size); /*lint !e671 The elmt_size will be OK */
+ H5MM_memcpy(dst, src, (size_t)elmt_size); /*lint !e671 The elmt_size will be OK */
/* Decrement indices and advance pointers */
for (j=(int)(n-1), carry=TRUE; j>=0 && carry; --j) {
@@ -818,7 +819,7 @@ H5VM_stride_copy_s(unsigned n, hsize_t elmt_size, const hsize_t *size,
}
} else {
H5_CHECK_OVERFLOW(elmt_size,hsize_t,size_t);
- HDmemcpy (dst, src, (size_t)elmt_size); /*lint !e671 The elmt_size will be OK */
+ H5MM_memcpy (dst, src, (size_t)elmt_size); /*lint !e671 The elmt_size will be OK */
}
FUNC_LEAVE_NOAPI(SUCCEED)
@@ -877,7 +878,7 @@ H5VM_stride_copy2(hsize_t nelmts, hsize_t elmt_size,
/* Copy an element */
H5_CHECK_OVERFLOW(elmt_size,hsize_t,size_t);
- HDmemcpy(dst, src, (size_t)elmt_size); /*lint !e671 The elmt_size will be OK */
+ H5MM_memcpy(dst, src, (size_t)elmt_size); /*lint !e671 The elmt_size will be OK */
/* Decrement indices and advance pointers */
for (j=(int)(dst_n-1), carry=TRUE; j>=0 && carry; --j) {
@@ -936,7 +937,7 @@ H5VM_array_fill(void *_dst, const void *src, size_t size, size_t count)
HDassert(size < SIZET_MAX && size > 0);
HDassert(count < SIZET_MAX && count > 0);
- HDmemcpy(dst, src, size); /* copy first item */
+ H5MM_memcpy(dst, src, size); /* copy first item */
/* Initialize counters, etc. while compensating for first element copied */
copy_size = size;
@@ -947,7 +948,7 @@ H5VM_array_fill(void *_dst, const void *src, size_t size, size_t count)
/* copy until we've copied at least half of the items */
while (items_left >= copy_items)
{
- HDmemcpy(dst, _dst, copy_size); /* copy the current chunk */
+ H5MM_memcpy(dst, _dst, copy_size); /* copy the current chunk */
dst += copy_size; /* move the offset for the next chunk */
items_left -= copy_items; /* decrement the number of items left */
@@ -955,7 +956,7 @@ H5VM_array_fill(void *_dst, const void *src, size_t size, size_t count)
copy_items *= 2; /* increase the count of items we are copying */
} /* end while */
if (items_left > 0) /* if there are any items left to copy */
- HDmemcpy(dst, _dst, items_left * size);
+ H5MM_memcpy(dst, _dst, items_left * size);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* H5VM_array_fill() */
@@ -1548,7 +1549,7 @@ done:
*
* Purpose: Given source and destination buffers in memory (SRC & DST)
* copy sequences of from the source buffer into the destination
- * buffer. Each set of sequnces has an array of lengths, an
+ * buffer. Each set of sequences has an array of lengths, an
* array of offsets, the maximum number of sequences and the
* current sequence to start at in the sequence.
*
@@ -1623,7 +1624,7 @@ src_smaller:
acc_len = 0;
do {
/* Copy data */
- HDmemcpy(dst, src, tmp_src_len);
+ H5MM_memcpy(dst, src, tmp_src_len);
/* Accumulate number of bytes copied */
acc_len += tmp_src_len;
@@ -1666,7 +1667,7 @@ dst_smaller:
acc_len = 0;
do {
/* Copy data */
- HDmemcpy(dst, src, tmp_dst_len);
+ H5MM_memcpy(dst, src, tmp_dst_len);
/* Accumulate number of bytes copied */
acc_len += tmp_dst_len;
@@ -1709,7 +1710,7 @@ equal:
acc_len = 0;
do {
/* Copy data */
- HDmemcpy(dst, src, tmp_dst_len);
+ H5MM_memcpy(dst, src, tmp_dst_len);
/* Accumulate number of bytes copied */
acc_len += tmp_dst_len;
diff --git a/src/H5VMprivate.h b/src/H5VMprivate.h
index decac7e..26f59e2 100644
--- a/src/H5VMprivate.h
+++ b/src/H5VMprivate.h
@@ -21,6 +21,7 @@
/* Private headers needed by this file */
#include "H5private.h" /* Generic Functions */
#include "H5Eprivate.h" /* Error handling */
+#include "H5MMprivate.h" /* Memory management */
/* Vector-Vector sequence operation callback */
typedef herr_t (*H5VM_opvv_func_t)(hsize_t dst_off, hsize_t src_off,
@@ -41,7 +42,7 @@ typedef herr_t (*H5VM_opvv_func_t)(hsize_t dst_off, hsize_t src_off,
/* Other functions */
#define H5VM_vector_cpy(N,DST,SRC) { \
HDassert(sizeof(*(DST))==sizeof(*(SRC))); \
- if (SRC) HDmemcpy (DST, SRC, (N)*sizeof(*(DST))); \
+ if (SRC) H5MM_memcpy (DST, SRC, (N)*sizeof(*(DST))); \
else HDmemset (DST, 0, (N)*sizeof(*(DST))); \
}
diff --git a/src/H5Z.c b/src/H5Z.c
index 9dc358c..b703958 100644
--- a/src/H5Z.c
+++ b/src/H5Z.c
@@ -322,7 +322,7 @@ H5Z_register (const H5Z_class2_t *cls)
/* Initialize */
i = H5Z_table_used_g++;
- HDmemcpy(H5Z_table_g+i, cls, sizeof(H5Z_class2_t));
+ H5MM_memcpy(H5Z_table_g+i, cls, sizeof(H5Z_class2_t));
#ifdef H5Z_DEBUG
HDmemset(H5Z_stat_table_g+i, 0, sizeof(H5Z_stats_t));
#endif /* H5Z_DEBUG */
@@ -330,7 +330,7 @@ H5Z_register (const H5Z_class2_t *cls)
/* Filter already registered */
else {
/* Replace old contents */
- HDmemcpy(H5Z_table_g+i, cls, sizeof(H5Z_class2_t));
+ H5MM_memcpy(H5Z_table_g+i, cls, sizeof(H5Z_class2_t));
} /* end else */
done:
@@ -586,7 +586,9 @@ static int
H5Z__flush_file_cb(void *obj_ptr, hid_t H5_ATTR_UNUSED obj_id, void *key)
{
H5F_t *f = (H5F_t *)obj_ptr; /* File object for operations */
+#ifdef H5_HAVE_PARALLEL
H5Z_object_t *object = (H5Z_object_t *)key;
+#endif /* H5_HAVE_PARALLEL */
int ret_value = FALSE; /* Return value */
FUNC_ENTER_STATIC
@@ -609,7 +611,7 @@ H5Z__flush_file_cb(void *obj_ptr, hid_t H5_ATTR_UNUSED obj_id, void *key)
/* Sanity check for collectively calling H5Zunregister, if requested */
/* (Sanity check assumes that a barrier on one file's comm
* is sufficient (i.e. that there aren't different comms for
- * different files). -QAK, 2018/02/14
+ * different files). -QAK, 2018/02/14)
*/
if(H5_coll_api_sanity_check_g && !object->sanity_checked) {
MPI_Comm mpi_comm; /* File's communicator */
@@ -695,11 +697,11 @@ H5Z_filter_avail(H5Z_filter_t id)
HGOTO_DONE(TRUE)
key.id = (int)id;
- if (NULL != (filter_info = (const H5Z_class2_t *)H5PL_load(H5PL_TYPE_FILTER, key))) {
- if (H5Z_register(filter_info) < 0)
+ if(NULL != (filter_info = (const H5Z_class2_t *)H5PL_load(H5PL_TYPE_FILTER, &key))) {
+ if(H5Z_register(filter_info) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_CANTINIT, FAIL, "unable to register loaded filter")
HGOTO_DONE(TRUE)
- }
+ } /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -1287,7 +1289,7 @@ H5Z_pipeline(const H5O_pline_t *pline, unsigned flags,
/* Try loading the filter */
key.id = (int)(pline->filter[idx].id);
- if(NULL != (filter_info = (const H5Z_class2_t *)H5PL_load(H5PL_TYPE_FILTER, key))) {
+ if(NULL != (filter_info = (const H5Z_class2_t *)H5PL_load(H5PL_TYPE_FILTER, &key))) {
/* Register the filter we loaded */
if(H5Z_register(filter_info) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_CANTINIT, FAIL, "unable to register filter")
diff --git a/src/H5Zfletcher32.c b/src/H5Zfletcher32.c
index 4cd77ef..4d75d14 100644
--- a/src/H5Zfletcher32.c
+++ b/src/H5Zfletcher32.c
@@ -108,7 +108,7 @@ H5Z_filter_fletcher32 (unsigned flags, size_t H5_ATTR_UNUSED cd_nelmts, const un
* system. We'll check both the correct checksum and the wrong
* checksum to be consistent with Release 1.6.2 and before.
*/
- HDmemcpy(c, &fletcher, (size_t)4);
+ H5MM_memcpy(c, &fletcher, (size_t)4);
tmp = c[1];
c[1] = c[0];
@@ -118,7 +118,7 @@ H5Z_filter_fletcher32 (unsigned flags, size_t H5_ATTR_UNUSED cd_nelmts, const un
c[3] = c[2];
c[2] = tmp;
- HDmemcpy(&reversed_fletcher, c, (size_t)4);
+ H5MM_memcpy(&reversed_fletcher, c, (size_t)4);
/* Verify computed checksum matches stored checksum */
if(stored_fletcher != fletcher && stored_fletcher != reversed_fletcher)
@@ -140,7 +140,7 @@ H5Z_filter_fletcher32 (unsigned flags, size_t H5_ATTR_UNUSED cd_nelmts, const un
dst = (unsigned char *) outbuf;
/* Copy raw data */
- HDmemcpy((void*)dst, (void*)(*buf), nbytes);
+ H5MM_memcpy((void*)dst, (void*)(*buf), nbytes);
/* Append checksum to raw data for storage */
dst += nbytes;
diff --git a/src/H5Zpublic.h b/src/H5Zpublic.h
index 0df05f0..a2a44fa 100644
--- a/src/H5Zpublic.h
+++ b/src/H5Zpublic.h
@@ -25,7 +25,7 @@
* Filter identifiers. Values 0 through 255 are for filters defined by the
* HDF5 library. Values 256 through 511 are available for testing new
* filters. Subsequent values should be obtained from the HDF5 development
- * team at hdf5dev@ncsa.uiuc.edu. These values will never change because they
+ * team at help@hdfgroup.org. These values will never change because they
* appear in the HDF5 files.
*/
typedef int H5Z_filter_t;
diff --git a/src/H5Zscaleoffset.c b/src/H5Zscaleoffset.c
index cdf31a4..7bdc283 100644
--- a/src/H5Zscaleoffset.c
+++ b/src/H5Zscaleoffset.c
@@ -141,7 +141,7 @@ H5Z_class2_t H5Z_SCALEOFFSET[1] = {{
} /* end if */ \
\
/* Copy the value */ \
- HDmemcpy(&_cd_value, _fv_p, _copy_size); \
+ H5MM_memcpy(&_cd_value, _fv_p, _copy_size); \
(cd_values)[_i] = (unsigned)_cd_value; \
\
/* Next field */ \
@@ -158,7 +158,7 @@ H5Z_class2_t H5Z_SCALEOFFSET[1] = {{
_fv_p = ((char *)&(fill_val)) + sizeof(type) - MIN(4, _size_rem); \
while(_size_rem >= 4) { \
/* Copy the value */ \
- HDmemcpy(&_cd_value, _fv_p, _copy_size); \
+ H5MM_memcpy(&_cd_value, _fv_p, _copy_size); \
(cd_values)[_i] = (unsigned)_cd_value; \
\
/* Next field */ \
@@ -176,7 +176,7 @@ H5Z_class2_t H5Z_SCALEOFFSET[1] = {{
* _cd_value as it will not be fully overwritten and copy to the end \
* of _cd value as it is BE. */ \
_cd_value = (uint32_t)0; \
- HDmemcpy((char *)&_cd_value + 4 - _size_rem, _fv_p, _size_rem); \
+ H5MM_memcpy((char *)&_cd_value + 4 - _size_rem, _fv_p, _size_rem); \
(cd_values)[_i] = (unsigned)_cd_value; \
} /* end if */ \
} /* end else */ \
@@ -269,7 +269,7 @@ H5Z_class2_t H5Z_SCALEOFFSET[1] = {{
\
/* Copy the value */ \
_cd_value = (uint32_t)(cd_values)[_i]; \
- HDmemcpy(_fv_p, &_cd_value, _copy_size); \
+ H5MM_memcpy(_fv_p, &_cd_value, _copy_size); \
\
/* Next field */ \
_i++; \
@@ -286,7 +286,7 @@ H5Z_class2_t H5Z_SCALEOFFSET[1] = {{
while(_size_rem >= 4) { \
/* Copy the value */ \
_cd_value = (uint32_t)(cd_values)[_i]; \
- HDmemcpy(_fv_p, &_cd_value, _copy_size); \
+ H5MM_memcpy(_fv_p, &_cd_value, _copy_size); \
\
/* Next field */ \
_i++; \
@@ -303,7 +303,7 @@ H5Z_class2_t H5Z_SCALEOFFSET[1] = {{
* _cd_value as it will not be fully overwritten and copy to the end \
* of _cd value as it is BE. */ \
_cd_value = (uint32_t)(cd_values)[_i]; \
- HDmemcpy(_fv_p, (char *)&_cd_value + 4 - _size_rem, _size_rem); \
+ H5MM_memcpy(_fv_p, (char *)&_cd_value + 4 - _size_rem, _size_rem); \
} /* end if */ \
} /* end else */ \
}
@@ -482,23 +482,23 @@ H5Z_class2_t H5Z_SCALEOFFSET[1] = {{
if(sizeof(type) == sizeof(int)) \
for(i = 0; i < d_nelmts; i++) { \
if(abs_fun(buf[i] - filval) < pow_fun(10.0f, (type)-D_val)) \
- *(int *)&buf[i] = (int)(((unsigned int)1 << *minbits) - 1); \
+ *(int *)((void *)&buf[i]) = (int)(((unsigned int)1 << *minbits) - 1); \
else \
- *(int *)&buf[i] = (int)lround_fun(buf[i] * pow_fun(10.0f, (type)D_val) - min * pow_fun(10.0f, (type)D_val)); \
+ *(int *)((void *)&buf[i]) = (int)lround_fun(buf[i] * pow_fun(10.0f, (type)D_val) - min * pow_fun(10.0f, (type)D_val)); \
} \
else if(sizeof(type) == sizeof(long)) \
for(i = 0; i < d_nelmts; i++) { \
if(abs_fun(buf[i] - filval) < pow_fun(10.0f, (type)-D_val)) \
- *(long *)&buf[i] = (long)(((unsigned long)1 << *minbits) - 1); \
+ *(long *)((void *)&buf[i]) = (long)(((unsigned long)1 << *minbits) - 1); \
else \
- *(long *)&buf[i] = lround_fun(buf[i] * pow_fun(10.0f, (type)D_val) - min * pow_fun(10.0f, (type)D_val)); \
+ *(long *)((void *)&buf[i]) = lround_fun(buf[i] * pow_fun(10.0f, (type)D_val) - min * pow_fun(10.0f, (type)D_val)); \
} \
else if(sizeof(type) == sizeof(long long)) \
for(i = 0; i < d_nelmts; i++) { \
if(abs_fun(buf[i] - filval) < pow_fun(10.0f, (type)-D_val)) \
- *(long long *)&buf[i] = (long long)(((unsigned long long)1 << *minbits) - 1); \
+ *(long long *)((void *)&buf[i]) = (long long)(((unsigned long long)1 << *minbits) - 1); \
else \
- *(long long *)&buf[i] = llround_fun(buf[i] * pow_fun(10.0f, (type)D_val) - min * pow_fun(10.0f, (type)D_val)); \
+ *(long long *)((void *)&buf[i]) = llround_fun(buf[i] * pow_fun(10.0f, (type)D_val) - min * pow_fun(10.0f, (type)D_val)); \
} \
else \
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "cannot find matched integer dataype") \
@@ -509,13 +509,13 @@ H5Z_class2_t H5Z_SCALEOFFSET[1] = {{
{ \
if(sizeof(type) == sizeof(int)) \
for(i = 0; i < d_nelmts; i++) \
- *(int *)&buf[i] = (int)lround_fun(buf[i] * pow_fun(10.0f, (type)D_val) - min * pow_fun(10.0f, (type)D_val)); \
+ *(int *)((void *)&buf[i]) = (int)lround_fun(buf[i] * pow_fun(10.0f, (type)D_val) - min * pow_fun(10.0f, (type)D_val)); \
else if(sizeof(type) == sizeof(long)) \
for(i = 0; i < d_nelmts; i++) \
- *(long *)&buf[i] = lround_fun(buf[i] * pow_fun(10.0f, (type)D_val) - min * pow_fun(10.0f, (type)D_val)); \
+ *(long *)((void *)&buf[i]) = lround_fun(buf[i] * pow_fun(10.0f, (type)D_val) - min * pow_fun(10.0f, (type)D_val)); \
else if(sizeof(type) == sizeof(long long)) \
for(i = 0; i < d_nelmts; i++) \
- *(long long *)&buf[i] = llround_fun(buf[i] * pow_fun(10.0f, (type)D_val) - min * pow_fun(10.0f, (type)D_val)); \
+ *(long long *)((void *)&buf[i]) = llround_fun(buf[i] * pow_fun(10.0f, (type)D_val) - min * pow_fun(10.0f, (type)D_val)); \
else \
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "cannot find matched integer dataype") \
}
@@ -529,10 +529,10 @@ H5Z_class2_t H5Z_SCALEOFFSET[1] = {{
* account for offset in BE if sizes differ \
*/ \
if(H5T_native_order_g == H5T_ORDER_LE) \
- HDmemcpy(minval, &min, sizeof(type)); \
+ H5MM_memcpy(minval, &min, sizeof(type)); \
else { \
HDassert(H5T_native_order_g == H5T_ORDER_BE); \
- HDmemcpy(((char *)minval) + (sizeof(long long) - sizeof(type)), \
+ H5MM_memcpy(((char *)minval) + (sizeof(long long) - sizeof(type)), \
&min, sizeof(type)); \
} /* end else */ \
else \
@@ -604,10 +604,10 @@ H5Z_class2_t H5Z_SCALEOFFSET[1] = {{
* account for offset in BE if sizes differ \
*/ \
if(H5T_native_order_g == H5T_ORDER_LE) \
- HDmemcpy(&min, &minval, sizeof(type)); \
+ H5MM_memcpy(&min, &minval, sizeof(type)); \
else { \
HDassert(H5T_native_order_g == H5T_ORDER_BE); \
- HDmemcpy(&min, ((char *)&minval) + (sizeof(long long) \
+ H5MM_memcpy(&min, ((char *)&minval) + (sizeof(long long) \
- sizeof(type)), sizeof(type)); \
} /* end else */ \
else \
@@ -619,16 +619,16 @@ H5Z_class2_t H5Z_SCALEOFFSET[1] = {{
{ \
if(sizeof(type) == sizeof(int)) \
for(i = 0; i < d_nelmts; i++) \
- buf[i] = (type)((*(int *)&buf[i] == (int)(((unsigned int)1 << minbits) - 1)) ? \
- filval : (type)(*(int *)&buf[i]) / pow_fun(10.0f, (type)D_val) + min); \
+ buf[i] = (type)((*(int *)((void *)&buf[i]) == (int)(((unsigned int)1 << minbits) - 1)) ? \
+ filval : (type)(*(int *)((void *)&buf[i])) / pow_fun(10.0f, (type)D_val) + min); \
else if(sizeof(type) == sizeof(long)) \
for(i = 0; i < d_nelmts; i++) \
- buf[i] = (type)((*(long *)&buf[i] == (long)(((unsigned long)1 << minbits) - 1)) ? \
- filval : (type)(*(long *)&buf[i]) / pow_fun(10.0f, (type)D_val) + min); \
+ buf[i] = (type)((*(long *)((void *)&buf[i]) == (long)(((unsigned long)1 << minbits) - 1)) ? \
+ filval : (type)(*(long *)((void *)&buf[i])) / pow_fun(10.0f, (type)D_val) + min); \
else if(sizeof(type) == sizeof(long long)) \
for(i = 0; i < d_nelmts; i++) \
- buf[i] = (type)((*(long long *)&buf[i] == (long long)(((unsigned long long)1 << minbits) - 1)) ? \
- filval : (type)(*(long long *)&buf[i]) / pow_fun(10.0f, (type)D_val) + min); \
+ buf[i] = (type)((*(long long *)((void *)&buf[i]) == (long long)(((unsigned long long)1 << minbits) - 1)) ? \
+ filval : (type)(*(long long *)((void *)&buf[i])) / pow_fun(10.0f, (type)D_val) + min); \
else \
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "cannot find matched integer dataype") \
}
@@ -638,13 +638,13 @@ H5Z_class2_t H5Z_SCALEOFFSET[1] = {{
{ \
if(sizeof(type)==sizeof(int)) \
for(i = 0; i < d_nelmts; i++) \
- buf[i] = ((type)(*(int *)&buf[i]) / pow_fun(10.0f, (type)D_val) + min); \
+ buf[i] = ((type)(*(int *)((void *)&buf[i])) / pow_fun(10.0f, (type)D_val) + min); \
else if(sizeof(type)==sizeof(long)) \
for(i = 0; i < d_nelmts; i++) \
- buf[i] = ((type)(*(long *)&buf[i]) / pow_fun(10.0f, (type)D_val) + min); \
+ buf[i] = ((type)(*(long *)((void *)&buf[i])) / pow_fun(10.0f, (type)D_val) + min); \
else if(sizeof(type)==sizeof(long long)) \
for(i = 0; i < d_nelmts; i++) \
- buf[i] = ((type)(*(long long *)&buf[i]) / pow_fun(10.0f, (type)D_val) + min); \
+ buf[i] = ((type)(*(long long *)((void *)&buf[i])) / pow_fun(10.0f, (type)D_val) + min); \
else \
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "cannot find matched integer dataype") \
}
@@ -1173,7 +1173,9 @@ H5Z_filter_scaleoffset(unsigned flags, size_t cd_nelmts, const unsigned cd_value
/* special case: minbits equal to full precision */
if(minbits == p.size * 8) {
- HDmemcpy(outbuf, (unsigned char*)(*buf)+buf_offset, size_out);
+ H5MM_memcpy(outbuf, (unsigned char*)(*buf)+buf_offset, size_out);
+ /* free the original buffer */
+ H5MM_xfree(*buf);
/* convert to dataset datatype endianness order if needed */
if(need_convert)
@@ -1271,7 +1273,10 @@ H5Z_filter_scaleoffset(unsigned flags, size_t cd_nelmts, const unsigned cd_value
/* special case: minbits equal to full precision */
if(minbits == p.size * 8) {
- HDmemcpy(outbuf + buf_offset, *buf, nbytes);
+ H5MM_memcpy(outbuf + buf_offset, *buf, nbytes);
+ /* free the original buffer */
+ H5MM_xfree(*buf);
+
*buf = outbuf;
outbuf = NULL;
*buf_size = size_out;
diff --git a/src/H5Zshuffle.c b/src/H5Zshuffle.c
index 1fef1c1..b1d0722 100644
--- a/src/H5Zshuffle.c
+++ b/src/H5Zshuffle.c
@@ -185,18 +185,25 @@ H5Z_filter_shuffle(unsigned flags, size_t cd_nelmts, const unsigned cd_values[],
do
{
DUFF_GUTS
+ H5_ATTR_FALLTHROUGH
case 7:
DUFF_GUTS
+ H5_ATTR_FALLTHROUGH
case 6:
DUFF_GUTS
+ H5_ATTR_FALLTHROUGH
case 5:
DUFF_GUTS
+ H5_ATTR_FALLTHROUGH
case 4:
DUFF_GUTS
+ H5_ATTR_FALLTHROUGH
case 3:
DUFF_GUTS
+ H5_ATTR_FALLTHROUGH
case 2:
DUFF_GUTS
+ H5_ATTR_FALLTHROUGH
case 1:
DUFF_GUTS
} while (--duffs_index > 0);
@@ -210,7 +217,7 @@ H5Z_filter_shuffle(unsigned flags, size_t cd_nelmts, const unsigned cd_values[],
if(leftover>0) {
/* Adjust back to end of shuffled bytes */
_dest -= (bytesoftype - 1); /*lint !e794 _dest is initialized */
- HDmemcpy((void*)_dest, (void*)_src, leftover);
+ H5MM_memcpy((void*)_dest, (void*)_src, leftover);
}
} /* end if */
else {
@@ -243,18 +250,25 @@ H5Z_filter_shuffle(unsigned flags, size_t cd_nelmts, const unsigned cd_values[],
do
{
DUFF_GUTS
+ H5_ATTR_FALLTHROUGH
case 7:
DUFF_GUTS
+ H5_ATTR_FALLTHROUGH
case 6:
DUFF_GUTS
+ H5_ATTR_FALLTHROUGH
case 5:
DUFF_GUTS
+ H5_ATTR_FALLTHROUGH
case 4:
DUFF_GUTS
+ H5_ATTR_FALLTHROUGH
case 3:
DUFF_GUTS
+ H5_ATTR_FALLTHROUGH
case 2:
DUFF_GUTS
+ H5_ATTR_FALLTHROUGH
case 1:
DUFF_GUTS
} while (--duffs_index > 0);
@@ -268,7 +282,7 @@ H5Z_filter_shuffle(unsigned flags, size_t cd_nelmts, const unsigned cd_values[],
if(leftover>0) {
/* Adjust back to end of shuffled bytes */
_src -= (bytesoftype - 1); /*lint !e794 _src is initialized */
- HDmemcpy((void*)_dest, (void*)_src, leftover);
+ H5MM_memcpy((void*)_dest, (void*)_src, leftover);
}
} /* end else */
diff --git a/src/H5Ztrans.c b/src/H5Ztrans.c
index 67646a0..6d07513 100644
--- a/src/H5Ztrans.c
+++ b/src/H5Ztrans.c
@@ -850,7 +850,7 @@ H5Z_parse_factor(H5Z_token *current, H5Z_datval_ptrs* dat_val_pointers)
if (!factor)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "Unable to allocate new node")
- sscanf(current->tok_begin, "%ld", &factor->value.int_val);
+ HDsscanf(current->tok_begin, "%ld", &factor->value.int_val);
break;
case H5Z_XFORM_FLOAT:
@@ -858,7 +858,7 @@ H5Z_parse_factor(H5Z_token *current, H5Z_datval_ptrs* dat_val_pointers)
if (!factor)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "Unable to allocate new node")
- sscanf(current->tok_begin, "%lf", &factor->value.float_val);
+ HDsscanf(current->tok_begin, "%lf", &factor->value.float_val);
break;
case H5Z_XFORM_SYMBOL:
@@ -1078,7 +1078,7 @@ H5Z_xform_eval(H5Z_data_xform_t *data_xform_prop, void* array, size_t array_size
if(NULL == (data_xform_prop->dat_val_pointers->ptr_dat_val[i] = (void*)H5MM_malloc(array_size * H5T_get_size((H5T_t *)H5I_object(array_type)))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "Ran out of memory trying to allocate space for data in data transform")
- HDmemcpy(data_xform_prop->dat_val_pointers->ptr_dat_val[i], array, array_size * H5T_get_size((H5T_t *)H5I_object(array_type)));
+ H5MM_memcpy(data_xform_prop->dat_val_pointers->ptr_dat_val[i], array, array_size * H5T_get_size((H5T_t *)H5I_object(array_type)));
} /* end for */
} /* end else */
@@ -1086,7 +1086,7 @@ H5Z_xform_eval(H5Z_data_xform_t *data_xform_prop, void* array, size_t array_size
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "error while performing data transform")
if(data_xform_prop->dat_val_pointers->num_ptrs > 1)
- HDmemcpy(array, res.value.dat_val, array_size * H5T_get_size((H5T_t *)H5I_object(array_type)));
+ H5MM_memcpy(array, res.value.dat_val, array_size * H5T_get_size((H5T_t *)H5I_object(array_type)));
/* Free the temporary arrays we used */
if(data_xform_prop->dat_val_pointers->num_ptrs > 1)
diff --git a/src/H5checksum.c b/src/H5checksum.c
index 64d527e..4e98976 100644
--- a/src/H5checksum.c
+++ b/src/H5checksum.c
@@ -407,16 +407,27 @@ H5_checksum_lookup3(const void *key, size_t length, uint32_t initval)
switch(length) /* all the case statements fall through */
{
case 12: c+=((uint32_t)k[11])<<24;
+ H5_ATTR_FALLTHROUGH
case 11: c+=((uint32_t)k[10])<<16;
+ H5_ATTR_FALLTHROUGH
case 10: c+=((uint32_t)k[9])<<8;
+ H5_ATTR_FALLTHROUGH
case 9 : c+=k[8];
+ H5_ATTR_FALLTHROUGH
case 8 : b+=((uint32_t)k[7])<<24;
+ H5_ATTR_FALLTHROUGH
case 7 : b+=((uint32_t)k[6])<<16;
+ H5_ATTR_FALLTHROUGH
case 6 : b+=((uint32_t)k[5])<<8;
+ H5_ATTR_FALLTHROUGH
case 5 : b+=k[4];
+ H5_ATTR_FALLTHROUGH
case 4 : a+=((uint32_t)k[3])<<24;
+ H5_ATTR_FALLTHROUGH
case 3 : a+=((uint32_t)k[2])<<16;
+ H5_ATTR_FALLTHROUGH
case 2 : a+=((uint32_t)k[1])<<8;
+ H5_ATTR_FALLTHROUGH
case 1 : a+=k[0];
break;
case 0 : goto done;
diff --git a/src/H5dbg.c b/src/H5dbg.c
index dd50034..4939bca 100644
--- a/src/H5dbg.c
+++ b/src/H5dbg.c
@@ -113,7 +113,7 @@ H5_buffer_dump(FILE *stream, int indent, const uint8_t *buf,
} /* end else */
} /* end if */
else
- fprintf(stream, " ");
+ HDfprintf(stream, " ");
if(7 == v)
HDfputc(' ', stream);
} /* end for */
diff --git a/src/H5detect.c b/src/H5detect.c
index 4424009..d01ee9f 100644
--- a/src/H5detect.c
+++ b/src/H5detect.c
@@ -46,6 +46,11 @@ static const char *FileHeader = "\n\
#include "H5Tpublic.h"
#include "H5Rpublic.h"
+/* Disable warning about cast increasing the alignment of the target type,
+ * that's _exactly_ what this code is probing. -QAK
+ */
+#pragma GCC diagnostic ignored "-Wcast-align"
+
#if defined(__has_attribute)
# if __has_attribute(no_sanitize_address)
# define HDF_NO_UBSAN __attribute__((no_sanitize_address))
@@ -102,8 +107,8 @@ typedef struct detected_t {
unsigned int comp_align; /* alignment for structure */
} detected_t;
-/* This structure holds structure alignment for pointers, hvl_t, hobj_ref_t,
- * hdset_reg_ref_t */
+/* This structure holds structure alignment for pointers, vlen and reference
+ * types. */
typedef struct malign_t {
const char *name;
unsigned int comp_align; /* alignment for structure */
@@ -378,9 +383,8 @@ precision (detected_t *d)
/*-------------------------------------------------------------------------
* Function: DETECT_M
*
- * Purpose: This macro takes only miscellaneous structures or pointer
- * (pointer, hvl_t, hobj_ref_t, hdset_reg_ref_t). It
- * constructs the names and decides the alignment in structure.
+ * Purpose: This macro takes only miscellaneous structures or pointer.
+ * It constructs the names and decides the alignment in structure.
*
* Return: void
*-------------------------------------------------------------------------
@@ -756,8 +760,8 @@ H5T__init_native(void)\n\
H5T_native_order_g = H5T_ORDER_%s;\n", "BE");
}
- /* Structure alignment for pointers, hvl_t, hobj_ref_t, hdset_reg_ref_t */
- fprintf(rawoutstream, "\n /* Structure alignment for pointers, hvl_t, hobj_ref_t, hdset_reg_ref_t */\n");
+ /* Structure alignment for pointers, vlen and reference types */
+ fprintf(rawoutstream, "\n /* Structure alignment for pointers, vlen and reference types */\n");
for(j=0; j<na; j++)
fprintf(rawoutstream, " H5T_%s_COMP_ALIGN_g = %lu;\n", misc_align[j].name, (unsigned long)(misc_align[j].comp_align));
@@ -1539,11 +1543,12 @@ detect_C99_floats(void)
static void HDF_NO_UBSAN
detect_alignments(void)
{
- /* Detect structure alignment for pointers, hvl_t, hobj_ref_t, hdset_reg_ref_t */
+ /* Detect structure alignment for pointers, vlen and reference types */
DETECT_M(void *, POINTER, m_g[na_g]); na_g++;
DETECT_M(hvl_t, HVL, m_g[na_g]); na_g++;
DETECT_M(hobj_ref_t, HOBJREF, m_g[na_g]); na_g++;
DETECT_M(hdset_reg_ref_t, HDSETREGREF, m_g[na_g]); na_g++;
+ DETECT_M(H5R_ref_t, REF, m_g[na_g]); na_g++;
}
diff --git a/src/H5err.txt b/src/H5err.txt
index 19374cd..9fec521 100644
--- a/src/H5err.txt
+++ b/src/H5err.txt
@@ -46,7 +46,7 @@
MAJOR, H5E_ARGS, Invalid arguments to routine
MAJOR, H5E_RESOURCE, Resource unavailable
MAJOR, H5E_INTERNAL, Internal error (too specific to document in detail)
-MAJOR, H5E_FILE, File accessibilty
+MAJOR, H5E_FILE, File accessibility
MAJOR, H5E_IO, Low-level I/O
MAJOR, H5E_FUNC, Function entry/exit
MAJOR, H5E_ATOM, Object atom
@@ -66,6 +66,7 @@ MAJOR, H5E_PLINE, Data filters
MAJOR, H5E_EFL, External file list
MAJOR, H5E_REFERENCE, References
MAJOR, H5E_VFL, Virtual File Layer
+MAJOR, H5E_VOL, Virtual Object Layer
MAJOR, H5E_TST, Ternary Search Trees
MAJOR, H5E_RS, Reference Counted Strings
MAJOR, H5E_ERROR, Error API
@@ -77,12 +78,13 @@ MAJOR, H5E_FARRAY, Fixed Array
MAJOR, H5E_PLUGIN, Plugin for dynamically loaded library
MAJOR, H5E_PAGEBUF, Page Buffering
MAJOR, H5E_CONTEXT, API Context
+MAJOR, H5E_MAP, Map
MAJOR, H5E_NONE_MAJOR, No error
# Sections (for grouping minor errors)
SECTION, ARGS, Argument errors
SECTION, RESOURCE, Resource errors
-SECTION, FILEACC, File accessibilty errors
+SECTION, FILEACC, File accessibility errors
SECTION, FILE, Generic low-level file I/O errors
SECTION, FUNC, Function entry/exit interface errors
SECTION, ATOM, Object atom related errors
@@ -123,7 +125,7 @@ MINOR, RESOURCE, H5E_CANTGC, Unable to garbage collect
MINOR, RESOURCE, H5E_CANTGETSIZE, Unable to compute size
MINOR, RESOURCE, H5E_OBJOPEN, Object is already open
-# File accessibilty errors
+# File accessibility errors
MINOR, FILEACC, H5E_FILEEXISTS, File already exists
MINOR, FILEACC, H5E_FILEOPEN, File already open
MINOR, FILEACC, H5E_CANTCREATE, Unable to create file
@@ -133,6 +135,7 @@ MINOR, FILEACC, H5E_NOTHDF5, Not an HDF5 file
MINOR, FILEACC, H5E_BADFILE, Bad file ID accessed
MINOR, FILEACC, H5E_TRUNCATED, File has been truncated
MINOR, FILEACC, H5E_MOUNT, File mount error
+MINOR, FILEACC, H5E_CANTDELETEFILE, Unable to delete file
# Generic low-level file I/O errors
MINOR, FILE, H5E_SEEKERROR, Seek failed
@@ -180,7 +183,7 @@ MINOR, CACHE, H5E_CANTRESIZE, Unable to resize a metadata cache entry
MINOR, CACHE, H5E_CANTDEPEND, Unable to create a flush dependency
MINOR, CACHE, H5E_CANTUNDEPEND, Unable to destroy a flush dependency
MINOR, CACHE, H5E_CANTNOTIFY, Unable to notify object about action
-MINOR, CACHE, H5E_LOGFAIL, Failure in the cache logging framework
+MINOR, CACHE, H5E_LOGGING, Failure in the cache logging framework
MINOR, CACHE, H5E_CANTCORK, Unable to cork an object
MINOR, CACHE, H5E_CANTUNCORK, Unable to uncork an object
@@ -225,6 +228,7 @@ MINOR, DSPACE, H5E_CANTSELECT, Can't select hyperslab
MINOR, DSPACE, H5E_CANTNEXT, Can't move to next iterator location
MINOR, DSPACE, H5E_BADSELECT, Invalid selection
MINOR, DSPACE, H5E_CANTCOMPARE, Can't compare objects
+MINOR, DSPACE, H5E_INCONSISTENTSTATE, Internal states are inconsistent
MINOR, DSPACE, H5E_CANTAPPEND, Can't append object
# Property list errors
diff --git a/src/H5make_libsettings.c b/src/H5make_libsettings.c
index da7c8d9..fd67184 100644
--- a/src/H5make_libsettings.c
+++ b/src/H5make_libsettings.c
@@ -35,12 +35,15 @@ static const char *FileHeader = "\n\
#include <stdio.h>
#include <time.h>
#include "H5private.h"
+/* Do NOT use HDfprintf in this file as it is not linked with the library,
+ * which contains the H5system.c file in which the function is defined.
+ */
#define LIBSETTINGSFNAME "libhdf5.settings"
FILE *rawoutstream = NULL;
-
+
/*-------------------------------------------------------------------------
* Function: insert_libhdf5_settings
*
@@ -105,7 +108,7 @@ insert_libhdf5_settings(FILE *flibinfo)
#endif
} /* insert_libhdf5_settings() */
-
+
/*-------------------------------------------------------------------------
* Function: make_libinfo
*
@@ -123,7 +126,7 @@ make_libinfo(void)
insert_libhdf5_settings(rawoutstream);
}
-
+
/*-------------------------------------------------------------------------
* Function: print_header
*
@@ -229,7 +232,7 @@ information about the library build configuration\n";
fprintf(rawoutstream, "\n */\n\n");
}
-
+
/*-------------------------------------------------------------------------
* Function: print_footer
*
@@ -244,7 +247,7 @@ print_footer(void)
/* nothing */
}
-
+
/*-------------------------------------------------------------------------
* Function: main
*
diff --git a/src/H5mpi.c b/src/H5mpi.c
new file mode 100644
index 0000000..f529b3d
--- /dev/null
+++ b/src/H5mpi.c
@@ -0,0 +1,563 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Purpose: Common MPI routines
+ *
+ */
+
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5MMprivate.h" /* Memory Management */
+
+
+#ifdef H5_HAVE_PARALLEL
+
+/****************/
+/* Local Macros */
+/****************/
+#define TWO_GIG_LIMIT (1 << 31)
+#ifndef H5_MAX_MPI_COUNT
+#define H5_MAX_MPI_COUNT (1 << 30)
+#endif
+
+/*******************/
+/* Local Variables */
+/*******************/
+static hsize_t bigio_count = H5_MAX_MPI_COUNT;
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5_mpi_set_bigio_count
+ *
+ * Purpose: Allow us to programatically change the switch point
+ * when we utilize derived datatypes. This is of
+ * particular interest for allowing nightly testing
+ *
+ * Return: The current/previous value of bigio_count.
+ *
+ * Programmer: Richard Warren, March 10, 2017
+ *
+ *-------------------------------------------------------------------------
+ */
+hsize_t
+H5_mpi_set_bigio_count(hsize_t new_count)
+{
+ hsize_t orig_count = bigio_count;
+
+ if((new_count > 0) && (new_count < (hsize_t)TWO_GIG_LIMIT)) {
+ bigio_count = new_count;
+ }
+ return orig_count;
+} /* end H5_mpi_set_bigio_count() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5_mpi_get_bigio_count
+ *
+ * Purpose: Allow other HDF5 library functions to access
+ * the current value for bigio_count.
+ *
+ * Return: The current/previous value of bigio_count.
+ *
+ * Programmer: Richard Warren, October 7, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+hsize_t
+H5_mpi_get_bigio_count()
+{
+ return bigio_count;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5_mpi_comm_dup
+ *
+ * Purpose: Duplicate an MPI communicator.
+ *
+ * Does not duplicate MPI_COMM_NULL. Instead, comm_new will
+ * be set to MPI_COMM_NULL directly.
+ *
+ * The new communicator is returned via the comm_new pointer.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5_mpi_comm_dup(MPI_Comm comm, MPI_Comm *comm_new)
+{
+ herr_t ret_value = SUCCEED;
+ MPI_Comm comm_dup = MPI_COMM_NULL;
+ int mpi_code;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Check arguments */
+ if (!comm_new)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_BADVALUE, FAIL, "comm_new cannot be NULL")
+
+ /* Handle MPI_COMM_NULL separately */
+ if (MPI_COMM_NULL == comm) {
+ /* Don't duplicate MPI_COMM_NULL since that's an error in MPI */
+ comm_dup = MPI_COMM_NULL;
+ }
+ else {
+
+ /* Duplicate the MPI communicator */
+ if (MPI_SUCCESS != (mpi_code = MPI_Comm_dup(comm, &comm_dup)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Comm_dup failed", mpi_code)
+
+ /* Set MPI_ERRORS_RETURN on comm_dup so that MPI failures are not fatal,
+ * and return codes can be checked and handled.
+ */
+ if (MPI_SUCCESS != (mpi_code = MPI_Comm_set_errhandler(comm_dup, MPI_ERRORS_RETURN)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Errhandler_set failed", mpi_code)
+
+ }
+
+ /* Copy the new communicator to the return argument */
+ *comm_new = comm_dup;
+
+done:
+ if (FAIL == ret_value) {
+ /* need to free anything created here */
+ if (MPI_COMM_NULL != comm_dup)
+ MPI_Comm_free(&comm_dup);
+ }
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5_mpi_comm_dup() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5_mpi_info_dup
+ *
+ * Purpose: Duplicate an MPI info.
+ *
+ * If the info object is MPI_INFO_NULL, no duplicate
+ * is made but the same value assigned to the new info object
+ * handle.
+ *
+ * The new info is returned via the info_new pointer.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5_mpi_info_dup(MPI_Info info, MPI_Info *info_new)
+{
+ herr_t ret_value = SUCCEED;
+ MPI_Info info_dup = MPI_INFO_NULL;
+ int mpi_code;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Check arguments */
+ if (!info_new)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_BADVALUE, FAIL, "info_new cannot be NULL")
+
+ /* Duplicate the MPI info */
+ if (info == MPI_INFO_NULL) {
+ /* Don't duplicate MPI_INFO_NULL. Just copy it. */
+ info_dup = MPI_INFO_NULL;
+ }
+ else {
+ /* Duplicate the info */
+ if (MPI_SUCCESS != (mpi_code = MPI_Info_dup(info, &info_dup)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Info_dup failed", mpi_code)
+ }
+
+ /* Copy the new info to the return argument */
+ *info_new = info_dup;
+
+done:
+ if (FAIL == ret_value) {
+ /* need to free anything created here */
+ if (MPI_INFO_NULL != info_dup)
+ MPI_Info_free(&info_dup);
+ }
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5_mpi_info_dup() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5_mpi_comm_free
+ *
+ * Purpose: Free an MPI communicator.
+ *
+ * If comm is MPI_COMM_NULL this call does nothing.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5_mpi_comm_free(MPI_Comm *comm)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Check arguments */
+ if (!comm)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_BADVALUE, FAIL, "comm pointer cannot be NULL")
+
+ /* Free the communicator */
+ if (MPI_COMM_NULL != *comm)
+ MPI_Comm_free(comm);
+
+ *comm = MPI_COMM_NULL;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* End H5_mpi_comm_free() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5_mpi_info_free
+ *
+ * Purpose: Free the MPI info.
+ *
+ * If info is MPI_INFO_NULL this call does nothing.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5_mpi_info_free(MPI_Info *info)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Check arguments */
+ if (!info)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_BADVALUE, FAIL, "info pointer cannot be NULL")
+
+ /* Free the info */
+ if (MPI_INFO_NULL != *info)
+ MPI_Info_free(info);
+
+ *info = MPI_INFO_NULL;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* End H5_mpi_info_free() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5_mpi_comm_cmp
+ *
+ * Purpose: Compares two MPI communicators.
+ *
+ * Note that passing MPI_COMM_NULL to this function will not
+ * throw errors, unlike MPI_Comm_compare().
+ *
+ * We consider MPI communicators to be the "same" when the
+ * groups are identical. We don't care about the context
+ * since that will always be different as we call MPI_Comm_dup
+ * when we store the communicator in the fapl.
+ *
+ * The out parameter is a value like strcmp. The value is
+ * undefined when the return value is FAIL.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5_mpi_comm_cmp(MPI_Comm comm1, MPI_Comm comm2, int *result)
+{
+ int mpi_code;
+ int mpi_result = MPI_IDENT;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Check arguments */
+ if (!result)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_BADVALUE, FAIL, "result cannot be NULL")
+
+ /* Set out parameter to something reasonable in case something goes wrong */
+ *result = 0;
+
+ /* Can't pass MPI_COMM_NULL to MPI_Comm_compare() so we have to handle
+ * it in special cases.
+ *
+ * MPI_Comm can either be an integer type or a pointer. We cast them
+ * to intptr_t so we can compare them with < and > when needed.
+ */
+ if (MPI_COMM_NULL == comm1 && MPI_COMM_NULL == comm2) {
+ /* Special case of both communicators being MPI_COMM_NULL */
+ *result = 0;
+ }
+ else if (MPI_COMM_NULL == comm1 || MPI_COMM_NULL == comm2) {
+
+ /* Special case of one communicator being MPI_COMM_NULL */
+ *result = (intptr_t)comm1 < (intptr_t)comm2 ? -1 : 1;
+ }
+ else {
+
+ /* Normal communicator compare */
+
+ /* Compare the MPI communicators */
+ if (MPI_SUCCESS != (mpi_code = MPI_Comm_compare(comm1, comm2, &mpi_result)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Comm_compare failed", mpi_code)
+
+ /* Set the result */
+ if (MPI_IDENT == mpi_result || MPI_CONGRUENT == mpi_result)
+ *result = 0;
+ else
+ *result = (intptr_t)comm1 < (intptr_t)comm2 ? -1 : 1;
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5_mpi_comm_cmp() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5_mpi_info_cmp
+ *
+ * Purpose: Compares two MPI info objects.
+ *
+ * For our purposes, two mpi info objects are the "same" if
+ * they contain the same key-value pairs or are both
+ * MPI_INFO_NULL.
+ *
+ * The out parameter is a value like strcmp. The value is
+ * undefined when the return value is FAIL.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5_mpi_info_cmp(MPI_Info info1, MPI_Info info2, int *result)
+{
+ hbool_t same = FALSE;
+ char *key = NULL;
+ char *value1 = NULL;
+ char *value2 = NULL;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Check arguments */
+ if (!result)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_BADVALUE, FAIL, "result cannot be NULL")
+
+ /* Check for MPI_INFO_NULL */
+ if (MPI_INFO_NULL == info1 && MPI_INFO_NULL == info2) {
+ /* Special case of both info objects being MPI_INFO_NULL */
+ same = TRUE;
+ }
+ else if (MPI_INFO_NULL == info1 || MPI_INFO_NULL == info2) {
+
+ /* Special case of one info object being MPI_INFO_NULL */
+ same = FALSE;
+ }
+ else {
+ int mpi_code;
+ int nkeys_1;
+ int nkeys_2;
+
+ /* Check if the number of keys is the same */
+ if (MPI_SUCCESS != (mpi_code = MPI_Info_get_nkeys(info1, &nkeys_1)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Info_get_nkeys failed", mpi_code)
+ if (MPI_SUCCESS != (mpi_code = MPI_Info_get_nkeys(info2, &nkeys_2)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Info_get_nkeys failed", mpi_code)
+
+ if (nkeys_1 != nkeys_2)
+ same = FALSE;
+ else if (0 == nkeys_1 && 0 == nkeys_2)
+ same = TRUE;
+ else {
+ int i;
+ int flag1 = -1;
+ int flag2 = -1;
+
+ /* Allocate buffers for iteration */
+ if (NULL == (key = (char *)H5MM_malloc(MPI_MAX_INFO_KEY * sizeof(char))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ if (NULL == (value1 = (char *)H5MM_malloc(MPI_MAX_INFO_VAL * sizeof(char))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ if (NULL == (value2 = (char *)H5MM_malloc(MPI_MAX_INFO_VAL * sizeof(char))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /* Iterate over the keys, comparing them */
+ for (i = 0; i < nkeys_1; i++) {
+
+ same = TRUE;
+
+ /* Memset the buffers to zero */
+ HDmemset(key, 0, MPI_MAX_INFO_KEY);
+ HDmemset(value1, 0, MPI_MAX_INFO_VAL);
+ HDmemset(value2, 0, MPI_MAX_INFO_VAL);
+
+ /* Get the nth key */
+ if (MPI_SUCCESS != (mpi_code = MPI_Info_get_nthkey(info1, i, key)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Info_get_nthkey failed", mpi_code)
+
+ /* Get the values */
+ if (MPI_SUCCESS != (mpi_code = MPI_Info_get(info1, key, MPI_MAX_INFO_VAL, value1, &flag1)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Info_get failed", mpi_code)
+ if (MPI_SUCCESS != (mpi_code = MPI_Info_get(info2, key, MPI_MAX_INFO_VAL, value2, &flag2)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Info_get failed", mpi_code)
+
+ /* Compare values and flags */
+ if (!flag1 || !flag2 || HDmemcmp(value1, value2, MPI_MAX_INFO_VAL)) {
+ same = FALSE;
+ break;
+ }
+
+ } /* end for */
+ } /* end else */
+ } /* end else */
+
+ /* Set the output value
+ *
+ * MPI_Info can either be an integer type or a pointer. We cast them
+ * to intptr_t so we can compare them with < and > when needed.
+ */
+ if (same)
+ *result = 0;
+ else
+ *result = (intptr_t)info1 < (intptr_t)info2 ? -1 : 1;
+
+done:
+ if (key)
+ H5MM_xfree(key);
+ if (value1)
+ H5MM_xfree(value1);
+ if (value2)
+ H5MM_xfree(value2);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5_mpi_info_cmp() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5_mpio_create_large_type
+ *
+ * Purpose: Create a large datatype of size larger than what a 32 bit integer
+ * can hold.
+ *
+ * Return: Non-negative on success, negative on failure.
+ *
+ * *new_type the new datatype created
+ *
+ * Programmer: Mohamad Chaarawi
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5_mpio_create_large_type(hsize_t num_elements, MPI_Aint stride_bytes,
+ MPI_Datatype old_type, MPI_Datatype *new_type)
+{
+ int num_big_types; /* num times the 2G datatype will be repeated */
+ int remaining_bytes; /* the number of bytes left that can be held in an int value */
+ hsize_t leftover;
+ int block_len[2];
+ int mpi_code; /* MPI return code */
+ MPI_Datatype inner_type, outer_type, leftover_type, type[2];
+ MPI_Aint disp[2], old_extent;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Calculate how many Big MPI datatypes are needed to represent the buffer */
+ num_big_types = (int)(num_elements/bigio_count);
+ leftover = num_elements - num_big_types * (hsize_t)bigio_count;
+ H5_CHECKED_ASSIGN(remaining_bytes, int, leftover, hsize_t);
+
+ /* Create a contiguous datatype of size equal to the largest
+ * number that a 32 bit integer can hold x size of old type.
+ * If the displacement is 0, then the type is contiguous, otherwise
+ * use type_hvector to create the type with the displacement provided
+ */
+ if (0 == stride_bytes) {
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_contiguous(bigio_count, old_type, &inner_type)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Type_contiguous failed", mpi_code)
+ } /* end if */
+ else
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_create_hvector(bigio_count, 1, stride_bytes, old_type, &inner_type)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hvector failed", mpi_code)
+
+ /* Create a contiguous datatype of the buffer (minus the remaining < 2GB part)
+ * If a stride is present, use hvector type
+ */
+ if(0 == stride_bytes) {
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_contiguous(num_big_types, inner_type, &outer_type)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Type_contiguous failed", mpi_code)
+ } /* end if */
+ else
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_create_hvector(num_big_types, 1, stride_bytes, inner_type, &outer_type)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hvector failed", mpi_code)
+
+ MPI_Type_free(&inner_type);
+
+ /* If there is a remaining part create a contiguous/vector datatype and then
+ * use a struct datatype to encapsulate everything.
+ */
+ if(remaining_bytes) {
+ if(stride_bytes == 0) {
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_contiguous(remaining_bytes, old_type, &leftover_type)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Type_contiguous failed", mpi_code)
+ } /* end if */
+ else
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_create_hvector((int)(num_elements - (hsize_t)num_big_types * bigio_count), 1, stride_bytes, old_type, &leftover_type)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hvector failed", mpi_code)
+
+ /* As of version 4.0, OpenMPI now turns off MPI-1 API calls by default,
+ * so we're using the MPI-2 version even though we don't need the lb
+ * value.
+ */
+ {
+ MPI_Aint unused_lb_arg;
+ MPI_Type_get_extent(old_type, &unused_lb_arg, &old_extent);
+ }
+
+ /* Set up the arguments for MPI_Type_struct constructor */
+ type[0] = outer_type;
+ type[1] = leftover_type;
+ block_len[0] = 1;
+ block_len[1] = 1;
+ disp[0] = 0;
+ disp[1] = (old_extent + stride_bytes) * num_big_types * (MPI_Aint)bigio_count;
+
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_create_struct(2, block_len, disp, type, new_type)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_struct failed", mpi_code)
+
+ MPI_Type_free(&outer_type);
+ MPI_Type_free(&leftover_type);
+ } /* end if */
+ else
+ /* There are no remaining bytes so just set the new type to
+ * the outer type created */
+ *new_type = outer_type;
+
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(new_type)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code)
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5_mpio_create_large_type() */
+
+
+#endif /* H5_HAVE_PARALLEL */
+
diff --git a/src/H5private.h b/src/H5private.h
index 91d5c91..cbdccce 100644
--- a/src/H5private.h
+++ b/src/H5private.h
@@ -169,6 +169,9 @@
*/
#define H5_DEFAULT_VFD H5FD_SEC2
+/* Define the default VOL driver */
+#define H5_DEFAULT_VOL H5VL_NATIVE
+
#ifdef H5_HAVE_WIN32_API
/* The following two defines must be before any windows headers are included */
#define WIN32_LEAN_AND_MEAN /* Exclude rarely-used stuff from Windows headers */
@@ -306,6 +309,7 @@
# define H5_ATTR_NORETURN /*void*/
# define H5_ATTR_CONST /*void*/
# define H5_ATTR_PURE /*void*/
+# define H5_ATTR_FALLTHROUGH /*void*/
#else /* __cplusplus */
#if defined(H5_HAVE_ATTRIBUTE) && !defined(__SUNPRO_C)
# define H5_ATTR_FORMAT(X,Y,Z) __attribute__((format(X, Y, Z)))
@@ -313,12 +317,18 @@
# define H5_ATTR_NORETURN __attribute__((noreturn))
# define H5_ATTR_CONST __attribute__((const))
# define H5_ATTR_PURE __attribute__((pure))
+#if defined(__GNUC__) && __GNUC__ >= 7 && !defined(__INTEL_COMPILER)
+# define H5_ATTR_FALLTHROUGH __attribute__((fallthrough));
+#else
+# define H5_ATTR_FALLTHROUGH /*void*/
+#endif
#else
# define H5_ATTR_FORMAT(X,Y,Z) /*void*/
# define H5_ATTR_UNUSED /*void*/
# define H5_ATTR_NORETURN /*void*/
# define H5_ATTR_CONST /*void*/
# define H5_ATTR_PURE /*void*/
+# define H5_ATTR_FALLTHROUGH /*void*/
#endif
#endif /* __cplusplus */
@@ -518,6 +528,11 @@
# define H5_INC_ENUM(TYPE,VAR) (VAR)=((TYPE)((VAR)+1))
#endif
+/* Represents an empty asynchronous request handle.
+ * Used in the VOL code.
+ */
+#define H5_REQUEST_NULL NULL
+
/*
* A macro to portably decrement enumerated types.
*/
@@ -1107,12 +1122,8 @@ typedef off_t h5_stat_size_t;
#ifndef HDmemcmp
#define HDmemcmp(X,Y,Z) memcmp(X,Y,Z)
#endif /* HDmemcmp */
-/*
- * The (char*) casts are required for the DEC when optimizations are turned
- * on and the source and/or destination are not aligned.
- */
#ifndef HDmemcpy
- #define HDmemcpy(X,Y,Z) memcpy((char*)(X),(const char*)(Y),Z)
+ #define HDmemcpy(X,Y,Z) memcpy(X,Y,Z)
#endif /* HDmemcpy */
#ifndef HDmemmove
#define HDmemmove(X,Y,Z) memmove((char*)(X),(const char*)(Y),Z)
@@ -1159,6 +1170,9 @@ typedef off_t h5_stat_size_t;
#ifndef HDpowf
#define HDpowf(X,Y) powf(X,Y)
#endif /* HDpowf */
+#ifndef HDpread
+ #define HDpread(F,B,C,O) pread(F,B,C,O)
+#endif /* HDpread */
#ifndef HDprintf
#define HDprintf(...) HDfprintf(stdout, __VA_ARGS__)
#endif /* HDprintf */
@@ -1171,6 +1185,9 @@ typedef off_t h5_stat_size_t;
#ifndef HDputs
#define HDputs(S) puts(S)
#endif /* HDputs */
+#ifndef HDpwrite
+ #define HDpwrite(F,B,C,O) pwrite(F,B,C,O)
+#endif /* HDpwrite */
#ifndef HDqsort
#define HDqsort(M,N,Z,F) qsort(M,N,Z,F)
#endif /* HDqsort*/
@@ -1337,8 +1354,9 @@ typedef off_t h5_stat_size_t;
#define HDsrandom(S) srand(S)
#endif /* HDsrandom */
#endif /* H5_HAVE_RAND_R */
-/* sscanf() variable arguments */
-
+#ifndef HDsscanf
+ #define HDsscanf(S,FMT,...) sscanf(S,FMT,__VA_ARGS__)
+#endif /* HDsscanf */
#ifndef HDstrcat
#define HDstrcat(X,Y) strcat(X,Y)
#endif /* HDstrcat */
@@ -1396,6 +1414,9 @@ typedef off_t h5_stat_size_t;
#ifndef HDstrtok
#define HDstrtok(X,Y) strtok(X,Y)
#endif /* HDstrtok */
+#ifndef HDstrtok_r
+ #define HDstrtok_r(X,Y,Z) strtok_r(X,Y,Z)
+#endif /* HDstrtok */
#ifndef HDstrtol
#define HDstrtol(S,R,N) strtol(S,R,N)
#endif /* HDstrtol */
@@ -1498,6 +1519,9 @@ typedef off_t h5_stat_size_t;
#ifndef HDva_arg
#define HDva_arg(A,T) va_arg(A,T)
#endif /* HDva_arg */
+#ifndef HDva_copy
+#define HDva_copy(D,S) va_copy(D,S)
+#endif /* HDva_copy */
#ifndef HDva_end
#define HDva_end(A) va_end(A)
#endif /* HDva_end */
@@ -1717,6 +1741,7 @@ typedef enum {
H5_PKG_HG, /* Global heaps */
H5_PKG_HL, /* Local heaps */
H5_PKG_I, /* IDs */
+ H5_PKG_M, /* Maps */
H5_PKG_MF, /* File memory management */
H5_PKG_MM, /* Core memory management */
H5_PKG_O, /* Object headers */
@@ -1724,6 +1749,7 @@ typedef enum {
H5_PKG_S, /* Dataspaces */
H5_PKG_T, /* Datatypes */
H5_PKG_V, /* Vector functions */
+ H5_PKG_VL, /* VOL functions */
H5_PKG_Z, /* Raw data filters */
H5_NPKGS /* Must be last */
} H5_pkg_t;
@@ -1962,8 +1988,6 @@ extern hbool_t H5_libterm_g; /* Is the library being shutdown? */
#define H5_INIT_GLOBAL (H5_libinit_g)
#define H5_TERM_GLOBAL (H5_libterm_g)
-#include "H5FDvfd_swmr_private.h"
-
#endif /* H5_HAVE_THREADSAFE */
#ifdef H5_HAVE_CODESTACK
@@ -2079,42 +2103,42 @@ H5_DLL herr_t H5CX_pop(void);
\
BEGIN_MPE_LOG
+#include "H5FDvfd_swmr_private.h"
#include "H5time_private.h" /* for timespeccmp */
-#define VFD_SWMR_TEST_FOR_END_OF_TICK(entering, swmr_reader_exit, err) \
- /* Initialize the library */ \
- /* TBD assert that the API lock is held. The API lock */ \
- /* synchronizes access to `vfd_swmr_api_entries_g` */ \
- { \
- if (!entering && --vfd_swmr_api_entries_g > 0) { \
- ; /* Do nothing: we are still in an API call. */ \
- } else if (entering && vfd_swmr_api_entries_g++ > 0) { \
- ; /* Do nothing: we are *re-*entering the API. */ \
- } else if(err_occurred) { \
- ; /* Do nothing: an error occurred. */ \
- } else if(vfd_swmr_eot_queue_head_g != NULL) { \
- struct H5F_vfd_swmr_eot_queue_entry_t *init_eot_queue_head = vfd_swmr_eot_queue_head_g; \
- struct timespec curr_time; \
- do { \
- if(HDclock_gettime(CLOCK_MONOTONIC, &curr_time) < 0) \
- HGOTO_ERROR(H5E_FUNC, H5E_CANTGET, err, \
- "can't get time via clock_gettime") \
- if(timespeccmp(&curr_time, &end_of_tick_g, <)) { \
- break; \
- } else if(vfd_swmr_writer_g) { \
- if(H5F_vfd_swmr_writer_end_of_tick(NULL) < 0) \
- HGOTO_ERROR(H5E_FUNC, H5E_CANTSET, err, \
- "end of tick error for VFD SWMR writer") \
- } else if(!swmr_reader_exit) { \
- if(H5F_vfd_swmr_reader_end_of_tick(NULL) < 0) \
- HGOTO_ERROR(H5E_FUNC, H5E_CANTSET, err, \
- "end of tick error for VFD SWMR reader") \
- } else \
- break; \
- } while ((vfd_swmr_eot_queue_head_g != NULL) && \
- (vfd_swmr_eot_queue_head_g != init_eot_queue_head)); \
- } \
- }
+#define VFD_SWMR_TEST_FOR_END_OF_TICK(entering, _swmr_reader_exit, err) \
+ /* Initialize the library */ \
+ /* TBD assert that the API lock is held. The API lock */ \
+ /* synchronizes access to `vfd_swmr_api_entries_g` */ \
+ if (!entering && --vfd_swmr_api_entries_g > 0) { \
+ ; /* Do nothing: we are still in an API call. */ \
+ } else if (entering && vfd_swmr_api_entries_g++ > 0) { \
+ ; /* Do nothing: we are *re-*entering the API. */ \
+ } else if(err_occurred) { \
+ ; /* Do nothing: an error occurred. */ \
+ } else if(vfd_swmr_eot_queue_head_g != NULL) { \
+ const bool swmr_reader_exit = _swmr_reader_exit; \
+ struct timespec curr_time; \
+ struct H5F_vfd_swmr_eot_queue_entry_t *init_eot_queue_head = vfd_swmr_eot_queue_head_g; \
+ do { \
+ if(HDclock_gettime(CLOCK_MONOTONIC, &curr_time) < 0) { \
+ HGOTO_ERROR(H5E_FUNC, H5E_CANTGET, err, \
+ "can't get time via clock_gettime") \
+ } else if(timespeccmp(&curr_time, &end_of_tick_g, <)) { \
+ break; \
+ } else if (vfd_swmr_writer_g) { \
+ if(H5F_vfd_swmr_writer_end_of_tick(NULL) < 0) \
+ HGOTO_ERROR(H5E_FUNC, H5E_CANTSET, err, \
+ "end of tick error for VFD SWMR writer") \
+ } else if(!swmr_reader_exit) { \
+ if(H5F_vfd_swmr_reader_end_of_tick(NULL) < 0) \
+ HGOTO_ERROR(H5E_FUNC, H5E_CANTSET, err, \
+ "end of tick error for VFD SWMR reader") \
+ } else \
+ break; \
+ } while ((vfd_swmr_eot_queue_head_g != NULL) && \
+ (vfd_swmr_eot_queue_head_g != init_eot_queue_head)); \
+ } \
/* Use this macro for all "normal" API functions */
#define FUNC_ENTER_API(err) {{ \
@@ -2138,10 +2162,11 @@ H5_DLL herr_t H5CX_pop(void);
/*
* Use this macro for API functions that shouldn't perform _any_ initialization
* of the library or an interface, just perform tracing, etc. Examples
- * are: H5allocate_memory, H5is_library_threadsafe, etc.
+ * are: H5allocate_memory, H5is_library_threadsafe, public VOL callback
+ * wrappers (e.g. H5VLfile_create, H5VLdataset_read, etc.), etc.
*
*/
-#define FUNC_ENTER_API_NOINIT {{ \
+#define FUNC_ENTER_API_NOINIT {{{ \
FUNC_ENTER_API_COMMON \
H5_PUSH_FUNC \
BEGIN_MPE_LOG \
@@ -2154,7 +2179,7 @@ H5_DLL herr_t H5CX_pop(void);
* are: H5close, H5check_version, etc.
*
*/
-#define FUNC_ENTER_API_NOINIT_NOERR_NOFS {{ \
+#define FUNC_ENTER_API_NOINIT_NOERR_NOFS {{{{ \
FUNC_ENTER_API_VARS \
FUNC_ENTER_COMMON_NOERR(H5_IS_API(FUNC)); \
FUNC_ENTER_API_THREADSAFE; \
@@ -2342,14 +2367,14 @@ H5_DLL herr_t H5CX_pop(void);
(void)H5E_dump_api_stack(TRUE); \
FUNC_LEAVE_API_THREADSAFE \
return(ret_value); \
-}} /*end scope from beginning of FUNC_ENTER*/
+}}} /*end scope from beginning of FUNC_ENTER*/
/* Use this macro to match the FUNC_ENTER_API_NOINIT_NOERR_NOFS macro */
#define FUNC_LEAVE_API_NOFS(ret_value) \
FUNC_LEAVE_API_COMMON(ret_value); \
FUNC_LEAVE_API_THREADSAFE \
return(ret_value); \
-}} /*end scope from beginning of FUNC_ENTER*/
+}}}} /*end scope from beginning of FUNC_ENTER*/
#define FUNC_LEAVE_NOAPI(ret_value) \
; \
@@ -2673,6 +2698,8 @@ H5_DLL int H5G_term_package(void);
H5_DLL int H5G_top_term_package(void);
H5_DLL int H5I_term_package(void);
H5_DLL int H5L_term_package(void);
+H5_DLL int H5M_term_package(void);
+H5_DLL int H5M_top_term_package(void);
H5_DLL int H5P_term_package(void);
H5_DLL int H5PL_term_package(void);
H5_DLL int H5R_term_package(void);
@@ -2682,6 +2709,7 @@ H5_DLL int H5S_top_term_package(void);
H5_DLL int H5SL_term_package(void);
H5_DLL int H5T_term_package(void);
H5_DLL int H5T_top_term_package(void);
+H5_DLL int H5VL_term_package(void);
H5_DLL int H5Z_term_package(void);
/* Checksum functions */
@@ -2700,11 +2728,23 @@ H5_DLL double H5_get_time(void);
H5_DLL herr_t H5_build_extpath(const char *name, char **extpath /*out*/);
H5_DLL herr_t H5_combine_path(const char *path1, const char *path2, char **full_name /*out*/);
+#ifdef H5_HAVE_PARALLEL
+/* Generic MPI functions */
+H5_DLL hsize_t H5_mpi_set_bigio_count(hsize_t new_count);
+H5_DLL hsize_t H5_mpi_get_bigio_count();
+H5_DLL herr_t H5_mpi_comm_dup(MPI_Comm comm, MPI_Comm *comm_new);
+H5_DLL herr_t H5_mpi_info_dup(MPI_Info info, MPI_Info *info_new);
+H5_DLL herr_t H5_mpi_comm_free(MPI_Comm *comm);
+H5_DLL herr_t H5_mpi_info_free(MPI_Info *info);
+H5_DLL herr_t H5_mpi_comm_cmp(MPI_Comm comm1, MPI_Comm comm2, int *result);
+H5_DLL herr_t H5_mpi_info_cmp(MPI_Info info1, MPI_Info info2, int *result);
+H5_DLL herr_t H5_mpio_create_large_type(hsize_t num_elements, MPI_Aint stride_bytes,
+ MPI_Datatype old_type, MPI_Datatype *new_type);
+#endif /* H5_HAVE_PARALLEL */
+
/* Functions for debugging */
H5_DLL herr_t H5_buffer_dump(FILE *stream, int indent, const uint8_t *buf,
const uint8_t *marker, size_t buf_offset, size_t buf_size);
-#include "H5retry_private.h"
-
#endif /* _H5private_H */
diff --git a/src/H5public.h b/src/H5public.h
index 4dc617f..828c2d6 100644
--- a/src/H5public.h
+++ b/src/H5public.h
@@ -57,6 +57,9 @@
# include <stddef.h>
#endif
#ifdef H5_HAVE_PARALLEL
+/* Don't link against MPI C++ bindings */
+# define MPICH_SKIP_MPICXX 1
+# define OMPI_SKIP_MPICXX 1
# include <mpi.h>
#ifndef MPI_FILE_NULL /*MPIO may be defined in mpi.h already */
# include <mpio.h>
@@ -92,11 +95,11 @@ extern "C" {
/* Version numbers */
#define H5_VERS_MAJOR 1 /* For major interface/format changes */
-#define H5_VERS_MINOR 11 /* For minor interface/format changes */
-#define H5_VERS_RELEASE 3 /* For tweaks, bug-fixes, or development */
+#define H5_VERS_MINOR 13 /* For minor interface/format changes */
+#define H5_VERS_RELEASE 0 /* For tweaks, bug-fixes, or development */
#define H5_VERS_SUBRELEASE "" /* For pre-releases like snap0 */
/* Empty string for real releases. */
-#define H5_VERS_INFO "HDF5 library version: 1.11.3" /* Full version string */
+#define H5_VERS_INFO "HDF5 library version: 1.13.0" /* Full version string */
#define H5check() H5check_version(H5_VERS_MAJOR,H5_VERS_MINOR, \
H5_VERS_RELEASE)
diff --git a/src/H5system.c b/src/H5system.c
index 55cac8d..c47e60c 100644
--- a/src/H5system.c
+++ b/src/H5system.c
@@ -95,12 +95,16 @@ static hbool_t H5_ntzset = FALSE;
* Programmer: Robb Matzke
* Thursday, April 9, 1998
*
- * Modifications:
- * Robb Matzke, 1999-07-27
- * The `%a' format refers to an argument of `haddr_t' type
- * instead of `haddr_t*' and the return value is correct.
*-------------------------------------------------------------------------
*/
+/* Disable warning for "format not a string literal" here -QAK */
+/*
+ * This pragma only needs to surround the fprintf() calls with
+ * format_templ in the code below, but early (4.4.7, at least) gcc only
+ * allows diagnostic pragmas to be toggled outside of functions.
+ */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
int
HDfprintf(FILE *stream, const char *fmt, ...)
{
@@ -121,7 +125,7 @@ HDfprintf(FILE *stream, const char *fmt, ...)
HDassert(stream);
HDassert(fmt);
- va_start (ap, fmt);
+ HDva_start (ap, fmt);
while (*fmt) {
fwidth = prec = 0;
zerofill = 0;
@@ -170,7 +174,7 @@ HDfprintf(FILE *stream, const char *fmt, ...)
s = rest;
} /* end if */
else if ('*'==*s) {
- fwidth = va_arg(ap, int);
+ fwidth = HDva_arg(ap, int);
if(fwidth < 0) {
leftjust = 1;
fwidth = -fwidth;
@@ -185,7 +189,7 @@ HDfprintf(FILE *stream, const char *fmt, ...)
prec = (int)HDstrtol(s, &rest, 10);
s = rest;
} else if('*'==*s) {
- prec = va_arg(ap, int);
+ prec = HDva_arg(ap, int);
s++;
}
if(prec < 1)
@@ -272,16 +276,16 @@ HDfprintf(FILE *stream, const char *fmt, ...)
case 'd':
case 'i':
if(!HDstrcmp(modifier, "h")) {
- short x = (short)va_arg(ap, int);
+ short x = (short)HDva_arg(ap, int);
n = fprintf(stream, format_templ, x);
} else if(!*modifier) {
- int x = va_arg(ap, int);
+ int x = HDva_arg(ap, int);
n = fprintf(stream, format_templ, x);
} else if(!HDstrcmp(modifier, "l")) {
- long x = va_arg(ap, long);
+ long x = HDva_arg(ap, long);
n = fprintf(stream, format_templ, x);
} else {
- int64_t x = va_arg(ap, int64_t);
+ int64_t x = HDva_arg(ap, int64_t);
n = fprintf(stream, format_templ, x);
}
break;
@@ -291,16 +295,16 @@ HDfprintf(FILE *stream, const char *fmt, ...)
case 'x':
case 'X':
if(!HDstrcmp(modifier, "h")) {
- unsigned short x = (unsigned short)va_arg(ap, unsigned int);
+ unsigned short x = (unsigned short)HDva_arg(ap, unsigned int);
n = fprintf(stream, format_templ, x);
} else if(!*modifier) {
- unsigned int x = va_arg(ap, unsigned int);
+ unsigned int x = HDva_arg(ap, unsigned int);
n = fprintf(stream, format_templ, x);
} else if(!HDstrcmp(modifier, "l")) {
- unsigned long x = va_arg(ap, unsigned long);
+ unsigned long x = HDva_arg(ap, unsigned long);
n = fprintf(stream, format_templ, x);
} else {
- uint64_t x = va_arg(ap, uint64_t);
+ uint64_t x = HDva_arg(ap, uint64_t);
n = fprintf(stream, format_templ, x);
}
break;
@@ -311,10 +315,10 @@ HDfprintf(FILE *stream, const char *fmt, ...)
case 'g':
case 'G':
if(!HDstrcmp(modifier, "h")) {
- float x = (float)va_arg(ap, double);
+ float x = (float)HDva_arg(ap, double);
n = fprintf(stream, format_templ, (double)x);
} else if(!*modifier || !HDstrcmp(modifier, "l")) {
- double x = va_arg(ap, double);
+ double x = HDva_arg(ap, double);
n = fprintf(stream, format_templ, x);
} else {
/*
@@ -322,10 +326,10 @@ HDfprintf(FILE *stream, const char *fmt, ...)
* `double' are the same thing.
*/
#if H5_SIZEOF_LONG_DOUBLE != H5_SIZEOF_DOUBLE
- long double x = va_arg(ap, long double);
+ long double x = HDva_arg(ap, long double);
n = fprintf(stream, format_templ, x);
#else
- double x = va_arg(ap, double);
+ double x = HDva_arg(ap, double);
n = fprintf(stream, format_templ, x);
#endif
}
@@ -333,7 +337,7 @@ HDfprintf(FILE *stream, const char *fmt, ...)
case 'a':
{
- haddr_t x = va_arg(ap, haddr_t);
+ haddr_t x = HDva_arg(ap, haddr_t);
if(H5F_addr_defined(x)) {
len = 0;
@@ -379,7 +383,7 @@ HDfprintf(FILE *stream, const char *fmt, ...)
case 'c':
{
- char x = (char)va_arg(ap, int);
+ char x = (char)HDva_arg(ap, int);
n = fprintf(stream, format_templ, x);
}
break;
@@ -387,7 +391,7 @@ HDfprintf(FILE *stream, const char *fmt, ...)
case 's':
case 'p':
{
- char *x = va_arg(ap, char*);
+ char *x = HDva_arg(ap, char*);
n = fprintf(stream, format_templ, x);
}
break;
@@ -399,7 +403,7 @@ HDfprintf(FILE *stream, const char *fmt, ...)
case 't':
{
- htri_t tri_var = va_arg(ap, htri_t);
+ htri_t tri_var = HDva_arg(ap, htri_t);
if(tri_var > 0)
fprintf(stream, "TRUE");
@@ -423,9 +427,10 @@ HDfprintf(FILE *stream, const char *fmt, ...)
nout++;
}
}
- va_end(ap);
+ HDva_end(ap);
return nout;
} /* end HDfprintf() */
+#pragma GCC diagnostic pop
/*-------------------------------------------------------------------------
@@ -492,7 +497,8 @@ HDstrtoll(const char *s, const char **rest, int base)
/* Optional minus or plus sign */
if ('+'==*s) {
s++;
- } else if ('-'==*s) {
+ }
+ else if ('-'==*s) {
sign = -1;
s++;
}
@@ -501,10 +507,12 @@ HDstrtoll(const char *s, const char **rest, int base)
if (0==base && '0'==*s && ('x'==s[1] || 'X'==s[1])) {
base = 16;
s += 2;
- } else if (0==base && '0'==*s) {
+ }
+ else if (0==base && '0'==*s) {
base = 8;
s++;
- } else if (0==base) {
+ }
+ else if (0==base) {
base = 10;
}
@@ -525,7 +533,8 @@ HDstrtoll(const char *s, const char **rest, int base)
if (acc*base+digit < acc) {
overflow = TRUE;
- } else {
+ }
+ else {
acc = acc*base + digit;
}
}
@@ -536,7 +545,8 @@ HDstrtoll(const char *s, const char **rest, int base)
if (overflow) {
if (sign>0) {
acc = ((uint64_t)1<<(8*sizeof(int64_t)-1))-1;
- } else {
+ }
+ else {
acc = (int64_t)((uint64_t)1<<(8*sizeof(int64_t)-1));
}
errno = ERANGE;
@@ -621,7 +631,7 @@ Pflock(int fd, int operation) {
flk.l_pid = 0; /* not used with set */
/* Lock or unlock */
- if(HDfcntl(fd, F_SETLK, flk) < 0)
+ if(HDfcntl(fd, F_SETLK, &flk) < 0)
return -1;
return 0;
@@ -843,9 +853,9 @@ int c99_snprintf(char* str, size_t size, const char* format, ...)
int count;
va_list ap;
- va_start(ap, format);
+ HDva_start(ap, format);
count = c99_vsnprintf(str, size, format, ap);
- va_end(ap);
+ HDva_end(ap);
return count;
}
@@ -980,6 +990,132 @@ Wroundf(float arg)
return (float)(arg < 0.0F ? HDceil(arg - 0.5F) : HDfloor(arg + 0.5F));
}
+/*-------------------------------------------------------------------------
+* Function: H5_get_utf16_str
+*
+* Purpose: Gets a UTF-16 string from an UTF-8 (or ASCII) string.
+*
+* Return: Success: A pointer to a UTF-16 string
+* This must be freed by the caller using H5MM_xfree()
+* Failure: NULL
+*
+* Programmer: Dana Robinson
+* Spring 2019
+*
+*-------------------------------------------------------------------------
+*/
+const wchar_t *
+H5_get_utf16_str(const char *s)
+{
+ int nwchars = -1; /* Length of the UTF-16 buffer */
+ wchar_t *ret_s = NULL; /* UTF-16 version of the string */
+
+ /* Get the number of UTF-16 characters needed */
+ if(0 == (nwchars = MultiByteToWideChar(CP_UTF8, 0, s, -1, NULL, 0)))
+ goto error;
+
+ /* Allocate a buffer for the UTF-16 string */
+ if(NULL == (ret_s = (wchar_t *)H5MM_calloc(sizeof(wchar_t) * (size_t)nwchars)))
+ goto error;
+
+ /* Convert the input UTF-8 string to UTF-16 */
+ if(0 == MultiByteToWideChar(CP_UTF8, 0, s, -1, ret_s, nwchars))
+ goto error;
+
+ return ret_s;
+
+error:
+ if(ret_s)
+ H5MM_xfree((void *)ret_s);
+ return NULL;
+} /* end H5_get_utf16_str() */
+
+/*-------------------------------------------------------------------------
+ * Function: Wopen_utf8
+ *
+ * Purpose: UTF-8 equivalent of open(2) for use on Windows.
+ * Converts a UTF-8 input path to UTF-16 and then opens the
+ * file via _wopen() under the hood
+ *
+ * Return: Success: A POSIX file descriptor
+ * Failure: -1
+ *
+ * Programmer: Dana Robinson
+ * Spring 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+Wopen_utf8(const char *path, int oflag, ...)
+{
+ int fd = -1; /* POSIX file descriptor to be returned */
+ wchar_t *wpath = NULL; /* UTF-16 version of the path */
+ int pmode = 0; /* mode (optionally set via variable args) */
+
+ /* Convert the input UTF-8 path to UTF-16 */
+ if(NULL == (wpath = H5_get_utf16_str(path)))
+ goto done;
+
+ /* _O_BINARY must be set in Windows to avoid CR-LF <-> LF EOL
+ * transformations when performing I/O. Note that this will
+ * produce Unix-style text files, though.
+ */
+ oflag |= _O_BINARY;
+
+ /* Get the mode, if O_CREAT was specified */
+ if(oflag & O_CREAT) {
+ va_list vl;
+
+ HDva_start(vl, oflag);
+ pmode = HDva_arg(vl, int);
+ HDva_end(vl);
+ }
+
+ /* Open the file */
+ fd = _wopen(wpath, oflag, pmode);
+
+done:
+ if(wpath)
+ H5MM_xfree((void *)wpath);
+
+ return fd;
+} /* end Wopen_utf8() */
+
+/*-------------------------------------------------------------------------
+ * Function: Wremove_utf8
+ *
+ * Purpose: UTF-8 equivalent of remove(3) for use on Windows.
+ * Converts a UTF-8 input path to UTF-16 and then opens the
+ * file via _wremove() under the hood
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ * Programmer: Dana Robinson
+ * Spring 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+Wremove_utf8(const char *path)
+{
+ wchar_t *wpath = NULL; /* UTF-16 version of the path */
+ int ret;
+
+ /* Convert the input UTF-8 path to UTF-16 */
+ if(NULL == (wpath = H5_get_utf16_str(path)))
+ goto done;
+
+ /* Open the file */
+ ret = _wremove(wpath);
+
+done:
+ if(wpath)
+ H5MM_xfree((void *)wpath);
+
+ return ret;
+} /* end Wremove_utf8() */
+
#endif /* H5_HAVE_WIN32_API */
@@ -1125,13 +1261,13 @@ H5_combine_path(const char* path1, const char* path2, char **full_name /*out*/)
FUNC_ENTER_NOAPI_NOINIT
- HDassert(path1);
HDassert(path2);
- path1_len = HDstrlen(path1);
+ if(path1)
+ path1_len = HDstrlen(path1);
path2_len = HDstrlen(path2);
- if(*path1 == '\0' || H5_CHECK_ABSOLUTE(path2)) {
+ if(path1 == NULL || *path1 == '\0' || H5_CHECK_ABSOLUTE(path2)) {
/* If path1 is empty or path2 is absolute, simply use path2 */
if(NULL == (*full_name = (char *)H5MM_strdup(path2)))
@@ -1165,11 +1301,11 @@ H5_combine_path(const char* path1, const char* path2, char **full_name /*out*/)
* Allocate a buffer to hold path1 + path2 + possibly the delimiter
* + terminating null byte
*/
- if(NULL == (*full_name = (char *)H5MM_malloc(path1_len + path2_len + 2)))
+ if(NULL == (*full_name = (char *)H5MM_malloc(path1_len + path2_len + 2 + 2))) /* Extra "+2" to quiet GCC warning - 2019/07/05, QAK */
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate filename buffer")
/* Compose the full file name */
- HDsnprintf(*full_name, (path1_len + path2_len + 2), "%s%s%s", path1,
+ HDsnprintf(*full_name, (path1_len + path2_len + 2 + 2), "%s%s%s", path1, /* Extra "+2" to quiet GCC warning - 2019/07/05, QAK */
(H5_CHECK_DELIMITER(path1[path1_len - 1]) ? "" : H5_DIR_SEPS), path2);
} /* end else */
diff --git a/src/H5timer.c b/src/H5timer.c
index 0ba8bd1..4b1ec06 100644
--- a/src/H5timer.c
+++ b/src/H5timer.c
@@ -213,26 +213,26 @@ H5_bandwidth(char *buf/*out*/, double nbytes, double nseconds)
if(H5_DBL_ABS_EQUAL(bw, (double)0.0F))
HDstrcpy(buf, "0.000 B/s");
else if(bw < (double)1.0F)
- sprintf(buf, "%10.4e", bw);
+ HDsprintf(buf, "%10.4e", bw);
else if(bw < (double)H5_KB) {
- sprintf(buf, "%05.4f", bw);
+ HDsprintf(buf, "%05.4f", bw);
HDstrcpy(buf+5, " B/s");
} else if(bw < (double)H5_MB) {
- sprintf(buf, "%05.4f", bw / (double)H5_KB);
+ HDsprintf(buf, "%05.4f", bw / (double)H5_KB);
HDstrcpy(buf+5, " kB/s");
} else if(bw < (double)H5_GB) {
- sprintf(buf, "%05.4f", bw / (double)H5_MB);
+ HDsprintf(buf, "%05.4f", bw / (double)H5_MB);
HDstrcpy(buf+5, " MB/s");
} else if(bw < (double)H5_TB) {
- sprintf(buf, "%05.4f", bw / (double)H5_GB);
+ HDsprintf(buf, "%05.4f", bw / (double)H5_GB);
HDstrcpy(buf+5, " GB/s");
} else if(bw < (double)H5_PB) {
- sprintf(buf, "%05.4f", bw / (double)H5_TB);
+ HDsprintf(buf, "%05.4f", bw / (double)H5_TB);
HDstrcpy(buf+5, " TB/s");
} else {
- sprintf(buf, "%10.4e", bw);
+ HDsprintf(buf, "%10.4e", bw);
if(HDstrlen(buf) > 10)
- sprintf(buf, "%10.3e", bw);
+ HDsprintf(buf, "%10.3e", bw);
}
}
} /* end H5_bandwidth() */
diff --git a/src/H5trace.c b/src/H5trace.c
index eef268c..79dfbc8 100644
--- a/src/H5trace.c
+++ b/src/H5trace.c
@@ -25,7 +25,7 @@
/****************/
/* Module Setup */
/****************/
-#define H5I_FRIEND /*suppress error about including H5Ipkg */
+#define H5I_FRIEND /*suppress error about including H5Ipkg */
/***********/
/* Headers */
@@ -34,8 +34,10 @@
#include "H5Dprivate.h" /* Datasets */
#include "H5Eprivate.h" /* Error handling */
#include "H5FDprivate.h" /* File drivers */
+#include "H5Rprivate.h" /* References */
#include "H5Ipkg.h" /* IDs */
#include "H5MMprivate.h" /* Memory management */
+#include "H5VLprivate.h" /* Virtual Object Layer */
#ifdef H5_HAVE_PARALLEL
/* datatypes of predefined drivers needed by H5_trace() */
@@ -78,7 +80,7 @@
/*******************/
-
+
/*-------------------------------------------------------------------------
* Function: H5_trace
*
@@ -133,8 +135,8 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
/* FUNC_ENTER() should not be called */
if(!out)
- return 0.0F; /*tracing is off*/
- va_start(ap, type);
+ return 0.0F; /*tracing is off*/
+ HDva_start(ap, type);
if(H5_debug_g.ttop) {
if(returning) {
@@ -172,7 +174,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
if(current_depth < last_call_depth) {
/* We are at the beginning of a line */
if(H5_debug_g.ttimes) {
- char tmp[128];
+ char tmp[320];
HDsprintf(tmp, "%.6f", event_time.etime-first_time.etime);
HDfprintf(out, " %*s ", (int)HDstrlen(tmp), "");
@@ -226,7 +228,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
* name is the null pointer then don't print the argument or the
* following `='. This is used for return values.
*/
- argname = va_arg(ap, char *);
+ argname = HDva_arg(ap, char *);
if(argname) {
unsigned n = (unsigned)MAX (0, (int)HDstrlen(argname) - 3);
@@ -242,7 +244,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
/* The value */
if(ptr)
- vp = va_arg(ap, void *);
+ vp = HDva_arg(ap, void *);
switch(type[0]) {
case 'a':
if(ptr) {
@@ -252,7 +254,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- haddr_t addr = va_arg(ap, haddr_t);
+ haddr_t addr = HDva_arg(ap, haddr_t);
HDfprintf(out, "%a", addr);
} /* end else */
@@ -266,8 +268,8 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- /* Can't pass hbool_t to va_arg() */
- hbool_t bool_var = (hbool_t)va_arg(ap, int);
+ /* Can't pass hbool_t to HDva_arg() */
+ hbool_t bool_var = (hbool_t)HDva_arg(ap, int);
if(TRUE == bool_var)
HDfprintf(out, "TRUE");
else if(!bool_var)
@@ -285,7 +287,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- double dbl = va_arg(ap, double);
+ double dbl = HDva_arg(ap, double);
HDfprintf(out, "%g", dbl);
} /* end else */
@@ -301,7 +303,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5D_alloc_time_t alloc_time = (H5D_alloc_time_t)va_arg(ap, int);
+ H5D_alloc_time_t alloc_time = (H5D_alloc_time_t)HDva_arg(ap, int);
switch(alloc_time) {
case H5D_ALLOC_TIME_ERROR:
@@ -339,7 +341,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5FD_mpio_collective_opt_t opt = (H5FD_mpio_collective_opt_t)va_arg(ap, int);
+ H5FD_mpio_collective_opt_t opt = (H5FD_mpio_collective_opt_t)HDva_arg(ap, int);
switch(opt) {
case H5FD_MPIO_COLLECTIVE_IO:
@@ -365,7 +367,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5D_fill_time_t fill_time = (H5D_fill_time_t)va_arg(ap, int);
+ H5D_fill_time_t fill_time = (H5D_fill_time_t)HDva_arg(ap, int);
switch(fill_time) {
case H5D_FILL_TIME_ERROR:
@@ -399,7 +401,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5D_fill_value_t fill_value = (H5D_fill_value_t)va_arg(ap, int);
+ H5D_fill_value_t fill_value = (H5D_fill_value_t)HDva_arg(ap, int);
switch(fill_value) {
case H5D_FILL_VALUE_ERROR:
@@ -433,7 +435,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5FD_mpio_chunk_opt_t opt = (H5FD_mpio_chunk_opt_t)va_arg(ap, int);
+ H5FD_mpio_chunk_opt_t opt = (H5FD_mpio_chunk_opt_t)HDva_arg(ap, int);
switch(opt) {
case H5FD_MPIO_CHUNK_DEFAULT:
@@ -463,7 +465,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5D_mpio_actual_io_mode_t actual_io_mode = (H5D_mpio_actual_io_mode_t)va_arg(ap, int);
+ H5D_mpio_actual_io_mode_t actual_io_mode = (H5D_mpio_actual_io_mode_t)HDva_arg(ap, int);
switch(actual_io_mode) {
case H5D_MPIO_NO_COLLECTIVE:
@@ -501,7 +503,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5D_chunk_index_t idx = (H5D_chunk_index_t)va_arg(ap, int);
+ H5D_chunk_index_t idx = (H5D_chunk_index_t)HDva_arg(ap, int);
switch(idx) {
case H5D_CHUNK_IDX_BTREE:
@@ -547,7 +549,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5D_layout_t layout = (H5D_layout_t)va_arg(ap, int);
+ H5D_layout_t layout = (H5D_layout_t)HDva_arg(ap, int);
switch(layout) {
case H5D_LAYOUT_ERROR:
@@ -589,7 +591,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5D_mpio_no_collective_cause_t nocol_cause_mode = (H5D_mpio_no_collective_cause_t)va_arg(ap, int);
+ H5D_mpio_no_collective_cause_t nocol_cause_mode = (H5D_mpio_no_collective_cause_t)HDva_arg(ap, int);
hbool_t flag_already_displayed = FALSE;
/* Check for all bit-flags which might be set */
@@ -636,7 +638,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5D_mpio_actual_chunk_opt_mode_t chunk_opt_mode = (H5D_mpio_actual_chunk_opt_mode_t)va_arg(ap, int);
+ H5D_mpio_actual_chunk_opt_mode_t chunk_opt_mode = (H5D_mpio_actual_chunk_opt_mode_t)HDva_arg(ap, int);
switch(chunk_opt_mode) {
case H5D_MPIO_NO_CHUNK_OPTIMIZATION:
@@ -666,7 +668,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5D_space_status_t space_status = (H5D_space_status_t)va_arg(ap, int);
+ H5D_space_status_t space_status = (H5D_space_status_t)HDva_arg(ap, int);
switch(space_status) {
case H5D_SPACE_STATUS_NOT_ALLOCATED:
@@ -700,7 +702,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5FD_mpio_xfer_t transfer = (H5FD_mpio_xfer_t)va_arg(ap, int);
+ H5FD_mpio_xfer_t transfer = (H5FD_mpio_xfer_t)HDva_arg(ap, int);
switch(transfer) {
case H5FD_MPIO_INDEPENDENT:
@@ -726,7 +728,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5D_vds_view_t view = (H5D_vds_view_t)va_arg(ap, int);
+ H5D_vds_view_t view = (H5D_vds_view_t)HDva_arg(ap, int);
switch(view) {
case H5D_VDS_ERROR:
@@ -762,11 +764,11 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- herr_t status = va_arg(ap, herr_t);
+ herr_t status = HDva_arg(ap, herr_t);
if(status >= 0)
HDfprintf(out, "SUCCEED");
- else
+ else
HDfprintf(out, "FAIL");
} /* end else */
break;
@@ -781,7 +783,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5E_direction_t direction = (H5E_direction_t)va_arg(ap, int);
+ H5E_direction_t direction = (H5E_direction_t)HDva_arg(ap, int);
switch(direction) {
case H5E_WALK_UPWARD:
@@ -807,12 +809,43 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5E_error2_t *error = va_arg(ap, H5E_error2_t *);
+ H5E_error2_t *error = HDva_arg(ap, H5E_error2_t *);
HDfprintf(out, "0x%lx", (unsigned long)error);
} /* end else */
break;
+ case 's':
+ if(ptr) {
+ if(vp)
+ HDfprintf(out, "0x%lx", (unsigned long)vp);
+ else
+ HDfprintf(out, "NULL");
+ } /* end if */
+ else {
+ H5ES_status_t status = (H5ES_status_t)HDva_arg(ap, int);
+
+ switch(status) {
+ case H5ES_STATUS_IN_PROGRESS:
+ HDfprintf(out, "H5ES_STATUS_IN_PROGRESS");
+ break;
+ case H5ES_STATUS_SUCCEED:
+ HDfprintf(out, "H5ES_STATUS_SUCCEED");
+ break;
+ case H5ES_STATUS_FAIL:
+ HDfprintf(out, "H5ES_STATUS_FAIL");
+ break;
+ case H5ES_STATUS_CANCELED:
+ HDfprintf(out, "H5ES_STATUS_CANCELED");
+ break;
+
+ default:
+ HDfprintf(out, "%ld", (long)status);
+ break;
+ } /* end switch */
+ } /* end else */
+ break;
+
case 't':
if(ptr) {
if(vp)
@@ -821,7 +854,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5E_type_t etype = (H5E_type_t)va_arg(ap, int);
+ H5E_type_t etype = (H5E_type_t)HDva_arg(ap, int);
switch(etype) {
case H5E_MAJOR:
@@ -855,7 +888,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5F_close_degree_t degree = (H5F_close_degree_t)va_arg(ap, int);
+ H5F_close_degree_t degree = (H5F_close_degree_t)HDva_arg(ap, int);
switch(degree) {
case H5F_CLOSE_DEFAULT:
@@ -889,7 +922,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5F_fspace_strategy_t fs_strategy = (H5F_fspace_strategy_t)va_arg(ap, int);
+ H5F_fspace_strategy_t fs_strategy = (H5F_fspace_strategy_t)HDva_arg(ap, int);
switch(fs_strategy) {
case H5F_FSPACE_STRATEGY_FSM_AGGR:
@@ -924,7 +957,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5F_mem_t mem_type = (H5F_mem_t)va_arg(ap, int);
+ H5F_mem_t mem_type = (H5F_mem_t)HDva_arg(ap, int);
switch(mem_type) {
case H5FD_MEM_NOLIST:
@@ -975,7 +1008,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5F_scope_t scope = (H5F_scope_t)va_arg(ap, int);
+ H5F_scope_t scope = (H5F_scope_t)HDva_arg(ap, int);
switch(scope) {
case H5F_SCOPE_LOCAL:
@@ -1010,7 +1043,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5F_libver_t libver_vers = (H5F_libver_t)va_arg(ap, int);
+ H5F_libver_t libver_vers = (H5F_libver_t)HDva_arg(ap, int);
switch(libver_vers) {
case H5F_LIBVER_EARLIEST:
@@ -1022,7 +1055,15 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
break;
case H5F_LIBVER_V110:
- HDcompile_assert(H5F_LIBVER_LATEST == H5F_LIBVER_V110);
+ HDfprintf(out, "H5F_LIBVER_V110");
+ break;
+
+ case H5F_LIBVER_V112:
+ HDfprintf(out, "H5F_LIBVER_V112");
+ break;
+
+ case H5F_LIBVER_V114:
+ HDcompile_assert(H5F_LIBVER_LATEST == H5F_LIBVER_V114);
HDfprintf(out, "H5F_LIBVER_LATEST");
break;
@@ -1052,7 +1093,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5G_obj_t obj_type = (H5G_obj_t)va_arg(ap, int);
+ H5G_obj_t obj_type = (H5G_obj_t)HDva_arg(ap, int);
switch(obj_type) {
case H5G_UNKNOWN:
@@ -1100,7 +1141,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5G_stat_t *statbuf = va_arg(ap, H5G_stat_t*);
+ H5G_stat_t *statbuf = HDva_arg(ap, H5G_stat_t*);
HDfprintf(out, "0x%lx", (unsigned long)statbuf);
}
@@ -1134,7 +1175,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- hsize_t hsize = va_arg(ap, hsize_t);
+ hsize_t hsize = HDva_arg(ap, hsize_t);
if(H5S_UNLIMITED == hsize)
HDfprintf(out, "H5S_UNLIMITED");
@@ -1164,7 +1205,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- hssize_t hssize = va_arg(ap, hssize_t);
+ hssize_t hssize = HDva_arg(ap, hssize_t);
HDfprintf(out, "%Hd", hssize);
asize[argno] = (hssize_t)hssize;
@@ -1185,7 +1226,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- hid_t obj = va_arg(ap, hid_t);
+ hid_t obj = HDva_arg(ap, hid_t);
if(H5P_DEFAULT == obj)
HDfprintf(out, "H5P_DEFAULT");
@@ -1323,14 +1364,18 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "%ld (attr)", (long)obj);
break;
- case H5I_REFERENCE:
- HDfprintf(out, "%ld (reference)", (long)obj);
+ case H5I_MAP:
+ HDfprintf(out, "%ld (map)", (long)obj);
break;
case H5I_VFL:
HDfprintf(out, "%ld (file driver)", (long)obj);
break;
+ case H5I_VOL:
+ HDfprintf(out, "%ld (VOL plugin)", (long)obj);
+ break;
+
case H5I_GENPROP_CLS:
HDfprintf(out, "%ld (genprop class)", (long)obj);
break;
@@ -1351,6 +1396,10 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "%ld (err stack)", (long)obj);
break;
+ case H5I_SPACE_SEL_ITER:
+ HDfprintf(out, "%ld (dataspace selection iterator)", (long)obj);
+ break;
+
case H5I_NTYPES:
HDfprintf (out, "%ld (ntypes - error)", (long)obj);
break;
@@ -1373,7 +1422,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5_index_t idx_type = (H5_index_t)va_arg(ap, int);
+ H5_index_t idx_type = (H5_index_t)HDva_arg(ap, int);
switch(idx_type) {
case H5_INDEX_UNKNOWN:
@@ -1407,7 +1456,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5_iter_order_t order = (H5_iter_order_t)va_arg(ap, int);
+ H5_iter_order_t order = (H5_iter_order_t)HDva_arg(ap, int);
switch(order) {
case H5_ITER_UNKNOWN:
@@ -1454,7 +1503,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- int is = va_arg(ap, int);
+ int is = HDva_arg(ap, int);
HDfprintf (out, "%d", is);
asize[argno] = is;
@@ -1469,7 +1518,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5I_type_t id_type = (H5I_type_t)va_arg(ap, int);
+ H5I_type_t id_type = (H5I_type_t)HDva_arg(ap, int);
switch (id_type) {
case H5I_UNINIT:
@@ -1504,14 +1553,18 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "H5I_ATTR");
break;
- case H5I_REFERENCE:
- HDfprintf(out, "H5I_REFERENCE");
+ case H5I_MAP:
+ HDfprintf(out, "H5I_MAP");
break;
case H5I_VFL:
HDfprintf(out, "H5I_VFL");
break;
+ case H5I_VOL:
+ HDfprintf(out, "H5I_VOL");
+ break;
+
case H5I_GENPROP_CLS:
HDfprintf(out, "H5I_GENPROP_CLS");
break;
@@ -1532,6 +1585,10 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "H5I_ERROR_STACK");
break;
+ case H5I_SPACE_SEL_ITER:
+ HDfprintf(out, "H5I_SPACE_SEL_ITER");
+ break;
+
case H5I_NTYPES:
HDfprintf(out, "H5I_NTYPES");
break;
@@ -1560,7 +1617,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- unsigned iu = va_arg(ap, unsigned);
+ unsigned iu = HDva_arg(ap, unsigned);
HDfprintf(out, "%u", iu);
asize[argno] = iu;
@@ -1583,7 +1640,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5L_type_t link_type = (H5L_type_t)va_arg(ap, int);
+ H5L_type_t link_type = (H5L_type_t)HDva_arg(ap, int);
switch(link_type) {
case H5L_TYPE_ERROR:
@@ -1630,7 +1687,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
} /* end if */
#ifdef H5_HAVE_PARALLEL
else {
- MPI_Comm comm = va_arg(ap, MPI_Comm);
+ MPI_Comm comm = HDva_arg(ap, MPI_Comm);
HDfprintf(out, "%ld", (long)comm);
} /* end else */
@@ -1646,7 +1703,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
} /* end if */
#ifdef H5_HAVE_PARALLEL
else {
- MPI_Info info = va_arg(ap, MPI_Info);
+ MPI_Info info = HDva_arg(ap, MPI_Info);
HDfprintf(out, "%ld", (long)info);
} /* end else */
@@ -1661,7 +1718,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5FD_mem_t mt = (H5FD_mem_t)va_arg(ap, int);
+ H5FD_mem_t mt = (H5FD_mem_t)HDva_arg(ap, int);
switch(mt) {
case H5FD_MEM_NOLIST:
@@ -1720,7 +1777,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- off_t offset = va_arg(ap, off_t);
+ off_t offset = HDva_arg(ap, off_t);
HDfprintf (out, "%ld", (long)offset);
} /* end else */
@@ -1736,7 +1793,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5O_type_t objtype = (H5O_type_t)va_arg(ap, int);
+ H5O_type_t objtype = (H5O_type_t)HDva_arg(ap, int);
switch(objtype) {
case H5O_TYPE_UNKNOWN:
@@ -1755,8 +1812,12 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "H5O_TYPE_NAMED_DATATYPE");
break;
+ case H5O_TYPE_MAP:
+ HDfprintf(out, "H5O_TYPE_MAP");
+ break;
+
case H5O_TYPE_NTYPES:
- HDfprintf(out, "H5O_TYPE_TYPES");
+ HDfprintf(out, "H5O_TYPE_NTYPES");
break;
default:
@@ -1780,7 +1841,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- hid_t pclass_id = va_arg(ap, hid_t);
+ hid_t pclass_id = HDva_arg(ap, hid_t);
char *class_name = NULL;
H5P_genclass_t *pclass;
@@ -1796,22 +1857,51 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
} /* end else */
break;
- case 'r':
- if(ptr) {
- if(vp)
- HDfprintf(out, "0x%lx", (unsigned long)vp);
- else
- HDfprintf(out, "NULL");
- } /* end if */
- else {
- hobj_ref_t ref = va_arg(ap, hobj_ref_t);
-
- HDfprintf(out, "Reference Object=%a", ref);
- } /* end else */
- break;
-
case 'R':
switch(type[1]) {
+
+ case 'o':
+ if(ptr) {
+ if(vp)
+ HDfprintf(out, "0x%lx", (unsigned long)vp);
+ else
+ HDfprintf(out, "NULL");
+ } /* end if */
+ else {
+ hobj_ref_t ref = HDva_arg(ap, hobj_ref_t);
+
+ HDfprintf(out, "Reference Object=%a", ref);
+ } /* end else */
+ break;
+
+ case 'd':
+ if(ptr) {
+ if(vp)
+ HDfprintf(out, "0x%lx", (unsigned long)vp);
+ else
+ HDfprintf(out, "NULL");
+ } /* end if */
+ else {
+ /* Note! region references are array types */
+ HDfprintf(out, "Reference Region");
+ goto error;
+ } /* end else */
+ break;
+
+ case 'r':
+ if(ptr) {
+ if(vp)
+ HDfprintf(out, "0x%lx", (unsigned long)vp);
+ else
+ HDfprintf(out, "NULL");
+ } /* end if */
+ else {
+ /* Note! reference types are opaque types */
+ HDfprintf(out, "Reference Opaque");
+ goto error;
+ } /* end else */
+ break;
+
case 't':
if(ptr) {
if(vp)
@@ -1820,19 +1910,31 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5R_type_t reftype = (H5R_type_t)va_arg(ap, int);
+ H5R_type_t reftype = (H5R_type_t)HDva_arg(ap, int);
switch(reftype) {
case H5R_BADTYPE:
HDfprintf(out, "H5R_BADTYPE");
break;
- case H5R_OBJECT:
- HDfprintf(out, "H5R_OBJECT");
+ case H5R_OBJECT1:
+ HDfprintf(out, "H5R_OBJECT1");
+ break;
+
+ case H5R_DATASET_REGION1:
+ HDfprintf(out, "H5R_DATASET_REGION1");
break;
- case H5R_DATASET_REGION:
- HDfprintf(out, "H5R_DATASET_REGION");
+ case H5R_OBJECT2:
+ HDfprintf(out, "H5R_OBJECT2");
+ break;
+
+ case H5R_DATASET_REGION2:
+ HDfprintf(out, "H5R_DATASET_REGION2");
+ break;
+
+ case H5R_ATTR:
+ HDfprintf(out, "H5R_ATTR");
break;
case H5R_MAXTYPE:
@@ -1862,7 +1964,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5S_class_t cls = (H5S_class_t)va_arg(ap, int);
+ H5S_class_t cls = (H5S_class_t)HDva_arg(ap, int);
switch(cls) {
case H5S_NO_CLASS:
@@ -1896,7 +1998,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5S_seloper_t so = (H5S_seloper_t)va_arg(ap, int);
+ H5S_seloper_t so = (H5S_seloper_t)HDva_arg(ap, int);
switch(so) {
case H5S_SELECT_NOOP:
@@ -1954,7 +2056,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5S_sel_type st = (H5S_sel_type)va_arg(ap, int);
+ H5S_sel_type st = (H5S_sel_type)HDva_arg(ap, int);
switch(st) {
case H5S_SEL_ERROR:
@@ -2002,7 +2104,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- const char *str = va_arg(ap, const char *);
+ const char *str = HDva_arg(ap, const char *);
HDfprintf(out, "\"%s\"", str);
} /* end else */
@@ -2018,7 +2120,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5T_cset_t cset = (H5T_cset_t)va_arg(ap, int);
+ H5T_cset_t cset = (H5T_cset_t)HDva_arg(ap, int);
switch(cset) {
case H5T_CSET_ERROR:
@@ -2065,7 +2167,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5T_direction_t direct = (H5T_direction_t)va_arg(ap, int);
+ H5T_direction_t direct = (H5T_direction_t)HDva_arg(ap, int);
switch(direct) {
case H5T_DIR_DEFAULT:
@@ -2095,7 +2197,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5T_pers_t pers = (H5T_pers_t)va_arg(ap, int);
+ H5T_pers_t pers = (H5T_pers_t)HDva_arg(ap, int);
switch(pers) {
case H5T_PERS_DONTCARE:
@@ -2125,7 +2227,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5T_norm_t norm = (H5T_norm_t)va_arg(ap, int);
+ H5T_norm_t norm = (H5T_norm_t)HDva_arg(ap, int);
switch(norm) {
case H5T_NORM_ERROR:
@@ -2159,7 +2261,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5T_order_t order = (H5T_order_t)va_arg(ap, int);
+ H5T_order_t order = (H5T_order_t)HDva_arg(ap, int);
switch(order) {
case H5T_ORDER_ERROR:
@@ -2201,7 +2303,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5T_pad_t pad = (H5T_pad_t)va_arg(ap, int);
+ H5T_pad_t pad = (H5T_pad_t)HDva_arg(ap, int);
switch(pad) {
case H5T_PAD_ERROR:
@@ -2239,7 +2341,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5T_sign_t sign = (H5T_sign_t)va_arg(ap, int);
+ H5T_sign_t sign = (H5T_sign_t)HDva_arg(ap, int);
switch(sign) {
case H5T_SGN_ERROR:
@@ -2273,7 +2375,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5T_class_t type_class = (H5T_class_t)va_arg(ap, int);
+ H5T_class_t type_class = (H5T_class_t)HDva_arg(ap, int);
switch(type_class) {
case H5T_NO_CLASS:
@@ -2343,7 +2445,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5T_str_t str = (H5T_str_t)va_arg(ap, int);
+ H5T_str_t str = (H5T_str_t)HDva_arg(ap, int);
switch(str) {
case H5T_STR_ERROR:
@@ -2399,7 +2501,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- htri_t tri_var = va_arg (ap, htri_t);
+ htri_t tri_var = HDva_arg (ap, htri_t);
if(tri_var>0)
HDfprintf (out, "TRUE");
@@ -2429,7 +2531,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- unsigned long iul = va_arg(ap, unsigned long);
+ unsigned long iul = HDva_arg(ap, unsigned long);
HDfprintf(out, "%lu", iul);
asize[argno] = (hssize_t)iul;
@@ -2453,7 +2555,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- unsigned long long iull = va_arg(ap, unsigned long long);
+ unsigned long long iull = HDva_arg(ap, unsigned long long);
HDfprintf(out, "%llu", iull);
asize[argno] = (hssize_t)iull;
@@ -2466,6 +2568,517 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
} /* end switch */
break;
+ case 'V':
+ switch(type[1]) {
+ case 'a':
+ if(ptr) {
+ if(vp)
+ HDfprintf (out, "0x%lx", (unsigned long)vp);
+ else
+ HDfprintf(out, "NULL");
+ } /* end if */
+ else {
+ H5VL_attr_get_t get = (H5VL_attr_get_t)HDva_arg(ap, int);
+
+ switch(get) {
+ case H5VL_ATTR_GET_SPACE:
+ HDfprintf(out, "H5VL_ATTR_GET_SPACE");
+ break;
+ case H5VL_ATTR_GET_TYPE:
+ HDfprintf(out, "H5VL_ATTR_GET_TYPE");
+ break;
+ case H5VL_ATTR_GET_ACPL:
+ HDfprintf(out, "H5VL_ATTR_GET_ACPL");
+ break;
+ case H5VL_ATTR_GET_NAME:
+ HDfprintf(out, "H5VL_ATTR_GET_NAME");
+ break;
+ case H5VL_ATTR_GET_STORAGE_SIZE:
+ HDfprintf(out, "H5VL_ATTR_GET_STORAGE_SIZE");
+ break;
+ case H5VL_ATTR_GET_INFO:
+ HDfprintf(out, "H5VL_ATTR_GET_INFO");
+ break;
+ default:
+ HDfprintf(out, "%ld", (long)get);
+ break;
+ } /* end switch */
+ } /* end else */
+ break;
+ case 'b':
+ if(ptr) {
+ if(vp)
+ HDfprintf (out, "0x%lx", (unsigned long)vp);
+ else
+ HDfprintf(out, "NULL");
+ } /* end if */
+ else {
+ H5VL_attr_specific_t specific = (H5VL_attr_specific_t)HDva_arg(ap, int);
+
+ switch(specific) {
+ case H5VL_ATTR_DELETE:
+ HDfprintf(out, "H5VL_ATTR_DELETE");
+ break;
+ case H5VL_ATTR_EXISTS:
+ HDfprintf(out, "H5VL_ATTR_EXISTS");
+ break;
+ case H5VL_ATTR_ITER:
+ HDfprintf(out, "H5VL_ATTR_ITER");
+ break;
+ case H5VL_ATTR_RENAME:
+ HDfprintf(out, "H5VL_ATTR_RENAME");
+ break;
+ default:
+ HDfprintf(out, "%ld", (long)specific);
+ break;
+ } /* end switch */
+ } /* end else */
+ break;
+ case 'B':
+ if(ptr) {
+ if(vp)
+ HDfprintf (out, "0x%lx", (unsigned long)vp);
+ else
+ HDfprintf(out, "NULL");
+ } /* end if */
+ else {
+ H5VL_blob_specific_t specific = (H5VL_blob_specific_t)HDva_arg(ap, int);
+
+ switch(specific) {
+ case H5VL_BLOB_DELETE:
+ HDfprintf(out, "H5VL_BLOB_DELETE");
+ break;
+ case H5VL_BLOB_GETSIZE:
+ HDfprintf(out, "H5VL_BLOB_GETSIZE");
+ break;
+ case H5VL_BLOB_ISNULL:
+ HDfprintf(out, "H5VL_BLOB_ISNULL");
+ break;
+ case H5VL_BLOB_SETNULL:
+ HDfprintf(out, "H5VL_BLOB_SETNULL");
+ break;
+ default:
+ HDfprintf(out, "%ld", (long)specific);
+ break;
+ } /* end switch */
+ } /* end else */
+ break;
+ case 'C':
+ if(ptr) {
+ if(vp)
+ HDfprintf (out, "0x%lx", (unsigned long)vp);
+ else
+ HDfprintf(out, "NULL");
+ } /* end if */
+ else {
+ H5VL_class_value_t class_val = (H5VL_class_value_t)HDva_arg(ap, H5VL_class_value_t);
+
+ if(H5_VOL_NATIVE == class_val)
+ HDfprintf(out, "H5_VOL_NATIVE");
+ else
+ HDfprintf(out, "%ld", (long)class_val);
+ } /* end else */
+ break;
+ case 'c':
+ if(ptr) {
+ if(vp)
+ HDfprintf (out, "0x%lx", (unsigned long)vp);
+ else
+ HDfprintf(out, "NULL");
+ } /* end if */
+ else {
+ H5VL_dataset_get_t get = (H5VL_dataset_get_t)HDva_arg(ap, int);
+
+ switch(get) {
+ case H5VL_DATASET_GET_SPACE:
+ HDfprintf(out, "H5VL_DATASET_GET_SPACE");
+ break;
+ case H5VL_DATASET_GET_SPACE_STATUS:
+ HDfprintf(out, "H5VL_DATASET_GET_SPACE_STATUS");
+ break;
+ case H5VL_DATASET_GET_TYPE:
+ HDfprintf(out, "H5VL_DATASET_GET_TYPE");
+ break;
+ case H5VL_DATASET_GET_DCPL:
+ HDfprintf(out, "H5VL_DATASET_GET_DCPL");
+ break;
+ case H5VL_DATASET_GET_DAPL:
+ HDfprintf(out, "H5VL_DATASET_GET_DAPL");
+ break;
+ case H5VL_DATASET_GET_STORAGE_SIZE:
+ HDfprintf(out, "H5VL_DATASET_GET_STORAGE_SIZE");
+ break;
+ case H5VL_DATASET_GET_OFFSET:
+ HDfprintf(out, "H5VL_DATASET_GET_OFFSET");
+ break;
+ default:
+ HDfprintf(out, "%ld", (long)get);
+ break;
+ } /* end switch */
+ } /* end else */
+ break;
+ case 'd':
+ if(ptr) {
+ if(vp)
+ HDfprintf (out, "0x%lx", (unsigned long)vp);
+ else
+ HDfprintf(out, "NULL");
+ } /* end if */
+ else {
+ H5VL_dataset_specific_t specific = (H5VL_dataset_specific_t)HDva_arg(ap, int);
+
+ switch(specific) {
+ case H5VL_DATASET_SET_EXTENT:
+ HDfprintf(out, "H5VL_DATASET_SET_EXTENT");
+ break;
+ case H5VL_DATASET_FLUSH:
+ HDfprintf(out, "H5VL_DATASET_FLUSH");
+ break;
+ case H5VL_DATASET_REFRESH:
+ HDfprintf(out, "H5VL_DATASET_REFRESH");
+ break;
+ default:
+ HDfprintf(out, "%ld", (long)specific);
+ break;
+ } /* end switch */
+ } /* end else */
+ break;
+ case 'e':
+ if(ptr) {
+ if(vp)
+ HDfprintf (out, "0x%lx", (unsigned long)vp);
+ else
+ HDfprintf(out, "NULL");
+ } /* end if */
+ else {
+ H5VL_datatype_get_t get = (H5VL_datatype_get_t)HDva_arg(ap, int);
+
+ switch(get) {
+ case H5VL_DATATYPE_GET_BINARY:
+ HDfprintf(out, "H5VL_DATATYPE_GET_BINARY");
+ break;
+ case H5VL_DATATYPE_GET_TCPL:
+ HDfprintf(out, "H5VL_DATATYPE_GET_TCPL");
+ break;
+ default:
+ HDfprintf(out, "%ld", (long)get);
+ break;
+ } /* end switch */
+ } /* end else */
+ break;
+ case 'f':
+ if(ptr) {
+ if(vp)
+ HDfprintf (out, "0x%lx", (unsigned long)vp);
+ else
+ HDfprintf(out, "NULL");
+ } /* end if */
+ else {
+ H5VL_datatype_specific_t specific = (H5VL_datatype_specific_t)HDva_arg(ap, int);
+
+ switch(specific) {
+ case H5VL_DATATYPE_FLUSH:
+ HDfprintf(out, "H5VL_DATATYPE_FLUSH");
+ break;
+ case H5VL_DATATYPE_REFRESH:
+ HDfprintf(out, "H5VL_DATATYPE_REFRESH");
+ break;
+ default:
+ HDfprintf(out, "%ld", (long)specific);
+ break;
+ } /* end switch */
+ } /* end else */
+ break;
+ case 'g':
+ if(ptr) {
+ if(vp)
+ HDfprintf (out, "0x%lx", (unsigned long)vp);
+ else
+ HDfprintf(out, "NULL");
+ } /* end if */
+ else {
+ H5VL_file_get_t get = (H5VL_file_get_t)HDva_arg(ap, int);
+
+ switch(get) {
+ case H5VL_FILE_GET_CONT_INFO:
+ HDfprintf(out, "H5VL_FILE_GET_CONT_INFO");
+ break;
+ case H5VL_FILE_GET_FAPL:
+ HDfprintf(out, "H5VL_FILE_GET_FAPL");
+ break;
+ case H5VL_FILE_GET_FCPL:
+ HDfprintf(out, "H5VL_FILE_GET_FCPL");
+ break;
+ case H5VL_FILE_GET_FILENO:
+ HDfprintf(out, "H5VL_FILE_GET_FILENO");
+ break;
+ case H5VL_FILE_GET_INTENT:
+ HDfprintf(out, "H5VL_FILE_GET_INTENT");
+ break;
+ case H5VL_FILE_GET_NAME:
+ HDfprintf(out, "H5VL_FILE_GET_NAME");
+ break;
+ case H5VL_FILE_GET_OBJ_COUNT:
+ HDfprintf(out, "H5VL_FILE_GET_OBJ_COUNT");
+ break;
+ case H5VL_FILE_GET_OBJ_IDS:
+ HDfprintf(out, "H5VL_FILE_GET_OBJ_IDS");
+ break;
+ default:
+ HDfprintf(out, "%ld", (long)get);
+ break;
+ } /* end switch */
+ } /* end else */
+ break;
+ case 'h':
+ if(ptr) {
+ if(vp)
+ HDfprintf (out, "0x%lx", (unsigned long)vp);
+ else
+ HDfprintf(out, "NULL");
+ } /* end if */
+ else {
+ H5VL_file_specific_t specific = (H5VL_file_specific_t)HDva_arg(ap, int);
+
+ switch(specific) {
+ case H5VL_FILE_FLUSH:
+ HDfprintf(out, "H5VL_FILE_FLUSH");
+ break;
+ case H5VL_FILE_REOPEN:
+ HDfprintf(out, "H5VL_FILE_REOPEN");
+ break;
+ case H5VL_FILE_MOUNT:
+ HDfprintf(out, "H5VL_FILE_MOUNT");
+ break;
+ case H5VL_FILE_UNMOUNT:
+ HDfprintf(out, "H5VL_FILE_UNMOUNT");
+ break;
+ case H5VL_FILE_IS_ACCESSIBLE:
+ HDfprintf(out, "H5VL_FILE_IS_ACCESSIBLE");
+ break;
+ case H5VL_FILE_DELETE:
+ HDfprintf(out, "H5VL_FILE_DELETE");
+ break;
+ default:
+ HDfprintf(out, "%ld", (long)specific);
+ break;
+ } /* end switch */
+ } /* end else */
+ break;
+ case 'i':
+ if(ptr) {
+ if(vp)
+ HDfprintf (out, "0x%lx", (unsigned long)vp);
+ else
+ HDfprintf(out, "NULL");
+ } /* end if */
+ else {
+ H5VL_group_get_t get = (H5VL_group_get_t)HDva_arg(ap, int);
+
+ switch(get) {
+ case H5VL_GROUP_GET_GCPL:
+ HDfprintf(out, "H5VL_GROUP_GET_GCPL");
+ break;
+ case H5VL_GROUP_GET_INFO:
+ HDfprintf(out, "H5VL_GROUP_GET_INFO");
+ break;
+ default:
+ HDfprintf(out, "%ld", (long)get);
+ break;
+ } /* end switch */
+ } /* end else */
+ break;
+ case 'j':
+ if(ptr) {
+ if(vp)
+ HDfprintf (out, "0x%lx", (unsigned long)vp);
+ else
+ HDfprintf(out, "NULL");
+ } /* end if */
+ else {
+ H5VL_group_specific_t specific = (H5VL_group_specific_t)HDva_arg(ap, int);
+
+ switch(specific) {
+ case H5VL_GROUP_FLUSH:
+ HDfprintf(out, "H5VL_GROUP_FLUSH");
+ break;
+ case H5VL_GROUP_REFRESH:
+ HDfprintf(out, "H5VL_GROUP_REFRESH");
+ break;
+ default:
+ HDfprintf(out, "%ld", (long)specific);
+ break;
+ } /* end switch */
+ } /* end else */
+ break;
+ case 'k':
+ if(ptr) {
+ if(vp)
+ HDfprintf (out, "0x%lx", (unsigned long)vp);
+ else
+ HDfprintf(out, "NULL");
+ } /* end if */
+ else {
+ H5VL_link_create_type_t create = (H5VL_link_create_type_t)HDva_arg(ap, int);
+
+ switch(create) {
+ case H5VL_LINK_CREATE_HARD:
+ HDfprintf(out, "H5VL_LINK_CREATE_HARD");
+ break;
+ case H5VL_LINK_CREATE_SOFT:
+ HDfprintf(out, "H5VL_LINK_CREATE_SOFT");
+ break;
+ case H5VL_LINK_CREATE_UD:
+ HDfprintf(out, "H5VL_LINK_CREATE_UD");
+ break;
+ default:
+ HDfprintf(out, "%ld", (long)create);
+ break;
+ } /* end switch */
+ } /* end else */
+ break;
+ case 'l':
+ if(ptr) {
+ if(vp)
+ HDfprintf (out, "0x%lx", (unsigned long)vp);
+ else
+ HDfprintf(out, "NULL");
+ } /* end if */
+ else {
+ H5VL_link_get_t get = (H5VL_link_get_t)HDva_arg(ap, int);
+
+ switch(get) {
+ case H5VL_LINK_GET_INFO:
+ HDfprintf(out, "H5VL_LINK_GET_INFO");
+ break;
+ case H5VL_LINK_GET_NAME:
+ HDfprintf(out, "H5VL_LINK_GET_NAME");
+ break;
+ case H5VL_LINK_GET_VAL:
+ HDfprintf(out, "H5VL_LINK_GET_VAL");
+ break;
+ default:
+ HDfprintf(out, "%ld", (long)get);
+ break;
+ } /* end switch */
+ } /* end else */
+ break;
+ case 'm':
+ if(ptr) {
+ if(vp)
+ HDfprintf (out, "0x%lx", (unsigned long)vp);
+ else
+ HDfprintf(out, "NULL");
+ } /* end if */
+ else {
+ H5VL_link_specific_t specific = (H5VL_link_specific_t)HDva_arg(ap, int);
+
+ switch(specific) {
+ case H5VL_LINK_DELETE:
+ HDfprintf(out, "H5VL_LINK_DELETE");
+ break;
+ case H5VL_LINK_EXISTS:
+ HDfprintf(out, "H5VL_LINK_EXISTS");
+ break;
+ case H5VL_LINK_ITER:
+ HDfprintf(out, "H5VL_LINK_ITER");
+ break;
+ default:
+ HDfprintf(out, "%ld", (long)specific);
+ break;
+ } /* end switch */
+ } /* end else */
+ break;
+ case 'n':
+ if(ptr) {
+ if(vp)
+ HDfprintf (out, "0x%lx", (unsigned long)vp);
+ else
+ HDfprintf(out, "NULL");
+ } /* end if */
+ else {
+ H5VL_object_get_t get = (H5VL_object_get_t)HDva_arg(ap, int);
+
+ switch(get) {
+ case H5VL_OBJECT_GET_NAME:
+ HDfprintf(out, "H5VL_OBJECT_GET_NAME");
+ break;
+ case H5VL_OBJECT_GET_TYPE:
+ HDfprintf(out, "H5VL_OBJECT_GET_TYPE");
+ break;
+ default:
+ HDfprintf(out, "%ld", (long)get);
+ break;
+ } /* end switch */
+ } /* end else */
+ break;
+ case 'o':
+ if(ptr) {
+ if(vp)
+ HDfprintf (out, "0x%lx", (unsigned long)vp);
+ else
+ HDfprintf(out, "NULL");
+ } /* end if */
+ else {
+ H5VL_object_specific_t specific = (H5VL_object_specific_t)HDva_arg(ap, int);
+
+ switch(specific) {
+ case H5VL_OBJECT_CHANGE_REF_COUNT:
+ HDfprintf(out, "H5VL_OBJECT_CHANGE_REF_COUNT");
+ break;
+ case H5VL_OBJECT_EXISTS:
+ HDfprintf(out, "H5VL_OBJECT_EXISTS");
+ break;
+ case H5VL_OBJECT_LOOKUP:
+ HDfprintf(out, "H5VL_OBJECT_LOOKUP");
+ break;
+ case H5VL_OBJECT_VISIT:
+ HDfprintf(out, "H5VL_OBJECT_VISIT");
+ break;
+ case H5VL_OBJECT_FLUSH:
+ HDfprintf(out, "H5VL_OBJECT_FLUSH");
+ break;
+ case H5VL_OBJECT_REFRESH:
+ HDfprintf(out, "H5VL_OBJECT_REFRESH");
+ break;
+ default:
+ HDfprintf(out, "%ld", (long)specific);
+ break;
+ } /* end switch */
+ } /* end else */
+ break;
+ case 'r':
+ if(ptr) {
+ if(vp)
+ HDfprintf (out, "0x%lx", (unsigned long)vp);
+ else
+ HDfprintf(out, "NULL");
+ } /* end if */
+ else {
+ H5VL_request_specific_t specific = (H5VL_request_specific_t)HDva_arg(ap, int);
+
+ switch(specific) {
+ case H5VL_REQUEST_WAITANY:
+ HDfprintf(out, "H5VL_REQUEST_WAITANY");
+ break;
+ case H5VL_REQUEST_WAITSOME:
+ HDfprintf(out, "H5VL_REQUEST_WAITSOME");
+ break;
+ case H5VL_REQUEST_WAITALL:
+ HDfprintf(out, "H5VL_REQUEST_WAITALL");
+ break;
+ default:
+ HDfprintf(out, "%ld", (long)specific);
+ break;
+ } /* end switch */
+ } /* end else */
+ break;
+ default:
+ HDfprintf(out, "BADTYPE(Z%c)", type[1]);
+ goto error;
+ } /* end switch */
+ break;
+
case 'x':
if(ptr) {
if(vp) {
@@ -2487,7 +3100,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- vp = va_arg (ap, void *);
+ vp = HDva_arg (ap, void *);
if(vp)
HDfprintf(out, "0x%lx", (unsigned long)vp);
@@ -2513,7 +3126,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- size_t size = va_arg(ap, size_t);
+ size_t size = HDva_arg(ap, size_t);
HDfprintf(out, "%Zu", size);
asize[argno] = (hssize_t)size;
@@ -2530,7 +3143,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5Z_SO_scale_type_t scale_type = (H5Z_SO_scale_type_t)va_arg(ap, int);
+ H5Z_SO_scale_type_t scale_type = (H5Z_SO_scale_type_t)HDva_arg(ap, int);
switch(scale_type) {
case H5Z_SO_FLOAT_DSCALE:
@@ -2560,7 +3173,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5Z_class2_t *filter = va_arg(ap, H5Z_class2_t*);
+ H5Z_class2_t *filter = HDva_arg(ap, H5Z_class2_t*);
HDfprintf(out, "0x%lx", (unsigned long)filter);
} /* end else */
@@ -2574,7 +3187,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5Z_EDC_t edc = (H5Z_EDC_t)va_arg(ap, int);
+ H5Z_EDC_t edc = (H5Z_EDC_t)HDva_arg(ap, int);
if(H5Z_DISABLE_EDC == edc)
HDfprintf(out, "H5Z_DISABLE_EDC");
@@ -2593,7 +3206,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- H5Z_filter_t id = va_arg(ap, H5Z_filter_t);
+ H5Z_filter_t id = HDva_arg(ap, H5Z_filter_t);
if(H5Z_FILTER_DEFLATE == id)
HDfprintf(out, "H5Z_FILTER_DEFLATE");
@@ -2619,7 +3232,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "NULL");
} /* end if */
else {
- ssize_t ssize = va_arg(ap, ssize_t);
+ ssize_t ssize = HDva_arg(ap, ssize_t);
HDfprintf(out, "%Zd", ssize);
asize[argno] = (hssize_t)ssize;
@@ -2647,7 +3260,7 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
(event_time.etime - *returning));
error:
- va_end(ap);
+ HDva_end(ap);
if(returning)
HDfprintf(out, ";\n");
else {
diff --git a/src/H5vers.txt b/src/H5vers.txt
index 914c30e..22117c3 100644
--- a/src/H5vers.txt
+++ b/src/H5vers.txt
@@ -61,12 +61,14 @@ FUNCTION: H5Oget_info_by_name; ; v18, v112
FUNCTION: H5Oget_info_by_idx; ; v18, v112
FUNCTION: H5Ovisit; ; v18, v112
FUNCTION: H5Ovisit_by_name; ; v18, v112
+FUNCTION: H5Pencode; ; v110, v112
FUNCTION: H5Pget_filter; ; v10, v18
FUNCTION: H5Pget_filter_by_id; ; v16, v18
FUNCTION: H5Pinsert; ; v14, v18
FUNCTION: H5Pregister; ; v14, v18
FUNCTION: H5Rdereference; ; v10, v110
FUNCTION: H5Rget_obj_type; ; v16, v18
+FUNCTION: H5Sencode; ; v18, v112
FUNCTION: H5Tarray_create; ; v14, v18
FUNCTION: H5Tcommit; ; v10, v18
FUNCTION: H5Tget_array_dims; ; v14, v18
diff --git a/src/H5win32defs.h b/src/H5win32defs.h
index 4522228..29533dd 100644
--- a/src/H5win32defs.h
+++ b/src/H5win32defs.h
@@ -34,6 +34,7 @@ typedef __int64 h5_stat_size_t;
#define HDaccess(F,M) _access(F,M)
#define HDchdir(S) _chdir(S)
#define HDclose(F) _close(F)
+#define HDcreat(S,M) Wopen_utf8(S,O_CREAT|O_TRUNC|O_RDWR,M)
#define HDdup(F) _dup(F)
#define HDfdopen(N,S) _fdopen(N,S)
#define HDfileno(F) _fileno(F)
@@ -47,21 +48,24 @@ typedef __int64 h5_stat_size_t;
#define HDmkdir(S,M) _mkdir(S)
#define HDnanosleep(N, O) Wnanosleep(N, O)
#define HDoff_t __int64
-/* _O_BINARY must be set in Windows to avoid CR-LF <-> LF EOL
- * transformations when performing I/O. Note that this will
- * produce Unix-style text files, though.
- *
- * Also note that the variadic macro is using a VC++ extension
+
+/* Note that the variadic HDopen macro is using a VC++ extension
* where the comma is dropped if nothing is passed to the ellipsis.
*/
-#define HDopen(S,F,...) _open(S, F | _O_BINARY, __VA_ARGS__)
+#ifndef H5_HAVE_MINGW
+#define HDopen(S,F,...) Wopen_utf8(S,F,__VA_ARGS__)
+#else
+#define HDopen(S,F,...) Wopen_utf8(S,F,##__VA_ARGS__)
+#endif
#define HDread(F,M,Z) _read(F,M,Z)
+#define HDremove(S) Wremove_utf8(S)
#define HDrmdir(S) _rmdir(S)
#define HDsetvbuf(F,S,M,Z) setvbuf(F,S,M,(Z>1?Z:2))
#define HDsleep(S) Sleep(S*1000)
#define HDstat(S,B) _stati64(S,B)
#define HDstrcasecmp(A,B) _stricmp(A,B)
#define HDstrdup(S) _strdup(S)
+#define HDstrtok_r(X,Y,Z) strtok_s(X,Y,Z)
#define HDtzset() _tzset()
#define HDunlink(S) _unlink(S)
#define HDwrite(F,M,Z) _write(F,M,Z)
@@ -75,6 +79,11 @@ typedef __int64 h5_stat_size_t;
#ifndef H5_HAVE_STRTOULL
#define HDstrtoull(S,R,N) _strtoui64(S,R,N)
#endif /* H5_HAVE_STRTOULL */
+ /* va_copy() does not exist on pre-2013 Visual Studio. Since va_lists are
+ * just pointers into the stack in those CRTs, the usual work-around
+ * is to just define the operation as a pointer copy.
+ */
+ #define HDva_copy(D,S) ((D) = (S))
#endif /* MSC_VER < 1800 */
/*
@@ -120,6 +129,9 @@ extern "C" {
H5_DLL int c99_vsnprintf(char* str, size_t size, const char* format, va_list ap);
H5_DLL int Wnanosleep(const struct timespec *req, struct timespec *rem);
H5_DLL herr_t H5_expand_windows_env_vars(char **env_var);
+ H5_DLL const wchar_t *H5_get_utf16_str(const char *s);
+ H5_DLL int Wopen_utf8(const char *path, int oflag, ...);
+ H5_DLL int Wremove_utf8(const char *path);
/* Round functions only needed for VS2012 and earlier.
* They are always built to ensure they don't go stale and
diff --git a/src/Makefile.am b/src/Makefile.am
index 9fd3c1d..7d430dd 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -40,12 +40,12 @@ DISTCLEANFILES=H5pubconf.h
# library sources
libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \
H5A.c H5Abtree2.c H5Adense.c H5Adeprec.c H5Aint.c H5Atest.c \
- H5AC.c H5ACdbg.c H5AClog.c H5ACproxy_entry.c \
+ H5AC.c H5ACdbg.c H5ACproxy_entry.c \
H5B.c H5Bcache.c H5Bdbg.c \
H5B2.c H5B2cache.c H5B2dbg.c H5B2hdr.c H5B2int.c H5B2internal.c \
H5B2leaf.c H5B2stat.c H5B2test.c \
- H5C.c H5Cdbg.c H5Cepoch.c H5Cimage.c H5Clog.c H5Cprefetched.c \
- H5Cquery.c H5Ctag.c H5Ctest.c \
+ H5C.c H5Cdbg.c H5Cepoch.c H5Cimage.c H5Clog.c H5Clog_json.c H5Clog_trace.c \
+ H5Cprefetched.c H5Cquery.c H5Ctag.c H5Ctest.c \
H5CS.c \
H5CX.c \
H5D.c H5Dbtree.c H5Dbtree2.c H5Dchunk.c H5Dcompact.c H5Dcontig.c H5Ddbg.c \
@@ -62,8 +62,12 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \
H5Fsfile.c H5Fspace.c H5Fsuper.c H5Fsuper_cache.c H5Ftest.c \
H5FA.c H5FAcache.c H5FAdbg.c H5FAdblock.c H5FAdblkpage.c H5FAhdr.c \
H5FAint.c H5FAstat.c H5FAtest.c \
- H5FD.c H5FDcore.c \
- H5FDfamily.c H5FDint.c H5FDlog.c H5FDvfd_swmr.c \
+ H5FD.c H5FDcore.c \
+ H5FDfamily.c \
+ H5FDhdfs.c \
+ H5FDint.c \
+ H5FDlog.c \
+ H5FDvfd_swmr.c \
H5FDmulti.c H5FDsec2.c H5FDspace.c H5FDstdio.c H5FDtest.c \
H5FL.c H5FO.c H5FS.c H5FScache.c H5FSdbg.c H5FSint.c H5FSsection.c \
H5FSstat.c H5FStest.c \
@@ -78,13 +82,14 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \
H5HG.c H5HGcache.c H5HGdbg.c H5HGquery.c \
H5HL.c H5HLcache.c H5HLdbg.c H5HLint.c H5HLprfx.c H5HLdblk.c\
H5HP.c H5I.c H5Itest.c H5L.c H5Lexternal.c H5lib_settings.c \
+ H5M.c \
H5MF.c H5MFaggr.c H5MFdbg.c H5MFsection.c \
H5MV.c H5MVsection.c \
H5MM.c H5MP.c H5MPtest.c \
H5O.c H5Odeprec.c H5Oainfo.c H5Oalloc.c H5Oattr.c \
H5Oattribute.c H5Obogus.c H5Obtreek.c H5Ocache.c H5Ocache_image.c \
H5Ochunk.c \
- H5Ocont.c H5Ocopy.c H5Odbg.c H5Odrvinfo.c H5Odtype.c H5Oefl.c \
+ H5Ocont.c H5Ocopy.c H5Ocopy_ref.c H5Odbg.c H5Odrvinfo.c H5Odtype.c H5Oefl.c \
H5Ofill.c H5Oflush.c H5Ofsinfo.c H5Oginfo.c \
H5Oint.c H5Olayout.c \
H5Olinfo.c H5Olink.c H5Omessage.c H5Omtime.c \
@@ -96,14 +101,15 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \
H5P.c H5Pacpl.c H5Pdapl.c H5Pdcpl.c \
H5Pdeprec.c H5Pdxpl.c H5Pencdec.c \
H5Pfapl.c H5Pfcpl.c H5Pfmpl.c \
- H5Pgcpl.c H5Pint.c \
- H5Plapl.c H5Plcpl.c H5Pocpl.c H5Pocpypl.c H5Pstrcpl.c H5Ptest.c \
+ H5Pgcpl.c H5Pint.c H5Plapl.c H5Plcpl.c \
+ H5Pmapl.c H5Pmcpl.c H5Pocpl.c H5Pocpypl.c H5Pstrcpl.c \
+ H5Ptest.c \
H5PB.c \
H5PL.c H5PLint.c H5PLpath.c H5PLplugin_cache.c \
H5R.c H5Rint.c H5Rdeprec.c \
H5UC.c \
H5RS.c \
- H5S.c H5Sall.c H5Sdbg.c H5Shyper.c H5Snone.c H5Spoint.c \
+ H5S.c H5Sall.c H5Sdbg.c H5Sdeprec.c H5Shyper.c H5Snone.c H5Spoint.c \
H5Sselect.c H5Stest.c \
H5SL.c \
H5SM.c H5SMbtree2.c H5SMcache.c H5SMmessage.c H5SMtest.c \
@@ -114,14 +120,20 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \
H5Tfloat.c H5Tinit.c H5Tnative.c H5Toffset.c H5Toh.c \
H5Topaque.c \
H5Torder.c \
+ H5Tref.c \
H5Tpad.c H5Tprecis.c H5Tstrpad.c H5Tvisit.c H5Tvlen.c H5TS.c \
+ H5VL.c H5VLcallback.c H5VLint.c H5VLnative.c \
+ H5VLnative_attr.c H5VLnative_blob.c H5VLnative_dataset.c \
+ H5VLnative_datatype.c H5VLnative_file.c H5VLnative_group.c \
+ H5VLnative_link.c H5VLnative_object.c \
+ H5VLpassthru.c \
H5VM.c H5WB.c H5Z.c \
H5Zdeflate.c H5Zfletcher32.c H5Znbit.c H5Zshuffle.c \
H5Zscaleoffset.c H5Zszip.c H5Ztrans.c
# Only compile parallel sources if necessary
if BUILD_PARALLEL_CONDITIONAL
- libhdf5_la_SOURCES += H5ACmpio.c H5Cmpio.c H5Dmpio.c H5Fmpi.c H5FDmpi.c H5FDmpio.c H5Smpio.c
+ libhdf5_la_SOURCES += H5mpi.c H5ACmpio.c H5Cmpio.c H5Dmpio.c H5Fmpi.c H5FDmpi.c H5FDmpio.c H5Smpio.c
endif
# Only compile the direct VFD if necessary
@@ -129,18 +141,27 @@ if DIRECT_VFD_CONDITIONAL
libhdf5_la_SOURCES += H5FDdirect.c
endif
+# Only compile the read-only S3 VFD if necessary
+if ROS3_VFD_CONDITIONAL
+ libhdf5_la_SOURCES += H5FDros3.c H5FDs3comms.c
+endif
+
# Public headers
include_HEADERS = hdf5.h H5api_adpt.h H5overflow.h H5pubconf.h H5public.h H5version.h \
H5Apublic.h H5ACpublic.h \
H5Cpublic.h H5Dpublic.h \
- H5Epubgen.h H5Epublic.h H5Fpublic.h \
+ H5Epubgen.h H5Epublic.h H5ESpublic.h H5Fpublic.h \
H5FDpublic.h H5FDcore.h H5FDdirect.h \
- H5FDfamily.h H5FDlog.h H5FDmpi.h H5FDmpio.h \
- H5FDmulti.h H5FDsec2.h H5FDstdio.h H5FDvfd_swmr.h \
+ H5FDfamily.h H5FDhdfs.h H5FDlog.h H5FDmpi.h H5FDmpio.h \
+ H5FDmulti.h H5FDros3.h H5FDsec2.h H5FDstdio.h \
+ H5FDvfd_swmr.h \
+ H5FDwindows.h \
H5Gpublic.h H5Ipublic.h H5Lpublic.h \
- H5MMpublic.h H5Opublic.h H5Ppublic.h \
+ H5Mpublic.h H5MMpublic.h H5Opublic.h H5Ppublic.h \
H5PLextern.h H5PLpublic.h \
H5Rpublic.h H5Spublic.h H5Tpublic.h \
+ H5VLconnector.h H5VLconnector_passthru.h \
+ H5VLnative.h H5VLpassthru.h H5VLpublic.h \
H5Zpublic.h
# install libhdf5.settings in lib directory
@@ -206,3 +227,4 @@ trace: $(libhdf5_la_SOURCES)
done
include $(top_srcdir)/config/conclude.am
+
diff --git a/src/bsdqueue.h b/src/bsdqueue.h
new file mode 100644
index 0000000..816acca
--- /dev/null
+++ b/src/bsdqueue.h
@@ -0,0 +1,847 @@
+/* $NetBSD: queue.h,v 1.70.10.1 2017/10/02 13:21:41 martin Exp $ */
+
+/*
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)queue.h 8.5 (Berkeley) 8/20/94
+ */
+
+#ifndef _SYS_QUEUE_H_
+#define _SYS_QUEUE_H_
+
+/*
+ * This file defines five types of data structures: singly-linked lists,
+ * lists, simple queues, tail queues, and circular queues.
+ *
+ * A singly-linked list is headed by a single forward pointer. The
+ * elements are singly linked for minimum space and pointer manipulation
+ * overhead at the expense of O(n) removal for arbitrary elements. New
+ * elements can be added to the list after an existing element or at the
+ * head of the list. Elements being removed from the head of the list
+ * should use the explicit macro for this purpose for optimum
+ * efficiency. A singly-linked list may only be traversed in the forward
+ * direction. Singly-linked lists are ideal for applications with large
+ * datasets and few or no removals or for implementing a LIFO queue.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ *
+ * A simple queue is headed by a pair of pointers, one the head of the
+ * list and the other to the tail of the list. The elements are singly
+ * linked to save space, so elements can only be removed from the
+ * head of the list. New elements can be added to the list after
+ * an existing element, at the head of the list, or at the end of the
+ * list. A simple queue may only be traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ *
+ * A circle queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or after
+ * an existing element, at the head of the list, or at the end of the list.
+ * A circle queue may be traversed in either direction, but has a more
+ * complex end of list detection.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ */
+
+/*
+ * Include the definition of NULL only on NetBSD because sys/null.h
+ * is not available elsewhere. This conditional makes the header
+ * portable and it can simply be dropped verbatim into any system.
+ * The caveat is that on other systems some other header
+ * must provide NULL before the macros can be used.
+ */
+#ifdef __NetBSD__
+#include <sys/null.h>
+#endif
+
+#if defined(QUEUEDEBUG)
+# if defined(_KERNEL)
+# define QUEUEDEBUG_ABORT(...) panic(__VA_ARGS__)
+# else
+# include <err.h>
+# define QUEUEDEBUG_ABORT(...) err(1, __VA_ARGS__)
+# endif
+#endif
+
+/*
+ * Singly-linked List definitions.
+ */
+#define SLIST_HEAD(name, type) \
+struct name { \
+ struct type *slh_first; /* first element */ \
+}
+
+#define SLIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define SLIST_ENTRY(type) \
+struct { \
+ struct type *sle_next; /* next element */ \
+}
+
+/*
+ * Singly-linked List access methods.
+ */
+#define SLIST_FIRST(head) ((head)->slh_first)
+#define SLIST_END(head) NULL
+#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
+#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
+
+#define SLIST_FOREACH(var, head, field) \
+ for((var) = (head)->slh_first; \
+ (var) != SLIST_END(head); \
+ (var) = (var)->field.sle_next)
+
+#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = SLIST_FIRST((head)); \
+ (var) != SLIST_END(head) && \
+ ((tvar) = SLIST_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+/*
+ * Singly-linked List functions.
+ */
+#define SLIST_INIT(head) do { \
+ (head)->slh_first = SLIST_END(head); \
+} while (/*CONSTCOND*/0)
+
+#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
+ (elm)->field.sle_next = (slistelm)->field.sle_next; \
+ (slistelm)->field.sle_next = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define SLIST_INSERT_HEAD(head, elm, field) do { \
+ (elm)->field.sle_next = (head)->slh_first; \
+ (head)->slh_first = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define SLIST_REMOVE_AFTER(slistelm, field) do { \
+ (slistelm)->field.sle_next = \
+ SLIST_NEXT(SLIST_NEXT((slistelm), field), field); \
+} while (/*CONSTCOND*/0)
+
+#define SLIST_REMOVE_HEAD(head, field) do { \
+ (head)->slh_first = (head)->slh_first->field.sle_next; \
+} while (/*CONSTCOND*/0)
+
+#define SLIST_REMOVE(head, elm, type, field) do { \
+ if ((head)->slh_first == (elm)) { \
+ SLIST_REMOVE_HEAD((head), field); \
+ } \
+ else { \
+ struct type *curelm = (head)->slh_first; \
+ while(curelm->field.sle_next != (elm)) \
+ curelm = curelm->field.sle_next; \
+ curelm->field.sle_next = \
+ curelm->field.sle_next->field.sle_next; \
+ } \
+} while (/*CONSTCOND*/0)
+
+
+/*
+ * List definitions.
+ */
+#define LIST_HEAD(name, type) \
+struct name { \
+ struct type *lh_first; /* first element */ \
+}
+
+#define LIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define LIST_ENTRY(type) \
+struct { \
+ struct type *le_next; /* next element */ \
+ struct type **le_prev; /* address of previous next element */ \
+}
+
+/*
+ * List access methods.
+ */
+#define LIST_FIRST(head) ((head)->lh_first)
+#define LIST_END(head) NULL
+#define LIST_EMPTY(head) ((head)->lh_first == LIST_END(head))
+#define LIST_NEXT(elm, field) ((elm)->field.le_next)
+
+#define LIST_FOREACH(var, head, field) \
+ for ((var) = ((head)->lh_first); \
+ (var) != LIST_END(head); \
+ (var) = ((var)->field.le_next))
+
+#define LIST_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = LIST_FIRST((head)); \
+ (var) != LIST_END(head) && \
+ ((tvar) = LIST_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#define LIST_MOVE(head1, head2, field) do { \
+ LIST_INIT((head2)); \
+ if (!LIST_EMPTY((head1))) { \
+ (head2)->lh_first = (head1)->lh_first; \
+ (head2)->lh_first->field.le_prev = &(head2)->lh_first; \
+ LIST_INIT((head1)); \
+ } \
+} while (/*CONSTCOND*/0)
+
+/*
+ * List functions.
+ */
+#if defined(QUEUEDEBUG)
+#define QUEUEDEBUG_LIST_INSERT_HEAD(head, elm, field) \
+ if ((head)->lh_first && \
+ (head)->lh_first->field.le_prev != &(head)->lh_first) \
+ QUEUEDEBUG_ABORT("LIST_INSERT_HEAD %p %s:%d", (head), \
+ __FILE__, __LINE__);
+#define QUEUEDEBUG_LIST_OP(elm, field) \
+ if ((elm)->field.le_next && \
+ (elm)->field.le_next->field.le_prev != \
+ &(elm)->field.le_next) \
+ QUEUEDEBUG_ABORT("LIST_* forw %p %s:%d", (elm), \
+ __FILE__, __LINE__); \
+ if (*(elm)->field.le_prev != (elm)) \
+ QUEUEDEBUG_ABORT("LIST_* back %p %s:%d", (elm), \
+ __FILE__, __LINE__);
+#define QUEUEDEBUG_LIST_POSTREMOVE(elm, field) \
+ (elm)->field.le_next = (void *)1L; \
+ (elm)->field.le_prev = (void *)1L;
+#else
+#define QUEUEDEBUG_LIST_INSERT_HEAD(head, elm, field)
+#define QUEUEDEBUG_LIST_OP(elm, field)
+#define QUEUEDEBUG_LIST_POSTREMOVE(elm, field)
+#endif
+
+#define LIST_INIT(head) do { \
+ (head)->lh_first = LIST_END(head); \
+} while (/*CONSTCOND*/0)
+
+#define LIST_INSERT_AFTER(listelm, elm, field) do { \
+ QUEUEDEBUG_LIST_OP((listelm), field) \
+ if (((elm)->field.le_next = (listelm)->field.le_next) != \
+ LIST_END(head)) \
+ (listelm)->field.le_next->field.le_prev = \
+ &(elm)->field.le_next; \
+ (listelm)->field.le_next = (elm); \
+ (elm)->field.le_prev = &(listelm)->field.le_next; \
+} while (/*CONSTCOND*/0)
+
+#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
+ QUEUEDEBUG_LIST_OP((listelm), field) \
+ (elm)->field.le_prev = (listelm)->field.le_prev; \
+ (elm)->field.le_next = (listelm); \
+ *(listelm)->field.le_prev = (elm); \
+ (listelm)->field.le_prev = &(elm)->field.le_next; \
+} while (/*CONSTCOND*/0)
+
+#define LIST_INSERT_HEAD(head, elm, field) do { \
+ QUEUEDEBUG_LIST_INSERT_HEAD((head), (elm), field) \
+ if (((elm)->field.le_next = (head)->lh_first) != LIST_END(head))\
+ (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
+ (head)->lh_first = (elm); \
+ (elm)->field.le_prev = &(head)->lh_first; \
+} while (/*CONSTCOND*/0)
+
+#define LIST_REMOVE(elm, field) do { \
+ QUEUEDEBUG_LIST_OP((elm), field) \
+ if ((elm)->field.le_next != NULL) \
+ (elm)->field.le_next->field.le_prev = \
+ (elm)->field.le_prev; \
+ *(elm)->field.le_prev = (elm)->field.le_next; \
+ QUEUEDEBUG_LIST_POSTREMOVE((elm), field) \
+} while (/*CONSTCOND*/0)
+
+#define LIST_REPLACE(elm, elm2, field) do { \
+ if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \
+ (elm2)->field.le_next->field.le_prev = \
+ &(elm2)->field.le_next; \
+ (elm2)->field.le_prev = (elm)->field.le_prev; \
+ *(elm2)->field.le_prev = (elm2); \
+ QUEUEDEBUG_LIST_POSTREMOVE((elm), field) \
+} while (/*CONSTCOND*/0)
+
+/*
+ * Simple queue definitions.
+ */
+#define SIMPLEQ_HEAD(name, type) \
+struct name { \
+ struct type *sqh_first; /* first element */ \
+ struct type **sqh_last; /* addr of last next element */ \
+}
+
+#define SIMPLEQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).sqh_first }
+
+#define SIMPLEQ_ENTRY(type) \
+struct { \
+ struct type *sqe_next; /* next element */ \
+}
+
+/*
+ * Simple queue access methods.
+ */
+#define SIMPLEQ_FIRST(head) ((head)->sqh_first)
+#define SIMPLEQ_END(head) NULL
+#define SIMPLEQ_EMPTY(head) ((head)->sqh_first == SIMPLEQ_END(head))
+#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
+
+#define SIMPLEQ_FOREACH(var, head, field) \
+ for ((var) = ((head)->sqh_first); \
+ (var) != SIMPLEQ_END(head); \
+ (var) = ((var)->field.sqe_next))
+
+#define SIMPLEQ_FOREACH_SAFE(var, head, field, next) \
+ for ((var) = ((head)->sqh_first); \
+ (var) != SIMPLEQ_END(head) && \
+ ((next = ((var)->field.sqe_next)), 1); \
+ (var) = (next))
+
+/*
+ * Simple queue functions.
+ */
+#define SIMPLEQ_INIT(head) do { \
+ (head)->sqh_first = NULL; \
+ (head)->sqh_last = &(head)->sqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+ (head)->sqh_first = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.sqe_next = NULL; \
+ *(head)->sqh_last = (elm); \
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+ (listelm)->field.sqe_next = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_REMOVE_HEAD(head, field) do { \
+ if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
+ (head)->sqh_last = &(head)->sqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_REMOVE_AFTER(head, elm, field) do { \
+ if (((elm)->field.sqe_next = (elm)->field.sqe_next->field.sqe_next) \
+ == NULL) \
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_REMOVE(head, elm, type, field) do { \
+ if ((head)->sqh_first == (elm)) { \
+ SIMPLEQ_REMOVE_HEAD((head), field); \
+ } else { \
+ struct type *curelm = (head)->sqh_first; \
+ while (curelm->field.sqe_next != (elm)) \
+ curelm = curelm->field.sqe_next; \
+ if ((curelm->field.sqe_next = \
+ curelm->field.sqe_next->field.sqe_next) == NULL) \
+ (head)->sqh_last = &(curelm)->field.sqe_next; \
+ } \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_CONCAT(head1, head2) do { \
+ if (!SIMPLEQ_EMPTY((head2))) { \
+ *(head1)->sqh_last = (head2)->sqh_first; \
+ (head1)->sqh_last = (head2)->sqh_last; \
+ SIMPLEQ_INIT((head2)); \
+ } \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_LAST(head, type, field) \
+ (SIMPLEQ_EMPTY((head)) ? \
+ NULL : \
+ ((struct type *)(void *) \
+ ((char *)((head)->sqh_last) - offsetof(struct type, field))))
+
+/*
+ * Tail queue definitions.
+ */
+#define _TAILQ_HEAD(name, type, qual) \
+struct name { \
+ qual type *tqh_first; /* first element */ \
+ qual type *qual *tqh_last; /* addr of last next element */ \
+}
+#define TAILQ_HEAD(name, type) _TAILQ_HEAD(name, struct type,)
+
+#define TAILQ_HEAD_INITIALIZER(head) \
+ { TAILQ_END(head), &(head).tqh_first }
+
+#define _TAILQ_ENTRY(type, qual) \
+struct { \
+ qual type *tqe_next; /* next element */ \
+ qual type *qual *tqe_prev; /* address of previous next element */\
+}
+#define TAILQ_ENTRY(type) _TAILQ_ENTRY(struct type,)
+
+/*
+ * Tail queue access methods.
+ */
+#define TAILQ_FIRST(head) ((head)->tqh_first)
+#define TAILQ_END(head) (NULL)
+#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+#define TAILQ_LAST(head, headname) \
+ (*(((struct headname *)(void *)((head)->tqh_last))->tqh_last))
+#define TAILQ_PREV(elm, headname, field) \
+ (*(((struct headname *)(void *)((elm)->field.tqe_prev))->tqh_last))
+#define TAILQ_EMPTY(head) (TAILQ_FIRST(head) == TAILQ_END(head))
+
+
+#define TAILQ_FOREACH(var, head, field) \
+ for ((var) = ((head)->tqh_first); \
+ (var) != TAILQ_END(head); \
+ (var) = ((var)->field.tqe_next))
+
+#define TAILQ_FOREACH_SAFE(var, head, field, next) \
+ for ((var) = ((head)->tqh_first); \
+ (var) != TAILQ_END(head) && \
+ ((next) = TAILQ_NEXT(var, field), 1); (var) = (next))
+
+#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
+ for ((var) = TAILQ_LAST((head), headname); \
+ (var) != TAILQ_END(head); \
+ (var) = TAILQ_PREV((var), headname, field))
+
+#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, prev) \
+ for ((var) = TAILQ_LAST((head), headname); \
+ (var) != TAILQ_END(head) && \
+ ((prev) = TAILQ_PREV((var), headname, field), 1); (var) = (prev))
+
+/*
+ * Tail queue functions.
+ */
+#if defined(QUEUEDEBUG)
+#define QUEUEDEBUG_TAILQ_INSERT_HEAD(head, elm, field) \
+ if ((head)->tqh_first && \
+ (head)->tqh_first->field.tqe_prev != &(head)->tqh_first) \
+ QUEUEDEBUG_ABORT("TAILQ_INSERT_HEAD %p %s:%d", (head), \
+ __FILE__, __LINE__);
+#define QUEUEDEBUG_TAILQ_INSERT_TAIL(head, elm, field) \
+ if (*(head)->tqh_last != NULL) \
+ QUEUEDEBUG_ABORT("TAILQ_INSERT_TAIL %p %s:%d", (head), \
+ __FILE__, __LINE__);
+#define QUEUEDEBUG_TAILQ_OP(elm, field) \
+ if ((elm)->field.tqe_next && \
+ (elm)->field.tqe_next->field.tqe_prev != \
+ &(elm)->field.tqe_next) \
+ QUEUEDEBUG_ABORT("TAILQ_* forw %p %s:%d", (elm), \
+ __FILE__, __LINE__); \
+ if (*(elm)->field.tqe_prev != (elm)) \
+ QUEUEDEBUG_ABORT("TAILQ_* back %p %s:%d", (elm), \
+ __FILE__, __LINE__);
+#define QUEUEDEBUG_TAILQ_PREREMOVE(head, elm, field) \
+ if ((elm)->field.tqe_next == NULL && \
+ (head)->tqh_last != &(elm)->field.tqe_next) \
+ QUEUEDEBUG_ABORT("TAILQ_PREREMOVE head %p elm %p %s:%d",\
+ (head), (elm), __FILE__, __LINE__);
+#define QUEUEDEBUG_TAILQ_POSTREMOVE(elm, field) \
+ (elm)->field.tqe_next = (void *)1L; \
+ (elm)->field.tqe_prev = (void *)1L;
+#else
+#define QUEUEDEBUG_TAILQ_INSERT_HEAD(head, elm, field)
+#define QUEUEDEBUG_TAILQ_INSERT_TAIL(head, elm, field)
+#define QUEUEDEBUG_TAILQ_OP(elm, field)
+#define QUEUEDEBUG_TAILQ_PREREMOVE(head, elm, field)
+#define QUEUEDEBUG_TAILQ_POSTREMOVE(elm, field)
+#endif
+
+#define TAILQ_INIT(head) do { \
+ (head)->tqh_first = TAILQ_END(head); \
+ (head)->tqh_last = &(head)->tqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_INSERT_HEAD(head, elm, field) do { \
+ QUEUEDEBUG_TAILQ_INSERT_HEAD((head), (elm), field) \
+ if (((elm)->field.tqe_next = (head)->tqh_first) != TAILQ_END(head))\
+ (head)->tqh_first->field.tqe_prev = \
+ &(elm)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+ (head)->tqh_first = (elm); \
+ (elm)->field.tqe_prev = &(head)->tqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_INSERT_TAIL(head, elm, field) do { \
+ QUEUEDEBUG_TAILQ_INSERT_TAIL((head), (elm), field) \
+ (elm)->field.tqe_next = TAILQ_END(head); \
+ (elm)->field.tqe_prev = (head)->tqh_last; \
+ *(head)->tqh_last = (elm); \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ QUEUEDEBUG_TAILQ_OP((listelm), field) \
+ if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != \
+ TAILQ_END(head)) \
+ (elm)->field.tqe_next->field.tqe_prev = \
+ &(elm)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+ (listelm)->field.tqe_next = (elm); \
+ (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
+ QUEUEDEBUG_TAILQ_OP((listelm), field) \
+ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
+ (elm)->field.tqe_next = (listelm); \
+ *(listelm)->field.tqe_prev = (elm); \
+ (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_REMOVE(head, elm, field) do { \
+ QUEUEDEBUG_TAILQ_PREREMOVE((head), (elm), field) \
+ QUEUEDEBUG_TAILQ_OP((elm), field) \
+ if (((elm)->field.tqe_next) != TAILQ_END(head)) \
+ (elm)->field.tqe_next->field.tqe_prev = \
+ (elm)->field.tqe_prev; \
+ else \
+ (head)->tqh_last = (elm)->field.tqe_prev; \
+ *(elm)->field.tqe_prev = (elm)->field.tqe_next; \
+ QUEUEDEBUG_TAILQ_POSTREMOVE((elm), field); \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_REPLACE(head, elm, elm2, field) do { \
+ if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != \
+ TAILQ_END(head)) \
+ (elm2)->field.tqe_next->field.tqe_prev = \
+ &(elm2)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm2)->field.tqe_next; \
+ (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \
+ *(elm2)->field.tqe_prev = (elm2); \
+ QUEUEDEBUG_TAILQ_POSTREMOVE((elm), field); \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_CONCAT(head1, head2, field) do { \
+ if (!TAILQ_EMPTY(head2)) { \
+ *(head1)->tqh_last = (head2)->tqh_first; \
+ (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
+ (head1)->tqh_last = (head2)->tqh_last; \
+ TAILQ_INIT((head2)); \
+ } \
+} while (/*CONSTCOND*/0)
+
+/*
+ * Singly-linked Tail queue declarations.
+ */
+#define STAILQ_HEAD(name, type) \
+struct name { \
+ struct type *stqh_first; /* first element */ \
+ struct type **stqh_last; /* addr of last next element */ \
+}
+
+#define STAILQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).stqh_first }
+
+#define STAILQ_ENTRY(type) \
+struct { \
+ struct type *stqe_next; /* next element */ \
+}
+
+/*
+ * Singly-linked Tail queue access methods.
+ */
+#define STAILQ_FIRST(head) ((head)->stqh_first)
+#define STAILQ_END(head) NULL
+#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
+#define STAILQ_EMPTY(head) (STAILQ_FIRST(head) == STAILQ_END(head))
+
+/*
+ * Singly-linked Tail queue functions.
+ */
+#define STAILQ_INIT(head) do { \
+ (head)->stqh_first = NULL; \
+ (head)->stqh_last = &(head)->stqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define STAILQ_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.stqe_next = (head)->stqh_first) == NULL) \
+ (head)->stqh_last = &(elm)->field.stqe_next; \
+ (head)->stqh_first = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define STAILQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.stqe_next = NULL; \
+ *(head)->stqh_last = (elm); \
+ (head)->stqh_last = &(elm)->field.stqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define STAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if (((elm)->field.stqe_next = (listelm)->field.stqe_next) == NULL)\
+ (head)->stqh_last = &(elm)->field.stqe_next; \
+ (listelm)->field.stqe_next = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define STAILQ_REMOVE_HEAD(head, field) do { \
+ if (((head)->stqh_first = (head)->stqh_first->field.stqe_next) == NULL) \
+ (head)->stqh_last = &(head)->stqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define STAILQ_REMOVE(head, elm, type, field) do { \
+ if ((head)->stqh_first == (elm)) { \
+ STAILQ_REMOVE_HEAD((head), field); \
+ } else { \
+ struct type *curelm = (head)->stqh_first; \
+ while (curelm->field.stqe_next != (elm)) \
+ curelm = curelm->field.stqe_next; \
+ if ((curelm->field.stqe_next = \
+ curelm->field.stqe_next->field.stqe_next) == NULL) \
+ (head)->stqh_last = &(curelm)->field.stqe_next; \
+ } \
+} while (/*CONSTCOND*/0)
+
+#define STAILQ_FOREACH(var, head, field) \
+ for ((var) = ((head)->stqh_first); \
+ (var); \
+ (var) = ((var)->field.stqe_next))
+
+#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = STAILQ_FIRST((head)); \
+ (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#define STAILQ_CONCAT(head1, head2) do { \
+ if (!STAILQ_EMPTY((head2))) { \
+ *(head1)->stqh_last = (head2)->stqh_first; \
+ (head1)->stqh_last = (head2)->stqh_last; \
+ STAILQ_INIT((head2)); \
+ } \
+} while (/*CONSTCOND*/0)
+
+#define STAILQ_LAST(head, type, field) \
+ (STAILQ_EMPTY((head)) ? \
+ NULL : \
+ ((struct type *)(void *) \
+ ((char *)((head)->stqh_last) - offsetof(struct type, field))))
+
+
+#ifndef _KERNEL
+/*
+ * Circular queue definitions. Do not use. We still keep the macros
+ * for compatibility but because of pointer aliasing issues their use
+ * is discouraged!
+ */
+
+/*
+ * __launder_type(): We use this ugly hack to work around the the compiler
+ * noticing that two types may not alias each other and elide tests in code.
+ * We hit this in the CIRCLEQ macros when comparing 'struct name *' and
+ * 'struct type *' (see CIRCLEQ_HEAD()). Modern compilers (such as GCC
+ * 4.8) declare these comparisons as always false, causing the code to
+ * not run as designed.
+ *
+ * This hack is only to be used for comparisons and thus can be fully const.
+ * Do not use for assignment.
+ *
+ * If we ever choose to change the ABI of the CIRCLEQ macros, we could fix
+ * this by changing the head/tail sentinal values, but see the note above
+ * this one.
+ */
+static __inline const void * __launder_type(const void *);
+static __inline const void *
+__launder_type(const void *__x)
+{
+ __asm __volatile("" : "+r" (__x));
+ return __x;
+}
+
+#if defined(QUEUEDEBUG)
+#define QUEUEDEBUG_CIRCLEQ_HEAD(head, field) \
+ if ((head)->cqh_first != CIRCLEQ_ENDC(head) && \
+ (head)->cqh_first->field.cqe_prev != CIRCLEQ_ENDC(head)) \
+ QUEUEDEBUG_ABORT("CIRCLEQ head forw %p %s:%d", (head), \
+ __FILE__, __LINE__); \
+ if ((head)->cqh_last != CIRCLEQ_ENDC(head) && \
+ (head)->cqh_last->field.cqe_next != CIRCLEQ_ENDC(head)) \
+ QUEUEDEBUG_ABORT("CIRCLEQ head back %p %s:%d", (head), \
+ __FILE__, __LINE__);
+#define QUEUEDEBUG_CIRCLEQ_ELM(head, elm, field) \
+ if ((elm)->field.cqe_next == CIRCLEQ_ENDC(head)) { \
+ if ((head)->cqh_last != (elm)) \
+ QUEUEDEBUG_ABORT("CIRCLEQ elm last %p %s:%d", \
+ (elm), __FILE__, __LINE__); \
+ } else { \
+ if ((elm)->field.cqe_next->field.cqe_prev != (elm)) \
+ QUEUEDEBUG_ABORT("CIRCLEQ elm forw %p %s:%d", \
+ (elm), __FILE__, __LINE__); \
+ } \
+ if ((elm)->field.cqe_prev == CIRCLEQ_ENDC(head)) { \
+ if ((head)->cqh_first != (elm)) \
+ QUEUEDEBUG_ABORT("CIRCLEQ elm first %p %s:%d", \
+ (elm), __FILE__, __LINE__); \
+ } else { \
+ if ((elm)->field.cqe_prev->field.cqe_next != (elm)) \
+ QUEUEDEBUG_ABORT("CIRCLEQ elm prev %p %s:%d", \
+ (elm), __FILE__, __LINE__); \
+ }
+#define QUEUEDEBUG_CIRCLEQ_POSTREMOVE(elm, field) \
+ (elm)->field.cqe_next = (void *)1L; \
+ (elm)->field.cqe_prev = (void *)1L;
+#else
+#define QUEUEDEBUG_CIRCLEQ_HEAD(head, field)
+#define QUEUEDEBUG_CIRCLEQ_ELM(head, elm, field)
+#define QUEUEDEBUG_CIRCLEQ_POSTREMOVE(elm, field)
+#endif
+
+#define CIRCLEQ_HEAD(name, type) \
+struct name { \
+ struct type *cqh_first; /* first element */ \
+ struct type *cqh_last; /* last element */ \
+}
+
+#define CIRCLEQ_HEAD_INITIALIZER(head) \
+ { CIRCLEQ_END(&head), CIRCLEQ_END(&head) }
+
+#define CIRCLEQ_ENTRY(type) \
+struct { \
+ struct type *cqe_next; /* next element */ \
+ struct type *cqe_prev; /* previous element */ \
+}
+
+/*
+ * Circular queue functions.
+ */
+#define CIRCLEQ_INIT(head) do { \
+ (head)->cqh_first = CIRCLEQ_END(head); \
+ (head)->cqh_last = CIRCLEQ_END(head); \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \
+ QUEUEDEBUG_CIRCLEQ_ELM((head), (listelm), field) \
+ (elm)->field.cqe_next = (listelm)->field.cqe_next; \
+ (elm)->field.cqe_prev = (listelm); \
+ if ((listelm)->field.cqe_next == CIRCLEQ_ENDC(head)) \
+ (head)->cqh_last = (elm); \
+ else \
+ (listelm)->field.cqe_next->field.cqe_prev = (elm); \
+ (listelm)->field.cqe_next = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
+ QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \
+ QUEUEDEBUG_CIRCLEQ_ELM((head), (listelm), field) \
+ (elm)->field.cqe_next = (listelm); \
+ (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
+ if ((listelm)->field.cqe_prev == CIRCLEQ_ENDC(head)) \
+ (head)->cqh_first = (elm); \
+ else \
+ (listelm)->field.cqe_prev->field.cqe_next = (elm); \
+ (listelm)->field.cqe_prev = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
+ QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \
+ (elm)->field.cqe_next = (head)->cqh_first; \
+ (elm)->field.cqe_prev = CIRCLEQ_END(head); \
+ if ((head)->cqh_last == CIRCLEQ_ENDC(head)) \
+ (head)->cqh_last = (elm); \
+ else \
+ (head)->cqh_first->field.cqe_prev = (elm); \
+ (head)->cqh_first = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
+ QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \
+ (elm)->field.cqe_next = CIRCLEQ_END(head); \
+ (elm)->field.cqe_prev = (head)->cqh_last; \
+ if ((head)->cqh_first == CIRCLEQ_ENDC(head)) \
+ (head)->cqh_first = (elm); \
+ else \
+ (head)->cqh_last->field.cqe_next = (elm); \
+ (head)->cqh_last = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_REMOVE(head, elm, field) do { \
+ QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \
+ QUEUEDEBUG_CIRCLEQ_ELM((head), (elm), field) \
+ if ((elm)->field.cqe_next == CIRCLEQ_ENDC(head)) \
+ (head)->cqh_last = (elm)->field.cqe_prev; \
+ else \
+ (elm)->field.cqe_next->field.cqe_prev = \
+ (elm)->field.cqe_prev; \
+ if ((elm)->field.cqe_prev == CIRCLEQ_ENDC(head)) \
+ (head)->cqh_first = (elm)->field.cqe_next; \
+ else \
+ (elm)->field.cqe_prev->field.cqe_next = \
+ (elm)->field.cqe_next; \
+ QUEUEDEBUG_CIRCLEQ_POSTREMOVE((elm), field) \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_FOREACH(var, head, field) \
+ for ((var) = ((head)->cqh_first); \
+ (var) != CIRCLEQ_ENDC(head); \
+ (var) = ((var)->field.cqe_next))
+
+#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
+ for ((var) = ((head)->cqh_last); \
+ (var) != CIRCLEQ_ENDC(head); \
+ (var) = ((var)->field.cqe_prev))
+
+/*
+ * Circular queue access methods.
+ */
+#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
+#define CIRCLEQ_LAST(head) ((head)->cqh_last)
+/* For comparisons */
+#define CIRCLEQ_ENDC(head) (__launder_type(head))
+/* For assignments */
+#define CIRCLEQ_END(head) ((void *)(head))
+#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
+#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
+#define CIRCLEQ_EMPTY(head) \
+ (CIRCLEQ_FIRST(head) == CIRCLEQ_ENDC(head))
+
+#define CIRCLEQ_LOOP_NEXT(head, elm, field) \
+ (((elm)->field.cqe_next == CIRCLEQ_ENDC(head)) \
+ ? ((head)->cqh_first) \
+ : (elm->field.cqe_next))
+#define CIRCLEQ_LOOP_PREV(head, elm, field) \
+ (((elm)->field.cqe_prev == CIRCLEQ_ENDC(head)) \
+ ? ((head)->cqh_last) \
+ : (elm->field.cqe_prev))
+#endif /* !_KERNEL */
+
+#endif /* !_SYS_QUEUE_H_ */
diff --git a/src/hdf5.h b/src/hdf5.h
index 7fb3895..244bfb4 100644
--- a/src/hdf5.h
+++ b/src/hdf5.h
@@ -29,6 +29,7 @@
#include "H5Gpublic.h" /* Groups */
#include "H5Ipublic.h" /* ID management */
#include "H5Lpublic.h" /* Links */
+#include "H5Mpublic.h" /* Maps */
#include "H5MMpublic.h" /* Memory management */
#include "H5Opublic.h" /* Object headers */
#include "H5Ppublic.h" /* Property lists */
@@ -36,20 +37,27 @@
#include "H5Rpublic.h" /* References */
#include "H5Spublic.h" /* Dataspaces */
#include "H5Tpublic.h" /* Datatypes */
+#include "H5VLpublic.h" /* Virtual Object Layer */
#include "H5Zpublic.h" /* Data filters */
/* Predefined file drivers */
-#include "H5FDcore.h" /* Files stored entirely in memory */
-#include "H5FDdirect.h" /* Linux direct I/O */
-#include "H5FDfamily.h" /* File families */
+#include "H5FDcore.h" /* Files stored entirely in memory */
+#include "H5FDdirect.h" /* Linux direct I/O */
+#include "H5FDfamily.h" /* File families */
+#include "H5FDhdfs.h" /* Hadoop HDFS */
#include "H5FDlog.h" /* sec2 driver with I/O logging (for debugging) */
-#include "H5FDmpi.h" /* MPI-based file drivers */
-#include "H5FDmulti.h" /* Usage-partitioned file family */
-#include "H5FDsec2.h" /* POSIX unbuffered file I/O */
-#include "H5FDstdio.h" /* Standard C buffered I/O */
-#include "H5FDvfd_swmr.h" /* VFD SWMR reader VFD */
+#include "H5FDmpi.h" /* MPI-based file drivers */
+#include "H5FDmulti.h" /* Usage-partitioned file family */
+#include "H5FDros3.h" /* R/O S3 "file" I/O */
+#include "H5FDsec2.h" /* POSIX unbuffered file I/O */
+#include "H5FDstdio.h" /* Standard C buffered I/O */
+#include "H5FDvfd_swmr.h" /* VFD SWMR reader VFD */
#ifdef H5_HAVE_WINDOWS
-#include "H5FDwindows.h" /* Win32 I/O */
+#include "H5FDwindows.h" /* Win32 I/O */
#endif
+/* Virtual object layer (VOL) connectors */
+#include "H5VLnative.h" /* Native VOL connector */
+#include "H5VLpassthru.h" /* Pass-through VOL connector */
+
#endif
diff --git a/src/libhdf5.settings.in b/src/libhdf5.settings.in
index 531cd00..1591bed 100644
--- a/src/libhdf5.settings.in
+++ b/src/libhdf5.settings.in
@@ -71,18 +71,22 @@ Features:
Parallel Filtered Dataset Writes: @PARALLEL_FILTERED_WRITES@
Large Parallel I/O: @LARGE_PARALLEL_IO@
High-level library: @HDF5_HL@
+ Build HDF5 Tests: @HDF5_TESTS@
+ Build HDF5 Tools: @HDF5_TOOLS@
Threadsafety: @THREADSAFE@
Default API mapping: @DEFAULT_API_VERSION@
With deprecated public symbols: @DEPRECATED_SYMBOLS@
I/O filters (external): @EXTERNAL_FILTERS@
MPE: @MPE@
+ Map (H5M) API: @MAP_API@
Direct VFD: @DIRECT_VFD@
+ (Read-Only) S3 VFD: @ROS3_VFD@
+ (Read-Only) HDFS VFD: @HAVE_LIBHDFS@
dmalloc: @HAVE_DMALLOC@
Packages w/ extra debug output: @INTERNAL_DEBUG_OUTPUT@
API tracing: @TRACE_API@
Using memory checker: @USINGMEMCHECKER@
Memory allocation sanity checks: @MEMORYALLOCSANITYCHECK@
- Metadata trace file: @METADATATRACEFILE@
Function stack tracing: @CODESTACK@
Strict file format checks: @STRICT_FORMAT_CHECKS@
Optimization instrumentation: @INSTRUMENT_LIBRARY@