summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt15
-rw-r--r--src/H5CX.c148
-rw-r--r--src/H5CXprivate.h5
-rw-r--r--src/H5Dio.c18
-rw-r--r--src/H5Dmpio.c110
-rw-r--r--src/H5Dprivate.h8
-rw-r--r--src/H5FDmpio.c125
-rw-r--r--src/H5Obogus.c4
-rw-r--r--src/H5Ocache.c17
-rw-r--r--src/H5Omessage.c25
-rw-r--r--src/H5Opkg.h2
-rw-r--r--src/H5Oprivate.h5
-rw-r--r--src/H5Pdxpl.c3
-rw-r--r--src/H5Ppublic.h3
-rw-r--r--src/H5T.c106
-rw-r--r--src/H5Tprivate.h1
16 files changed, 369 insertions, 226 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 40b64f5..ff7402b 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -943,6 +943,21 @@ if (BUILD_SHARED_LIBS)
file (MAKE_DIRECTORY "${HDF5_BINARY_DIR}/shared")
endif ()
+if (LOCAL_BATCH_TEST)
+ 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}>")
diff --git a/src/H5CX.c b/src/H5CX.c
index ec18e14..0d20132 100644
--- a/src/H5CX.c
+++ b/src/H5CX.c
@@ -198,7 +198,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 mpio_Proc0_BCast; /* Whether a dataset meets read-proc0-and-bcast requirements */
+ hbool_t rank0_bcast; /* Whether a dataset meets read-with-rank0-and-bcast requirements */
#endif /* H5_HAVE_PARALLEL */
/* Cached DXPL properties */
@@ -262,6 +262,8 @@ 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 */
@@ -1255,6 +1257,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 */
@@ -1610,33 +1638,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5CX_get_mpio_Proc0_BCast
- *
- * Purpose: Retrieves if the dataset meets read-proc0-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_Proc0_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.mpio_Proc0_BCast)
-
-} /* end H5CX_get_mpio_Proc0_BCast() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5CX_get_mpio_chunk_opt_mode
*
* Purpose: Retrieves the collective chunk optimization mode for the current API call context.
@@ -2213,6 +2214,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 */
@@ -2420,34 +2449,6 @@ H5CX_set_mpio_global_no_coll_cause(uint32_t mpio_global_no_coll_cause)
FUNC_LEAVE_NOAPI_VOID
} /* end H5CX_set_mpio_global_no_coll_cause() */
-
-/*-------------------------------------------------------------------------
- * Function: H5CX_set_mpio_Proc0_BCast
- *
- * Purpose: Sets if the dataset meets read-proc0-and-bcast requirements for the current API call context.
- *
- * Return: <none>
- *
- * Programmer: M. Breitenfeld
- * December 31, 2018
- *
- *-------------------------------------------------------------------------
- */
-void
-H5CX_set_mpio_Proc0_BCast(hbool_t mpio_Proc0_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.mpio_Proc0_BCast = mpio_Proc0_BCast;
-
- FUNC_LEAVE_NOAPI_VOID
-} /* end H5CX_set_mpio_Proc0_BCast */
-
#ifdef H5_HAVE_INSTRUMENTED_LIBRARY
/*-------------------------------------------------------------------------
@@ -2652,6 +2653,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 */
@@ -2696,6 +2731,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 */
diff --git a/src/H5CXprivate.h b/src/H5CXprivate.h
index 22c6ebe..46d25d0 100644
--- a/src/H5CXprivate.h
+++ b/src/H5CXprivate.h
@@ -77,7 +77,7 @@ H5_DLL H5AC_ring_t H5CX_get_ring(void);
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_Proc0_BCast(void);
+H5_DLL hbool_t H5CX_get_mpio_rank0_bcast(void);
#endif /* H5_HAVE_PARALLEL */
/* "Getter" routines for DXPL properties cached in API context */
@@ -113,6 +113,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 */
@@ -131,7 +132,6 @@ H5_DLL void H5CX_set_mpio_actual_chunk_opt(H5D_mpio_actual_chunk_opt_mode_t chun
H5_DLL void H5CX_set_mpio_actual_io_mode(H5D_mpio_actual_io_mode_t actual_io_mode);
H5_DLL void H5CX_set_mpio_local_no_coll_cause(uint32_t mpio_local_no_coll_cause);
H5_DLL void H5CX_set_mpio_global_no_coll_cause(uint32_t mpio_global_no_coll_cause);
-H5_DLL void H5CX_set_mpio_Proc0_BCast(hbool_t mpio_Proc0_BCast);
#ifdef H5_HAVE_INSTRUMENTED_LIBRARY
H5_DLL herr_t H5CX_test_set_mpio_coll_chunk_link_hard(int mpio_coll_chunk_link_hard);
H5_DLL herr_t H5CX_test_set_mpio_coll_chunk_multi_hard(int mpio_coll_chunk_multi_hard);
@@ -139,6 +139,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/H5Dio.c b/src/H5Dio.c
index fe85d23..6062dff 100644
--- a/src/H5Dio.c
+++ b/src/H5Dio.c
@@ -657,22 +657,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. */
+ if(H5F_HAS_FEATURE(dataset->oloc.file, H5FD_FEAT_HAS_MPI)) {
+ /* If MPI based VFD is used, no VL or region reference datatype support yet. */
/* This is because they use the global heap in the file and we don't */
/* support parallel access of that yet */
- if(H5T_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. */
- /* 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 */
diff --git a/src/H5Dmpio.c b/src/H5Dmpio.c
index 8850c59..f5da33d 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 */
@@ -83,20 +82,26 @@
/* Macros to represent the regularity of the selection for multiple chunk IO case. */
#define H5D_CHUNK_SELECT_REG 1
-/* Macros for reasons to not enable read-proc-and-bcast. */
-#define H5D_MPIO_PROC0_BCAST 0x00
-#define H5D_MPIO_NOT_H5S_ALL 0x01
-#define H5D_MPIO_GREATER_THAN_2GB 0x02
/******************/
/* Local Typedefs */
/******************/
/* 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
@@ -285,11 +290,11 @@ 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[2] = {0,H5D_MPIO_PROC0_BCAST}; /* [0] Local reason(s) for breaking collective mode */
- /* [1] Flag if dataset is both: H5S_ALL and small */
- unsigned global_cause[2] = {0,H5D_MPIO_PROC0_BCAST}; /* 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 */
- hbool_t H5FD_MPIO_Proc0_BCast; /* Flag if dataset is both: H5S_ALL and < 2GB */
FUNC_ENTER_PACKAGE
@@ -302,7 +307,8 @@ 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[0] |= H5D_MPIO_SET_INDEPENDENT;
@@ -346,34 +352,56 @@ 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)
+ 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
- H5FD_MPIO_Proc0_BCast = FALSE;
- /* Check to see if all the processes are reading the same data */
- if((H5S_GET_SELECT_TYPE(file_space) != H5S_SEL_ALL)) {
- /* Flag to do a MPI_Bcast of the data from one proc instead of
- * having all the processes involved in the persistent I/O.
- */
- local_cause[1] |= H5D_MPIO_NOT_H5S_ALL;
- }
+ /* 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 */
- /* 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 persistent I/O.
- */
+ /* 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;
- hsize_t dset_storage_size;
- H5D__get_storage_size(io_info->dset, &dset_storage_size);
+ /* Determine dataset size */
+ dset_size = ((hsize_t)snelmts) * type_size;
- if(dset_storage_size > ((hsize_t)(H5_2GB) - 1) ) {
- local_cause[1] |= H5D_MPIO_GREATER_THAN_2GB;
- }
- }
+ /* 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[0] & H5D_MPIO_SET_INDEPENDENT)
@@ -386,23 +414,23 @@ H5D__mpio_opt_possible(const H5D_io_info_t *io_info, const H5S_t *file_space,
*/
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[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] > 0 ? FALSE : TRUE;
- /* read-proc0-and-bcast if collective and H5S_ALL */
- if(global_cause[0] == 0 && global_cause[1] == H5D_MPIO_PROC0_BCAST)
- H5FD_MPIO_Proc0_BCast = TRUE;
-
- /* Set Flag if dataset is both: H5S_ALL and < 2GB in the API context */
- H5CX_set_mpio_Proc0_BCast(H5FD_MPIO_Proc0_BCast);
-
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5D__mpio_opt_possible() */
diff --git a/src/H5Dprivate.h b/src/H5Dprivate.h
index aaa3db2..6fb7889 100644
--- a/src/H5Dprivate.h
+++ b/src/H5Dprivate.h
@@ -95,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 */
diff --git a/src/H5FDmpio.c b/src/H5FDmpio.c
index 911a5b6..3ab90aa 100644
--- a/src/H5FDmpio.c
+++ b/src/H5FDmpio.c
@@ -1336,28 +1336,6 @@ static herr_t
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*/)
{
-<<<<<<< HEAD
- 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 = 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 = 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;
- hbool_t Proc0_BCast_enabled = FALSE; /* If read-proc0-and-bcast option was used */
- herr_t ret_value = SUCCEED;
-=======
H5FD_mpio_t *file = (H5FD_mpio_t*)_file;
MPI_Offset mpi_off;
MPI_Status mpi_stat; /* Status from I/O operation */
@@ -1376,19 +1354,14 @@ H5FD__mpio_read(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type,
int n;
#endif
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;
->>>>>>> 7bf6d847ae36940f1b1147820356795c7764dbeb
FUNC_ENTER_STATIC
#ifdef H5FDmpio_DEBUG
-<<<<<<< HEAD
- 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);
->>>>>>> 7bf6d847ae36940f1b1147820356795c7764dbeb
#endif
/* Sanity checks */
@@ -1407,14 +1380,8 @@ H5FD__mpio_read(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type,
HGOTO_ERROR(H5E_INTERNAL, H5E_BADRANGE, FAIL, "can't convert from size to size_i")
#ifdef H5FDmpio_DEBUG
-<<<<<<< HEAD
- 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);
->>>>>>> 7bf6d847ae36940f1b1147820356795c7764dbeb
#endif
/* Only look for MPI views for raw data transfers */
@@ -1431,11 +1398,7 @@ 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).
*/
-<<<<<<< HEAD
- if(xfer_mode==H5FD_MPIO_COLLECTIVE) {
-=======
if(xfer_mode == H5FD_MPIO_COLLECTIVE) {
->>>>>>> 7bf6d847ae36940f1b1147820356795c7764dbeb
MPI_Datatype file_type;
/* Remember that views are used */
@@ -1463,13 +1426,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
-<<<<<<< HEAD
- 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);
->>>>>>> 7bf6d847ae36940f1b1147820356795c7764dbeb
#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)
@@ -1480,23 +1438,25 @@ H5FD__mpio_read(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type,
if(H5FD_mpio_Debug[(int)'r'])
HDfprintf(stdout, "%s: doing MPI collective IO\n", FUNC);
#endif
- if(H5CX_get_mpio_Proc0_BCast()) {
+ /* 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)'t'])
- fprintf(stdout, "H5FD_mpio_read: doing Proc0-read-and-MPI_Bcast\n");
+ if(H5FD_mpio_Debug[(int)'r'])
+ HDfprintf(stdout, "%s: doing read-rank0-and-MPI_Bcast\n", FUNC);
#endif
- 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)
- Proc0_BCast_enabled = TRUE;
- }
- 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)
- }
+ /* 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
@@ -1516,33 +1476,28 @@ H5FD__mpio_read(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type,
} /* end if */
else
if(MPI_SUCCESS != (mpi_code = MPI_File_read_at(file->f, mpi_off, buf, size_i, buf_type, &mpi_stat)))
-<<<<<<< HEAD
- HMPI_GOTO_ERROR(FAIL, "MPI_File_read_at failed", mpi_code)
- }
-=======
HMPI_GOTO_ERROR(FAIL, "MPI_File_read_at failed", mpi_code)
->>>>>>> 7bf6d847ae36940f1b1147820356795c7764dbeb
- if( !Proc0_BCast_enabled || (Proc0_BCast_enabled && file->mpi_rank == 0) ) {
- /* 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
-<<<<<<< HEAD
- 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_x(&mpi_stat, buf_type, &bytes_read)))
-#else
- if(MPI_SUCCESS != (mpi_code = MPI_Get_elements(&mpi_stat, MPI_BYTE, &bytes_read)))
->>>>>>> 7bf6d847ae36940f1b1147820356795c7764dbeb
+ 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(Proc0_BCast_enabled ) {
- if(MPI_SUCCESS != MPI_Bcast(&bytes_read, 1, MPI_LONG_LONG, 0, file->comm))
- HMPI_GOTO_ERROR(FAIL, "MPI_Bcast failed", 0)
- }
+ /* 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
@@ -1550,7 +1505,7 @@ H5FD__mpio_read(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type,
#else
if(MPI_SUCCESS != (mpi_code = MPI_Type_size(buf_type, &type_size)))
#endif
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_size failed", mpi_code)
+ HMPI_GOTO_ERROR(FAIL, "MPI_Type_size failed", mpi_code)
/* Compute the actual number of bytes requested */
io_size = type_size * size_i;
@@ -1562,15 +1517,6 @@ H5FD__mpio_read(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type,
/*
* This gives us zeroes beyond end of physical MPI file.
*/
-<<<<<<< HEAD
- 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((n = (io_size - bytes_read)) > 0)
HDmemset((char*)buf+bytes_read, 0, (size_t)n);
@@ -1578,7 +1524,6 @@ done:
#ifdef H5FDmpio_DEBUG
if(H5FD_mpio_Debug[(int)'t'])
HDfprintf(stdout, "%s: Leaving\n", FUNC);
->>>>>>> 7bf6d847ae36940f1b1147820356795c7764dbeb
#endif
FUNC_LEAVE_NOAPI(ret_value)
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 fba4f6e..23c38b9 100644
--- a/src/H5Ocache.c
+++ b/src/H5Ocache.c
@@ -1402,10 +1402,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)
@@ -1517,9 +1516,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.) */
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/H5Opkg.h b/src/H5Opkg.h
index dbc8089..668f4f0 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 */
diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h
index e0926e2..5987ecf 100644
--- a/src/H5Oprivate.h
+++ b/src/H5Oprivate.h
@@ -227,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
@@ -651,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 */
diff --git a/src/H5Pdxpl.c b/src/H5Pdxpl.c
index bfc1d93..8338d84 100644
--- a/src/H5Pdxpl.c
+++ b/src/H5Pdxpl.c
@@ -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/H5Ppublic.h b/src/H5Ppublic.h
index 2f094ea..078fe74 100644
--- a/src/H5Ppublic.h
+++ b/src/H5Ppublic.h
@@ -167,7 +167,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;
/********************/
diff --git a/src/H5T.c b/src/H5T.c
index 01ace87..9544488 100644
--- a/src/H5T.c
+++ b/src/H5T.c
@@ -295,6 +295,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_reg_ref(const H5T_t *dt);
/*****************************/
@@ -5506,6 +5507,111 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5T_detect_reg_ref
+ *
+ * Purpose: Check whether a datatype contains (or is) a region 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_reg_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 region reference */
+ if(H5T_REFERENCE == dt->shared->type && H5R_DATASET_REGION == dt->shared->u.atomic.u.r.rtype)
+ 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_reg_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_reg_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_reg_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_reg_ref(dt);
+ else
+ ret_value = FALSE;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T_is_vl_storage() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5T_upgrade_version_cb
*
* Purpose: H5T__visit callback to Upgrade the version of a datatype
diff --git a/src/H5Tprivate.h b/src/H5Tprivate.h
index 6b6446f..3dcbb2c 100644
--- a/src/H5Tprivate.h
+++ b/src/H5Tprivate.h
@@ -145,6 +145,7 @@ 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);