summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/H5Dchunk.c264
-rw-r--r--src/H5Dmpio.c7
-rw-r--r--src/H5FDcore.c4
-rw-r--r--src/H5FDcore.h12
-rw-r--r--src/H5FDdirect.h33
-rw-r--r--src/H5FDfamily.c3
-rw-r--r--src/H5FDfamily.h11
-rw-r--r--src/H5FDhdfs.h21
-rw-r--r--src/H5FDlog.c2
-rw-r--r--src/H5FDlog.h11
-rw-r--r--src/H5FDmirror.h11
-rw-r--r--src/H5FDmpi.c48
-rw-r--r--src/H5FDmpio.c39
-rw-r--r--src/H5FDmpio.h25
-rw-r--r--src/H5FDmulti.h8
-rw-r--r--src/H5FDonion.h17
-rw-r--r--src/H5FDprivate.h1
-rw-r--r--src/H5FDpublic.h1
-rw-r--r--src/H5FDros3.h20
-rw-r--r--src/H5FDsec2.c2
-rw-r--r--src/H5FDsec2.h13
-rw-r--r--src/H5FDsplitter.h121
-rw-r--r--src/H5FDstdio.h14
-rw-r--r--src/H5FDsubfiling/H5FDsubfiling.c6
-rw-r--r--src/H5FDwindows.h7
-rw-r--r--src/H5Fint.c8
-rw-r--r--src/H5Fmpi.c34
-rw-r--r--src/H5Fprivate.h1
-rw-r--r--src/H5Smpio.c2
-rw-r--r--src/H5T.c6
-rw-r--r--src/H5Tinit_float.c54
-rw-r--r--src/H5Tvlen.c2
-rw-r--r--src/H5Z.c142
-rw-r--r--src/H5mpi.c4
-rw-r--r--src/H5private.h1
-rw-r--r--src/H5system.c3
36 files changed, 590 insertions, 368 deletions
diff --git a/src/H5Dchunk.c b/src/H5Dchunk.c
index 41d774d..c8bad76 100644
--- a/src/H5Dchunk.c
+++ b/src/H5Dchunk.c
@@ -5536,11 +5536,9 @@ done:
/*-------------------------------------------------------------------------
* Function: H5D__chunk_collective_fill
*
- * Purpose: Use MPIO collective write to fill the chunks (if number of
- * chunks to fill is greater than the number of MPI procs;
- * otherwise use independent I/O).
+ * Purpose: Use MPIO selection vector I/O for writing fill chunks
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
@@ -5554,19 +5552,24 @@ H5D__chunk_collective_fill(const H5D_t *dset, H5D_chunk_coll_fill_info_t *chunk_
int mpi_code; /* MPI return code */
size_t num_blocks; /* Number of blocks between processes. */
size_t leftover_blocks; /* Number of leftover blocks to handle */
- int blocks, leftover; /* converted to int for MPI */
- MPI_Aint *chunk_disp_array = NULL;
- MPI_Aint *block_disps = NULL;
- int *block_lens = NULL;
- MPI_Datatype mem_type = MPI_BYTE, file_type = MPI_BYTE;
- H5FD_mpio_xfer_t prev_xfer_mode; /* Previous data xfer mode */
- bool have_xfer_mode = false; /* Whether the previous xffer mode has been retrieved */
- bool need_sort = false;
- size_t i; /* Local index variable */
+ int blocks; /* converted to int for MPI */
+ int leftover; /* converted to int for MPI */
+ H5FD_mpio_xfer_t prev_xfer_mode; /* Previous data xfer mode */
+ bool have_xfer_mode = false; /* Whether the previous xffer mode has been retrieved */
+ size_t i; /* Local index variable */
+ haddr_t *io_addrs = NULL;
+ size_t *io_sizes = NULL;
+ const void **io_wbufs = NULL;
+ H5FD_mem_t io_types[2];
+ bool all_same_block_len = true;
+ bool need_sort = false;
+ size_t io_2sizes[2];
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
+ assert(chunk_fill_info->num_chunks != 0);
+
/*
* If a separate fill buffer is provided for partial chunks, ensure
* that the "don't filter partial edge chunks" flag is set.
@@ -5589,6 +5592,7 @@ H5D__chunk_collective_fill(const H5D_t *dset, H5D_chunk_coll_fill_info_t *chunk_
/* 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 =
(size_t)(chunk_fill_info->num_chunks / (size_t)mpi_size); /* value should be the same on all procs */
@@ -5602,157 +5606,97 @@ H5D__chunk_collective_fill(const H5D_t *dset, H5D_chunk_coll_fill_info_t *chunk_
H5_CHECKED_ASSIGN(leftover, int, leftover_blocks, size_t);
/* Check if we have any chunks to write on this rank */
- if (num_blocks > 0 || (leftover && leftover > mpi_rank)) {
- MPI_Aint partial_fill_buf_disp = 0;
- bool all_same_block_len = true;
-
- /* Allocate buffers */
- if (NULL == (chunk_disp_array = (MPI_Aint *)H5MM_malloc((size_t)(blocks + 1) * sizeof(MPI_Aint))))
- HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate chunk file displacement buffer");
-
- if (partial_chunk_fill_buf) {
- MPI_Aint fill_buf_addr;
- MPI_Aint partial_fill_buf_addr;
-
- /* Calculate the displacement between the fill buffer and partial chunk fill buffer */
- if (MPI_SUCCESS != (mpi_code = MPI_Get_address(fill_buf, &fill_buf_addr)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Get_address failed", mpi_code)
- if (MPI_SUCCESS != (mpi_code = MPI_Get_address(partial_chunk_fill_buf, &partial_fill_buf_addr)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Get_address failed", mpi_code)
-
-#if H5_CHECK_MPI_VERSION(3, 1)
- partial_fill_buf_disp = MPI_Aint_diff(partial_fill_buf_addr, fill_buf_addr);
-#else
- partial_fill_buf_disp = partial_fill_buf_addr - fill_buf_addr;
-#endif
+ if (num_blocks > 0 || leftover > mpi_rank) {
- /*
- * Allocate all-zero block displacements array. If a block's displacement
- * is left as zero, that block will be written to from the regular fill
- * buffer. If a block represents an unfiltered partial edge chunk, its
- * displacement will be set so that the block is written to from the
- * unfiltered fill buffer.
- */
- if (NULL == (block_disps = (MPI_Aint *)H5MM_calloc((size_t)(blocks + 1) * sizeof(MPI_Aint))))
- HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate block displacements buffer");
- }
+ if (NULL == (io_addrs = H5MM_malloc((size_t)(blocks + 1) * sizeof(*io_addrs))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
+ "couldn't allocate space for I/O addresses vector");
- /*
- * Perform initial scan of chunk info list to:
- * - make sure that chunk addresses are monotonically non-decreasing
- * - check if all blocks have the same length
- */
- for (i = 1; i < chunk_fill_info->num_chunks; i++) {
- if (chunk_fill_info->chunk_info[i].addr < chunk_fill_info->chunk_info[i - 1].addr)
- need_sort = true;
-
- if (chunk_fill_info->chunk_info[i].chunk_size != chunk_fill_info->chunk_info[i - 1].chunk_size)
- all_same_block_len = false;
- }
+ if (NULL == (io_wbufs = H5MM_malloc((size_t)(blocks + 1) * sizeof(*io_wbufs))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "couldn't allocate space for I/O buffers vector");
+ }
- if (need_sort)
- qsort(chunk_fill_info->chunk_info, chunk_fill_info->num_chunks,
- sizeof(struct chunk_coll_fill_info), H5D__chunk_cmp_coll_fill_info);
+ /*
+ * Perform initial scan of chunk info list to:
+ * - make sure that chunk addresses are monotonically non-decreasing
+ * - check if all blocks have the same length
+ */
+ for (i = 1; i < chunk_fill_info->num_chunks; i++) {
+ if (chunk_fill_info->chunk_info[i].addr < chunk_fill_info->chunk_info[i - 1].addr)
+ need_sort = true;
- /* Allocate buffer for block lengths if necessary */
- if (!all_same_block_len)
- if (NULL == (block_lens = (int *)H5MM_malloc((size_t)(blocks + 1) * sizeof(int))))
- HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate chunk lengths buffer");
+ if (chunk_fill_info->chunk_info[i].chunk_size != chunk_fill_info->chunk_info[i - 1].chunk_size)
+ all_same_block_len = false;
+ }
- for (i = 0; i < (size_t)blocks; i++) {
- size_t idx = i + (size_t)(mpi_rank * blocks);
+ /*
+ * Note that we sort all of the chunks here, and not just a subset
+ * corresponding to this rank. We do this since we have found MPI I/O to work
+ * better when each rank writes blocks that are contiguous in the file,
+ * and by sorting the full list we maximize the chance of that happening.
+ */
+ if (need_sort)
+ qsort(chunk_fill_info->chunk_info, chunk_fill_info->num_chunks, sizeof(struct chunk_coll_fill_info),
+ H5D__chunk_cmp_coll_fill_info);
- /* store the chunk address as an MPI_Aint */
- chunk_disp_array[i] = (MPI_Aint)(chunk_fill_info->chunk_info[idx].addr);
+ /*
+ * If all the chunks have the same length, use the compressed feature
+ * to store the size.
+ * Otherwise, allocate the array of sizes for storing chunk sizes.
+ */
+ if (all_same_block_len) {
+ io_2sizes[0] = chunk_fill_info->chunk_info[0].chunk_size;
+ io_2sizes[1] = 0;
+ }
+ else {
+ if (NULL == (io_sizes = H5MM_malloc((size_t)(blocks + 1) * sizeof(*io_sizes))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "couldn't allocate space for I/O sizes vector");
+ }
- if (!all_same_block_len)
- H5_CHECKED_ASSIGN(block_lens[i], int, chunk_fill_info->chunk_info[idx].chunk_size, size_t);
+ /*
+ * Since the type of all chunks is raw data, use the compressed feature
+ * to store the chunk type.
+ */
+ io_types[0] = H5FD_MEM_DRAW;
+ io_types[1] = H5FD_MEM_NOLIST;
- if (chunk_fill_info->chunk_info[idx].unfiltered_partial_chunk) {
- assert(partial_chunk_fill_buf);
- block_disps[i] = partial_fill_buf_disp;
- }
- } /* end for */
+ /*
+ * For the chunks corresponding to this rank, fill in the
+ * address, size and buf pointer for each chunk.
+ */
+ for (i = 0; i < (size_t)blocks; i++) {
+ size_t idx = i + (size_t)(mpi_rank * blocks);
- /* Calculate if there are any leftover blocks after evenly
- * distributing. If there are, then round-robin the distribution
- * to processes 0 -> leftover.
- */
- if (leftover && leftover > mpi_rank) {
- chunk_disp_array[blocks] =
- (MPI_Aint)chunk_fill_info->chunk_info[(blocks * mpi_size) + mpi_rank].addr;
-
- if (!all_same_block_len)
- H5_CHECKED_ASSIGN(block_lens[blocks], int,
- chunk_fill_info->chunk_info[(blocks * mpi_size) + mpi_rank].chunk_size,
- size_t);
-
- if (chunk_fill_info->chunk_info[(blocks * mpi_size) + mpi_rank].unfiltered_partial_chunk) {
- assert(partial_chunk_fill_buf);
- block_disps[blocks] = partial_fill_buf_disp;
- }
+ io_addrs[i] = chunk_fill_info->chunk_info[idx].addr;
- blocks++;
- }
+ if (!all_same_block_len)
+ io_sizes[i] = chunk_fill_info->chunk_info[idx].chunk_size;
- /* Create file and memory types for the write operation */
- if (all_same_block_len) {
- int block_len;
+ if (chunk_fill_info->chunk_info[idx].unfiltered_partial_chunk)
+ io_wbufs[i] = partial_chunk_fill_buf;
+ else
+ io_wbufs[i] = fill_buf;
+ }
- H5_CHECKED_ASSIGN(block_len, int, chunk_fill_info->chunk_info[0].chunk_size, size_t);
+ /*
+ * For the leftover chunk corresponding to this rank, fill in the
+ * address, size and buf pointer for the chunk.
+ */
+ if (leftover > mpi_rank) {
+ io_addrs[blocks] = chunk_fill_info->chunk_info[(blocks * mpi_size) + mpi_rank].addr;
- mpi_code =
- MPI_Type_create_hindexed_block(blocks, block_len, chunk_disp_array, MPI_BYTE, &file_type);
- if (mpi_code != MPI_SUCCESS)
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hindexed_block failed", mpi_code)
+ if (!all_same_block_len)
+ io_sizes[blocks] = chunk_fill_info->chunk_info[(blocks * mpi_size) + mpi_rank].chunk_size;
- if (partial_chunk_fill_buf) {
- /*
- * If filters are disabled for partial edge chunks, those chunks could
- * potentially have the same block length as the other chunks, but still
- * need to be written to using the unfiltered fill buffer. Use an hindexed
- * block type rather than an hvector.
- */
- mpi_code =
- MPI_Type_create_hindexed_block(blocks, block_len, block_disps, MPI_BYTE, &mem_type);
- if (mpi_code != MPI_SUCCESS)
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hindexed_block failed", mpi_code)
- }
- else {
- mpi_code = MPI_Type_create_hvector(blocks, block_len, 0, MPI_BYTE, &mem_type);
- if (mpi_code != MPI_SUCCESS)
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hvector failed", mpi_code)
- }
- }
- else {
- /*
- * Currently, different block lengths implies that there are partial
- * edge chunks and the "don't filter partial edge chunks" flag is set.
- */
+ if (chunk_fill_info->chunk_info[(blocks * mpi_size) + mpi_rank].unfiltered_partial_chunk) {
assert(partial_chunk_fill_buf);
- assert(block_lens);
- assert(block_disps);
-
- mpi_code = MPI_Type_create_hindexed(blocks, block_lens, chunk_disp_array, MPI_BYTE, &file_type);
- if (mpi_code != MPI_SUCCESS)
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hindexed failed", mpi_code)
-
- mpi_code = MPI_Type_create_hindexed(blocks, block_lens, block_disps, MPI_BYTE, &mem_type);
- if (mpi_code != MPI_SUCCESS)
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hindexed failed", mpi_code)
+ io_wbufs[blocks] = partial_chunk_fill_buf;
}
+ else
+ io_wbufs[blocks] = fill_buf;
- if (MPI_SUCCESS != (mpi_code = MPI_Type_commit(&file_type)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code)
- if (MPI_SUCCESS != (mpi_code = MPI_Type_commit(&mem_type)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code)
- } /* end if */
-
- /* Set MPI-IO VFD properties */
-
- /* Set MPI datatypes for operation */
- if (H5CX_set_mpi_coll_datatypes(mem_type, file_type) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set MPI-I/O properties");
+ blocks++;
+ }
/* Get current transfer mode */
if (H5CX_get_io_xfer_mode(&prev_xfer_mode) < 0)
@@ -5763,31 +5707,24 @@ H5D__chunk_collective_fill(const H5D_t *dset, H5D_chunk_coll_fill_info_t *chunk_
if (H5CX_set_io_xfer_mode(H5FD_MPIO_COLLECTIVE) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set transfer mode");
- /* Low-level write (collective) */
- 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 */
if (MPI_SUCCESS != (mpi_code = MPI_Barrier(mpi_comm)))
HMPI_GOTO_ERROR(FAIL, "MPI_Barrier failed", mpi_code)
+ /* Perform the selection vector I/O for the chunks */
+ if (H5F_shared_vector_write(H5F_SHARED(dset->oloc.file), (uint32_t)blocks, io_types, io_addrs,
+ all_same_block_len ? io_2sizes : io_sizes, io_wbufs) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "vector write call failed");
+
done:
if (have_xfer_mode)
- /* Set transfer mode */
+ /* Restore transfer mode */
if (H5CX_set_io_xfer_mode(prev_xfer_mode) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set transfer mode");
- /* free things */
- if (MPI_BYTE != file_type)
- if (MPI_SUCCESS != (mpi_code = MPI_Type_free(&file_type)))
- HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code)
- if (MPI_BYTE != mem_type)
- if (MPI_SUCCESS != (mpi_code = MPI_Type_free(&mem_type)))
- HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code)
- H5MM_xfree(chunk_disp_array);
- H5MM_xfree(block_disps);
- H5MM_xfree(block_lens);
+ H5MM_xfree(io_addrs);
+ H5MM_xfree(io_wbufs);
+ H5MM_xfree(io_sizes);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__chunk_collective_fill() */
@@ -5805,6 +5742,7 @@ H5D__chunk_cmp_coll_fill_info(const void *_entry1, const void *_entry2)
FUNC_LEAVE_NOAPI(H5_addr_cmp(entry1->addr, entry2->addr))
} /* end H5D__chunk_cmp_coll_fill_info() */
+
#endif /* H5_HAVE_PARALLEL */
/*-------------------------------------------------------------------------
diff --git a/src/H5Dmpio.c b/src/H5Dmpio.c
index 16243fa..b6976e6 100644
--- a/src/H5Dmpio.c
+++ b/src/H5Dmpio.c
@@ -911,7 +911,8 @@ H5D__mpio_get_no_coll_cause_strings(char *local_cause, size_t local_cause_len, c
case H5D_MPIO_COLLECTIVE:
case H5D_MPIO_NO_COLLECTIVE_MAX_CAUSE:
default:
- assert(0 && "invalid no collective cause reason");
+ cause_str = "invalid or unknown no collective cause reason";
+ assert(0 && "invalid or unknown no collective cause reason");
break;
}
@@ -3782,6 +3783,10 @@ H5D__mpio_redistribute_shared_chunks_int(H5D_filtered_collective_io_info_t *chun
counts_disps_array = H5MM_xfree(counts_disps_array);
}
+ /* No useful work to do - exit */
+ if (coll_chunk_list_num_entries == 0)
+ HGOTO_DONE(SUCCEED);
+
/*
* Phase 2 - Involved ranks now redistribute any shared chunks to new
* owners as necessary.
diff --git a/src/H5FDcore.c b/src/H5FDcore.c
index 08b714d..1aa8d4b 100644
--- a/src/H5FDcore.c
+++ b/src/H5FDcore.c
@@ -754,8 +754,10 @@ H5FD__core_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr
((file_image_info.buffer == NULL) && (file_image_info.size == 0)));
memset(&sb, 0, sizeof(sb));
if ((file_image_info.buffer != NULL) && !(H5F_ACC_CREAT & flags)) {
- if (HDopen(name, o_flags, H5_POSIX_CREATE_MODE_RW) >= 0)
+ if ((fd = HDopen(name, o_flags, H5_POSIX_CREATE_MODE_RW)) >= 0) {
+ HDclose(fd);
HGOTO_ERROR(H5E_FILE, H5E_FILEEXISTS, NULL, "file already exists");
+ }
/* If backing store is requested, create and stat the file
* Note: We are forcing the O_CREAT flag here, even though this is
diff --git a/src/H5FDcore.h b/src/H5FDcore.h
index 235d6fc..cd45c8d 100644
--- a/src/H5FDcore.h
+++ b/src/H5FDcore.h
@@ -11,17 +11,25 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
- * Purpose: The public header file for the core driver.
+ * Purpose: The public header file for the core virtual file driver (VFD)
*/
#ifndef H5FDcore_H
#define H5FDcore_H
-#define H5FD_CORE (H5FDperform_init(H5FD_core_init))
+/** Initializer for the core VFD */
+#define H5FD_CORE (H5FDperform_init(H5FD_core_init))
+
+/** Identifier for the core VFD */
#define H5FD_CORE_VALUE H5_VFD_CORE
#ifdef __cplusplus
extern "C" {
#endif
+
+/** @private
+ *
+ * \brief Private initializer for the core VFD
+ */
H5_DLL hid_t H5FD_core_init(void);
/**
diff --git a/src/H5FDdirect.h b/src/H5FDdirect.h
index e47ac37..1e60bb0 100644
--- a/src/H5FDdirect.h
+++ b/src/H5FDdirect.h
@@ -11,30 +11,47 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
- * Purpose: The public header file for the direct driver.
+ * Purpose: The public header file for the direct virtual file driver (VFD)
*/
#ifndef H5FDdirect_H
#define H5FDdirect_H
#ifdef H5_HAVE_DIRECT
-#define H5FD_DIRECT (H5FDperform_init(H5FD_direct_init))
+
+/** Initializer for the direct VFD */
+#define H5FD_DIRECT (H5FDperform_init(H5FD_direct_init))
+
+/** Identifier for the direct VFD */
#define H5FD_DIRECT_VALUE H5_VFD_DIRECT
+
#else
+
+/** Initializer for the direct VFD (disabled) */
#define H5FD_DIRECT (H5I_INVALID_HID)
+
+/** Identifier for the direct VFD (disabled) */
#define H5FD_DIRECT_VALUE H5_VFD_INVALID
+
#endif /* H5_HAVE_DIRECT */
+/** Default value for memory boundary */
+#define MBOUNDARY_DEF 4096
+
+/** Default value for file block size */
+#define FBSIZE_DEF 4096
+
+/** Default value for maximum copy buffer size */
+#define CBSIZE_DEF (16 * 1024 * 1024)
+
#ifdef H5_HAVE_DIRECT
#ifdef __cplusplus
extern "C" {
#endif
-/* Default values for memory boundary, file block size, and maximal copy buffer size.
- * Application can set these values through the function H5Pset_fapl_direct. */
-#define MBOUNDARY_DEF 4096
-#define FBSIZE_DEF 4096
-#define CBSIZE_DEF 16 * 1024 * 1024
-
+/** @private
+ *
+ * \brief Private initializer for the direct VFD
+ */
H5_DLL hid_t H5FD_direct_init(void);
/**
diff --git a/src/H5FDfamily.c b/src/H5FDfamily.c
index 94805a2..3f43ae9 100644
--- a/src/H5FDfamily.c
+++ b/src/H5FDfamily.c
@@ -1427,7 +1427,8 @@ H5FD__family_delete(const char *filename, hid_t fapl_id)
FUNC_ENTER_PACKAGE
- assert(filename);
+ if (!filename)
+ HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "invalid filename pointer");
/* Get the driver info (for the member fapl)
* The family_open call accepts H5P_DEFAULT, so we'll accept that here, too.
diff --git a/src/H5FDfamily.h b/src/H5FDfamily.h
index 76020f0..32e885c 100644
--- a/src/H5FDfamily.h
+++ b/src/H5FDfamily.h
@@ -11,18 +11,25 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
- * Purpose: The public header file for the family driver.
+ * Purpose: The public header file for the family virtual file driver (VFD)
*/
#ifndef H5FDfamily_H
#define H5FDfamily_H
-#define H5FD_FAMILY (H5FDperform_init(H5FD_family_init))
+/** Initializer for the family VFD */
+#define H5FD_FAMILY (H5FDperform_init(H5FD_family_init))
+
+/** Identifier for the family VFD */
#define H5FD_FAMILY_VALUE H5_VFD_FAMILY
#ifdef __cplusplus
extern "C" {
#endif
+/** @private
+ *
+ * \brief Private initializer for the family VFD
+ */
H5_DLL hid_t H5FD_family_init(void);
/**
diff --git a/src/H5FDhdfs.h b/src/H5FDhdfs.h
index c8c2c37..e5f7173 100644
--- a/src/H5FDhdfs.h
+++ b/src/H5FDhdfs.h
@@ -11,18 +11,29 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
- * Purpose: The public header file for the hdfs driver.
+ * Purpose: The public header file for the Hadoop Distributed File System
+ * (hdfs) virtual file driver (VFD)
*/
#ifndef H5FDhdfs_H
#define H5FDhdfs_H
#ifdef H5_HAVE_LIBHDFS
-#define H5FD_HDFS (H5FDperform_init(H5FD_hdfs_init))
+
+/** Initializer for the hdfs VFD */
+#define H5FD_HDFS (H5FDperform_init(H5FD_hdfs_init))
+
+/** Identifier for the hdfs VFD */
#define H5FD_HDFS_VALUE H5_VFD_HDFS
-#else /* H5_HAVE_LIBHDFS */
+
+#else
+
+/** Initializer for the hdfs VFD (disabled) */
#define H5FD_HDFS (H5I_INVALID_HID)
+
+/** Identifier for the hdfs VFD (disabled) */
#define H5FD_HDFS_VALUE H5_VFD_INVALID
+
#endif /* H5_HAVE_LIBHDFS */
#ifdef H5_HAVE_LIBHDFS
@@ -104,6 +115,10 @@ typedef struct H5FD_hdfs_fapl_t {
int32_t stream_buffer_size;
} H5FD_hdfs_fapl_t;
+/** @private
+ *
+ * \brief Private initializer for the hdfs VFD
+ */
H5_DLL hid_t H5FD_hdfs_init(void);
/**
diff --git a/src/H5FDlog.c b/src/H5FDlog.c
index 8d43dc8..e35a6a6 100644
--- a/src/H5FDlog.c
+++ b/src/H5FDlog.c
@@ -545,7 +545,7 @@ H5FD__log_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr)
#endif /* H5_HAVE_WIN32_API */
/* Retain a copy of the name used to open the file, for possible error reporting */
- strncpy(file->filename, name, sizeof(file->filename));
+ strncpy(file->filename, name, sizeof(file->filename) - 1);
file->filename[sizeof(file->filename) - 1] = '\0';
/* Get the flags for logging */
diff --git a/src/H5FDlog.h b/src/H5FDlog.h
index ae4e2d0..b4af205 100644
--- a/src/H5FDlog.h
+++ b/src/H5FDlog.h
@@ -11,12 +11,15 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
- * Purpose: The public header file for the log driver.
+ * Purpose: The public header file for the log virtual file driver (VFD)
*/
#ifndef H5FDlog_H
#define H5FDlog_H
-#define H5FD_LOG (H5FDperform_init(H5FD_log_init))
+/** Initializer for the log VFD */
+#define H5FD_LOG (H5FDperform_init(H5FD_log_init))
+
+/** Identifier for the log VFD */
#define H5FD_LOG_VALUE H5_VFD_LOG
/* Flags for H5Pset_fapl_log() */
@@ -62,6 +65,10 @@
extern "C" {
#endif
+/** @private
+ *
+ * \brief Private initializer for the log VFD
+ */
H5_DLL hid_t H5FD_log_init(void);
/**
diff --git a/src/H5FDmirror.h b/src/H5FDmirror.h
index b196b2b..6c98e1a 100644
--- a/src/H5FDmirror.h
+++ b/src/H5FDmirror.h
@@ -11,7 +11,7 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
- * Purpose: Public, shared definitions for Mirror VFD & remote Writer.
+ * Purpose: The public header file for the mirror virtual file driver (VFD)
*/
#ifndef H5FDmirror_H
@@ -19,7 +19,10 @@
#ifdef H5_HAVE_MIRROR_VFD
-#define H5FD_MIRROR (H5FDperform_init(H5FD_mirror_init))
+/** Initializer for the mirror VFD */
+#define H5FD_MIRROR (H5FDperform_init(H5FD_mirror_init))
+
+/** Identifier for the mirror VFD */
#define H5FD_MIRROR_VALUE H5_VFD_MIRROR
#ifdef __cplusplus
@@ -62,6 +65,10 @@ typedef struct H5FD_mirror_fapl_t {
char remote_ip[H5FD_MIRROR_MAX_IP_LEN + 1];
} H5FD_mirror_fapl_t;
+/** @private
+ *
+ * \brief Private initializer for the mirror VFD
+ */
H5_DLL hid_t H5FD_mirror_init(void);
/**
diff --git a/src/H5FDmpi.c b/src/H5FDmpi.c
index 127740e..f247c34 100644
--- a/src/H5FDmpi.c
+++ b/src/H5FDmpi.c
@@ -104,13 +104,12 @@ done:
} /* end H5FD_mpi_get_size() */
/*-------------------------------------------------------------------------
- * Function: H5FD_mpi_get_comm
+ * Function: H5FD_mpi_get_comm
*
- * Purpose: Retrieves the file's communicator
+ * Purpose: Retrieves the file's MPI_Comm communicator object
*
- * Return: Success: The communicator (non-negative)
- *
- * Failure: Negative
+ * Return: Success: The communicator object
+ * Failure: MPI_COMM_NULL
*
*-------------------------------------------------------------------------
*/
@@ -144,6 +143,45 @@ done:
} /* end H5FD_mpi_get_comm() */
/*-------------------------------------------------------------------------
+ * Function: H5FD_mpi_get_info
+ *
+ * Purpose: Retrieves the file's MPI_Info info object
+ *
+ * Return: Success: The info object
+ * Failure: MPI_INFO_NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+MPI_Info
+H5FD_mpi_get_info(H5FD_t *file)
+{
+ const H5FD_class_t *cls;
+ uint64_t flags = H5FD_CTL_FAIL_IF_UNKNOWN_FLAG | H5FD_CTL_ROUTE_TO_TERMINAL_VFD_FLAG;
+ MPI_Info info = MPI_INFO_NULL;
+ void *info_ptr = (void *)(&info);
+ MPI_Info ret_value;
+
+ FUNC_ENTER_NOAPI(MPI_INFO_NULL)
+
+ assert(file);
+ cls = (const H5FD_class_t *)(file->cls);
+ assert(cls);
+ assert(cls->ctl); /* All MPI drivers must implement this */
+
+ /* Dispatch to driver */
+ if ((cls->ctl)(file, H5FD_CTL_GET_MPI_INFO_OPCODE, flags, NULL, &info_ptr) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTGET, MPI_INFO_NULL, "driver get_info request failed");
+
+ if (info == MPI_INFO_NULL)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTGET, MPI_INFO_NULL, "driver get_info request failed -- bad info object");
+
+ ret_value = info;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_mpi_get_info() */
+
+/*-------------------------------------------------------------------------
* Function: H5FD_mpi_MPIOff_to_haddr
*
* Purpose: Convert an MPI_Offset value to haddr_t.
diff --git a/src/H5FDmpio.c b/src/H5FDmpio.c
index 7141550..8aae79e 100644
--- a/src/H5FDmpio.c
+++ b/src/H5FDmpio.c
@@ -106,7 +106,7 @@ static herr_t H5FD__mpio_ctl(H5FD_t *_file, uint64_t op_code, uint64_t flags, co
/* Other functions */
static herr_t H5FD__mpio_vector_build_types(uint32_t count, H5FD_mem_t types[], haddr_t addrs[],
size_t sizes[], H5_flexible_const_ptr_t bufs[],
- haddr_t *s_addrs[], size_t *s_sizes[],
+ haddr_t *s_addrs[], size_t *s_sizes[], uint32_t *s_sizes_len,
H5_flexible_const_ptr_t *s_bufs[], bool *vector_was_sorted,
MPI_Offset *mpi_off, H5_flexible_const_ptr_t *mpi_bufs_base,
int *size_i, MPI_Datatype *buf_type, bool *buf_type_created,
@@ -906,7 +906,7 @@ H5FD__mpio_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t H5_ATTR
/* copy over each hint */
for (i = 0; i < nkeys; i++) {
- char key[MPI_MAX_INFO_KEY], value[MPI_MAX_INFO_VAL];
+ char key[MPI_MAX_INFO_KEY], value[MPI_MAX_INFO_VAL + 1];
int valuelen, flag;
/* retrieve the nth hint */
@@ -916,7 +916,7 @@ H5FD__mpio_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t H5_ATTR
if (MPI_SUCCESS != (mpi_code = MPI_Info_get_valuelen(info_used, key, &valuelen, &flag)))
HMPI_GOTO_ERROR(NULL, "MPI_Info_get_valuelen failed", mpi_code)
/* retrieve the value of nth hint */
- if (MPI_SUCCESS != (mpi_code = MPI_Info_get(info_used, key, valuelen + 1, value, &flag)))
+ if (MPI_SUCCESS != (mpi_code = MPI_Info_get(info_used, key, valuelen, value, &flag)))
HMPI_GOTO_ERROR(NULL, "MPI_Info_get failed", mpi_code)
/* copy the hint into info */
@@ -1675,7 +1675,8 @@ done:
static herr_t
H5FD__mpio_vector_build_types(uint32_t count, H5FD_mem_t types[], haddr_t addrs[], size_t sizes[],
H5_flexible_const_ptr_t bufs[], haddr_t *s_addrs[], size_t *s_sizes[],
- H5_flexible_const_ptr_t *s_bufs[], bool *vector_was_sorted, MPI_Offset *mpi_off,
+ uint32_t *s_sizes_len, H5_flexible_const_ptr_t *s_bufs[],
+ bool *vector_was_sorted, MPI_Offset *mpi_off,
H5_flexible_const_ptr_t *mpi_bufs_base, int *size_i, MPI_Datatype *buf_type,
bool *buf_type_created, MPI_Datatype *file_type, bool *file_type_created,
char *unused)
@@ -1716,6 +1717,10 @@ H5FD__mpio_vector_build_types(uint32_t count, H5FD_mem_t types[], haddr_t addrs[
/* Get bio I/O transition point (may be lower than 2G for testing) */
bigio_count = H5_mpi_get_bigio_count();
+ /* Start with s_sizes_len at count */
+ if (s_sizes_len)
+ *s_sizes_len = count;
+
if (count == 1) {
/* Single block. Just use a series of MPI_BYTEs for the file view.
*/
@@ -1808,8 +1813,13 @@ H5FD__mpio_vector_build_types(uint32_t count, H5FD_mem_t types[], haddr_t addrs[
if (!fixed_size) {
if ((*s_sizes)[i] == 0) {
assert(vector_was_sorted);
+ assert(i > 0);
fixed_size = true;
size = sizes[i - 1];
+
+ /* Return the used length of the s_sizes buffer */
+ if (s_sizes_len)
+ *s_sizes_len = (uint32_t)i;
}
else {
size = (*s_sizes)[i];
@@ -2098,7 +2108,7 @@ H5FD__mpio_read_vector(H5FD_t *_file, hid_t H5_ATTR_UNUSED dxpl_id, uint32_t cou
if (xfer_mode == H5FD_MPIO_COLLECTIVE) {
/* Build MPI types, etc. */
if (H5FD__mpio_vector_build_types(count, types, addrs, sizes, (H5_flexible_const_ptr_t *)bufs,
- &s_addrs, &s_sizes, (H5_flexible_const_ptr_t **)&s_bufs,
+ &s_addrs, &s_sizes, NULL, (H5_flexible_const_ptr_t **)&s_bufs,
&vector_was_sorted, &mpi_off,
(H5_flexible_const_ptr_t *)&mpi_bufs_base, &size_i, &buf_type,
&buf_type_created, &file_type, &file_type_created, &unused) < 0)
@@ -2464,17 +2474,21 @@ H5FD__mpio_write_vector(H5FD_t *_file, hid_t H5_ATTR_UNUSED dxpl_id, uint32_t co
HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "can't get MPI-I/O transfer mode");
if (xfer_mode == H5FD_MPIO_COLLECTIVE) {
+ uint32_t s_sizes_len;
+
/* Build MPI types, etc. */
if (H5FD__mpio_vector_build_types(count, types, addrs, sizes, (H5_flexible_const_ptr_t *)bufs,
- &s_addrs, &s_sizes, (H5_flexible_const_ptr_t **)&s_bufs,
- &vector_was_sorted, &mpi_off,
+ &s_addrs, &s_sizes, &s_sizes_len,
+ (H5_flexible_const_ptr_t **)&s_bufs, &vector_was_sorted, &mpi_off,
(H5_flexible_const_ptr_t *)&mpi_bufs_base, &size_i, &buf_type,
&buf_type_created, &file_type, &file_type_created, &unused) < 0)
HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "can't build MPI datatypes for I/O");
- /* Compute max address written to */
+ /* Compute max address written to. Note s_sizes is indexed according to the length of that array as
+ * reported by H5FD__mpio_vector_build_types(), which may be shorter if using the compressed arrays
+ * feature. */
if (count > 0)
- max_addr = s_addrs[count - 1] + (haddr_t)(s_sizes[count - 1]);
+ max_addr = s_addrs[count - 1] + (haddr_t)(s_sizes[s_sizes_len - 1]);
/* free sorted vectors if they exist */
if (!vector_was_sorted) {
@@ -3795,6 +3809,7 @@ done:
* At present, the supported op codes are:
*
* H5FD_CTL_GET_MPI_COMMUNICATOR_OPCODE
+ * H5FD_CTL_GET_MPI_INFO_OPCODE
* H5FD_CTL_GET_MPI_RANK_OPCODE
* H5FD_CTL_GET_MPI_SIZE_OPCODE
* H5FD_CTL_GET_MPI_FILE_SYNC_OPCODE
@@ -3827,6 +3842,12 @@ H5FD__mpio_ctl(H5FD_t *_file, uint64_t op_code, uint64_t flags, const void H5_AT
**((MPI_Comm **)output) = file->comm;
break;
+ case H5FD_CTL_GET_MPI_INFO_OPCODE:
+ assert(output);
+ assert(*output);
+ **((MPI_Info **)output) = file->info;
+ break;
+
case H5FD_CTL_GET_MPI_RANK_OPCODE:
assert(output);
assert(*output);
diff --git a/src/H5FDmpio.h b/src/H5FDmpio.h
index 60deec2..5e7ecf3 100644
--- a/src/H5FDmpio.h
+++ b/src/H5FDmpio.h
@@ -11,35 +11,42 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
- * Purpose: The public header file for the mpio driver.
+ * Purpose: The public header file for the MPI-I/O (mpio) virtual file driver (VFD)
*/
#ifndef H5FDmpio_H
#define H5FDmpio_H
-/* Macros */
-
#ifdef H5_HAVE_PARALLEL
+
+/** Initializer for the mpio VFD */
#define H5FD_MPIO (H5FDperform_init(H5FD_mpio_init))
+
#else
+
+/** Initializer for the mpio VFD (disabled) */
#define H5FD_MPIO (H5I_INVALID_HID)
-#endif /* H5_HAVE_PARALLEL */
+
+#endif
#ifdef H5_HAVE_PARALLEL
-/*Turn on H5FDmpio_debug if H5F_DEBUG is on */
-#ifdef H5F_DEBUG
-#ifndef H5FDmpio_DEBUG
+
+#if defined(H5F_DEBUG) && !defined(H5FDmpio_DEBUG)
+/** Turn mpio VFD debugging on (requires H5F_DEBUG) */
#define H5FDmpio_DEBUG
#endif
-#endif
/* Global var whose value comes from environment variable */
/* (Defined in H5FDmpio.c) */
H5_DLLVAR hbool_t H5FD_mpi_opt_types_g;
-/* Function prototypes */
#ifdef __cplusplus
extern "C" {
#endif
+
+/** @private
+ *
+ * \brief Private initializer for the mpio VFD
+ */
H5_DLL hid_t H5FD_mpio_init(void);
/**
diff --git a/src/H5FDmulti.h b/src/H5FDmulti.h
index a85f2df..d89a3e2 100644
--- a/src/H5FDmulti.h
+++ b/src/H5FDmulti.h
@@ -11,16 +11,22 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
- * Purpose: The public header file for the "multi" driver.
+ * Purpose: The public header file for the multi virtual file driver (VFD)
*/
#ifndef H5FDmulti_H
#define H5FDmulti_H
+/** Initializer for the multi VFD */
#define H5FD_MULTI (H5FDperform_init(H5FD_multi_init))
#ifdef __cplusplus
extern "C" {
#endif
+
+/** @private
+ *
+ * \brief Private initializer for the multi VFD
+ */
H5_DLL hid_t H5FD_multi_init(void);
/**
diff --git a/src/H5FDonion.h b/src/H5FDonion.h
index 09b290e..4aaab6d 100644
--- a/src/H5FDonion.h
+++ b/src/H5FDonion.h
@@ -11,19 +11,18 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
- * Onion Virtual File Driver (VFD)
- *
- * Purpose: The public header file for the Onion VFD.
+ * Purpose: The public header file for the onion virtual file driver (VFD)
*/
#ifndef H5FDonion_H
#define H5FDonion_H
-#define H5FD_ONION (H5FDperform_init(H5FD_onion_init))
+/** Initializer for the onion VFD */
+#define H5FD_ONION (H5FDperform_init(H5FD_onion_init))
+
+/** Identifier for the onion VFD */
#define H5FD_ONION_VALUE H5_VFD_ONION
-/**
- * Current version of the onion VFD fapl info struct.
- */
+/** Current version of the onion VFD fapl info struct */
#define H5FD_ONION_FAPL_INFO_VERSION_CURR 1
#define H5FD_ONION_FAPL_INFO_CREATE_FLAG_ENABLE_PAGE_ALIGNMENT \
@@ -114,6 +113,10 @@ typedef struct H5FD_onion_fapl_info_t {
extern "C" {
#endif
+/** @private
+ *
+ * \brief Private initializer for the onion VFD
+ */
H5_DLL hid_t H5FD_onion_init(void);
/**
diff --git a/src/H5FDprivate.h b/src/H5FDprivate.h
index 5330077..2fe54a5 100644
--- a/src/H5FDprivate.h
+++ b/src/H5FDprivate.h
@@ -214,6 +214,7 @@ H5_DLL herr_t H5FD_get_mpio_atomicity(H5FD_t *file, bool *flag);
H5_DLL int H5FD_mpi_get_rank(H5FD_t *file);
H5_DLL int H5FD_mpi_get_size(H5FD_t *file);
H5_DLL MPI_Comm H5FD_mpi_get_comm(H5FD_t *file);
+H5_DLL MPI_Info H5FD_mpi_get_info(H5FD_t *file);
H5_DLL herr_t H5FD_mpi_get_file_sync_required(H5FD_t *file, bool *file_sync_required);
#endif /* H5_HAVE_PARALLEL */
diff --git a/src/H5FDpublic.h b/src/H5FDpublic.h
index 5f40bff..d8d77d6 100644
--- a/src/H5FDpublic.h
+++ b/src/H5FDpublic.h
@@ -179,6 +179,7 @@
#define H5FD_CTL_INVALID_OPCODE 0
#define H5FD_CTL_TEST_OPCODE 1
#define H5FD_CTL_GET_MPI_COMMUNICATOR_OPCODE 2
+#define H5FD_CTL_GET_MPI_INFO_OPCODE 9
#define H5FD_CTL_GET_MPI_RANK_OPCODE 3
#define H5FD_CTL_GET_MPI_SIZE_OPCODE 4
#define H5FD_CTL_MEM_ALLOC 5
diff --git a/src/H5FDros3.h b/src/H5FDros3.h
index ecd2678..217af2d 100644
--- a/src/H5FDros3.h
+++ b/src/H5FDros3.h
@@ -11,20 +11,24 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
- * Read-Only S3 Virtual File Driver (VFD)
- *
- * Purpose: The public header file for the ros3 driver.
+ * Purpose: The public header file for the read-only S3 (ros3) virtual file driver (VFD)
*/
#ifndef H5FDros3_H
#define H5FDros3_H
#ifdef H5_HAVE_ROS3_VFD
-#define H5FD_ROS3 (H5FDperform_init(H5FD_ros3_init))
+/** Initializer for the ros3 VFD */
+#define H5FD_ROS3 (H5FDperform_init(H5FD_ros3_init))
+
+/** Identifier for the ros3 VFD */
#define H5FD_ROS3_VALUE H5_VFD_ROS3
#else
+/** Initializer for the ros3 VFD (disabled) */
#define H5FD_ROS3 (H5I_INVALID_HID)
+
+/** Identifier for the ros3 VFD (disabled) */
#define H5FD_ROS3_VALUE H5_VFD_INVALID
-#endif /* H5_HAVE_ROS3_VFD */
+#endif
#ifdef H5_HAVE_ROS3_VFD
@@ -139,9 +143,9 @@ typedef struct H5FD_ros3_fapl_t {
extern "C" {
#endif
-/**
- * \brief Internal routine to initialize #H5FD_ROS3 driver. Not meant to be
- * called directly by an HDF5 application.
+/** @private
+ *
+ * \brief Private initializer for the ros3 VFD
*/
H5_DLL hid_t H5FD_ros3_init(void);
diff --git a/src/H5FDsec2.c b/src/H5FDsec2.c
index 2961684..15accf7 100644
--- a/src/H5FDsec2.c
+++ b/src/H5FDsec2.c
@@ -368,7 +368,7 @@ H5FD__sec2_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr
}
/* Retain a copy of the name used to open the file, for possible error reporting */
- strncpy(file->filename, name, sizeof(file->filename));
+ strncpy(file->filename, name, sizeof(file->filename) - 1);
file->filename[sizeof(file->filename) - 1] = '\0';
/* Check for non-default FAPL */
diff --git a/src/H5FDsec2.h b/src/H5FDsec2.h
index a2590ae..dd0a4d8 100644
--- a/src/H5FDsec2.h
+++ b/src/H5FDsec2.h
@@ -11,18 +11,26 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
- * Purpose: The public header file for the sec2 driver
+ * Purpose: The public header file for the POSOX I/O (sec2 - "POSIX section 2")
+ * virtual file driver (VFD)
*/
#ifndef H5FDsec2_H
#define H5FDsec2_H
-#define H5FD_SEC2 (H5FDperform_init(H5FD_sec2_init))
+/** Initializer for the sec2 VFD */
+#define H5FD_SEC2 (H5FDperform_init(H5FD_sec2_init))
+
+/** Identifier for the sec2 VFD */
#define H5FD_SEC2_VALUE H5_VFD_SEC2
#ifdef __cplusplus
extern "C" {
#endif
+/** @private
+ *
+ * \brief Private initializer for the sec2 VFD
+ */
H5_DLL hid_t H5FD_sec2_init(void);
/**
@@ -38,7 +46,6 @@ H5_DLL hid_t H5FD_sec2_init(void);
* #H5FD_SEC2 driver.
*
* \since 1.4.0
- *
*/
H5_DLL herr_t H5Pset_fapl_sec2(hid_t fapl_id);
diff --git a/src/H5FDsplitter.h b/src/H5FDsplitter.h
index c8751c8..99a471e 100644
--- a/src/H5FDsplitter.h
+++ b/src/H5FDsplitter.h
@@ -11,96 +11,103 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
- * Purpose: The public header file for the "splitter" driver.
+ * Purpose: The public header file for the splitter virtual file driver (VFD)
*/
#ifndef H5FDsplitter_H
#define H5FDsplitter_H
-#define H5FD_SPLITTER (H5FDperform_init(H5FD_splitter_init))
+/** Initializer for the splitter VFD */
+#define H5FD_SPLITTER (H5FDperform_init(H5FD_splitter_init))
+
+/** Identifier for the splitter VFD */
#define H5FD_SPLITTER_VALUE H5_VFD_SPLITTER
-/* The version of the H5FD_splitter_vfd_config_t structure used */
+/** The version of the H5FD_splitter_vfd_config_t structure used */
#define H5FD_CURR_SPLITTER_VFD_CONFIG_VERSION 1
-/* Maximum length of a filename/path string in the Write-Only channel,
+/**
+ * Maximum length of a filename/path string in the Write-Only channel,
* including the NULL-terminator.
*/
#define H5FD_SPLITTER_PATH_MAX 4096
-/* Semi-unique constant used to help identify structure pointers */
+/** Semi-unique constant used to help identify structure pointers */
#define H5FD_SPLITTER_MAGIC 0x2B916880
-/* ----------------------------------------------------------------------------
- * Structure: H5FD_spliiter_vfd_config_t
- *
- * One-stop shopping for configuring a Splitter VFD (rather than many
- * parameters passed into H5Pset/get functions).
- *
- * magic (int32_t)
- * Semi-unique number, used to sanity-check that a given pointer is
- * likely (or not) to be this structure type. MUST be first.
- * If magic is not H5FD_SPLITTER_MAGIC, the structure (and/or pointer to)
- * must be considered invalid.
- *
- * version (unsigned int)
- * Version number of this structure -- informs component membership.
- * If not H5FD_CURR_SPLITTER_VFD_CONFIG_VERSION, the structure (and/or
- * pointer to) must be considered invalid.
- *
- * rw_fapl_id (hid_t)
- * Library-given identification number of the Read/Write channel driver
- * File Access Property List.
- * The driver must support read/write access.
- * Must be set to H5P_DEFAULT or a valid FAPL ID.
- *
- * wo_fapl_id (hid_t)
- * Library-given identification number of the Read/Write channel driver
- * File Access Property List.
- * The driver feature flags must include H5FD_FEAT_DEFAULT_VFD_COMPAITBLE.
- * Must be set to H5P_DEFAULT or a valid FAPL ID.
- *
- * wo_file_path (char[H5FD_SPLITTER_PATH_MAX + 1])
- * String buffer for the Write-Only channel target file.
- * Must be null-terminated, cannot be empty.
- *
- * log_file_path (char[H5FD_SPLITTER_PATH_MAX + 1])
- * String buffer for the Splitter VFD logging output.
- * Must be null-terminated.
- * If null, no logfile is created.
- *
- * ignore_wo_errors (hbool_t)
- * Toggle flag for how judiciously to respond to errors on the Write-Only
- * channel.
- *
- * ----------------------------------------------------------------------------
+//! <!-- [H5FD_splitter_vfd_config_t_snip] -->
+/**
+ * Configuration options for setting up the Splitter VFD
*/
typedef struct H5FD_splitter_vfd_config_t {
- int32_t magic;
- unsigned int version;
- hid_t rw_fapl_id;
- hid_t wo_fapl_id;
- char wo_path[H5FD_SPLITTER_PATH_MAX + 1];
- char log_file_path[H5FD_SPLITTER_PATH_MAX + 1];
- hbool_t ignore_wo_errs;
+ int32_t magic; /**< Magic number to identify this struct. Must be \p H5FD_SPLITTER_MAGIC. */
+ unsigned int version; /**< Version number of this struct. Currently must be \p
+ H5FD_CURR_SPLITTER_VFD_CONFIG_VERSION. */
+ hid_t rw_fapl_id; /**< File-access property list for setting up the read/write channel. Can be \p
+ H5P_DEFAULT. */
+ hid_t wo_fapl_id; /**< File-access property list for setting up the read-only channel. The selected VFD
+ must support the \p H5FD_FEAT_DEFAULT_VFD_COMPATIBLE flag. Can be \p H5P_DEFAULT. */
+ char wo_path[H5FD_SPLITTER_PATH_MAX + 1]; /**< Path to the write-only file */
+ char log_file_path[H5FD_SPLITTER_PATH_MAX + 1]; /**< Path to the log file, which will be created on HDF5
+ file open (existing files will be clobbered). Can be
+ NULL, in which case no logging output is generated. */
+ hbool_t ignore_wo_errs; /**< Whether to ignore errors on the write-only channel */
} H5FD_splitter_vfd_config_t;
+//! <!-- [H5FD_splitter_vfd_config_t_snip] -->
#ifdef __cplusplus
extern "C" {
#endif
+
+/** @private
+ *
+ * \brief Private initializer for the splitter VFD
+ */
H5_DLL hid_t H5FD_splitter_init(void);
/**
* \ingroup FAPL
*
- * \todo Add missing documentation
+ * \brief Sets the file access property list to use the splitter driver
+ *
+ * \fapl_id
+ * \param[in] config_ptr Configuration options for the VFD
+ * \returns \herr_t
+ *
+ * \details H5Pset_fapl_splitter() sets the file access property list identifier,
+ * \p fapl_id, to use the splitter driver.
+ *
+ * The splitter VFD echoes file manipulation (e.g. create, truncate)
+ * and write calls to a second, write-only file.
+ *
+ * \note The splitter VFD should not be confused with the split VFD,
+ * which is a simplification of the multi VFD and creates separate
+ * files for metadata and data.
+ *
+ * \since 1.10.7, 1.12.1
*/
H5_DLL herr_t H5Pset_fapl_splitter(hid_t fapl_id, H5FD_splitter_vfd_config_t *config_ptr);
/**
* \ingroup FAPL
*
- * \todo Add missing documentation
+ * \brief Gets splitter driver properties from the the file access property list
+ *
+ * \fapl_id
+ * \param[out] config_ptr Configuration options for the VFD
+ * \returns \herr_t
+ *
+ * \details H5Pset_fapl_splitter() sets the file access property list identifier,
+ * \p fapl_id, to use the splitter driver.
+ *
+ * The splitter VFD echoes file manipulation (e.g. create, truncate)
+ * and write calls to a second file.
+ *
+ * \note The splitter VFD should not be confused with the split VFD,
+ * which is a simplification of the multi VFD and creates separate
+ * files for metadata and data.
+ *
+ * \since 1.10.7, 1.12.1
*/
H5_DLL herr_t H5Pget_fapl_splitter(hid_t fapl_id, H5FD_splitter_vfd_config_t *config_ptr);
diff --git a/src/H5FDstdio.h b/src/H5FDstdio.h
index e2e05a7..794fe31 100644
--- a/src/H5FDstdio.h
+++ b/src/H5FDstdio.h
@@ -11,20 +11,26 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
- * Purpose: The public header file for the C stdio driver
+ * Purpose: The public header file for the C stdio virtual file driver (VFD)
*/
#ifndef H5FDstdio_H
#define H5FDstdio_H
#include "H5Ipublic.h"
+/** Initializer for the stdio VFD */
#define H5FD_STDIO (H5FDperform_init(H5FD_stdio_init))
#ifdef __cplusplus
extern "C" {
#endif
+/** @private
+ *
+ * \brief Private initializer for the stdio VFD
+ */
H5_DLL hid_t H5FD_stdio_init(void);
+
/**
* \ingroup FAPL
*
@@ -34,7 +40,11 @@ H5_DLL hid_t H5FD_stdio_init(void);
* \returns \herr_t
*
* \details H5Pset_fapl_stdio() modifies the file access property list to use
- * the standard I/O driver, H5FDstdio().
+ * the stdio VFD, which uses I/O calls from stdio.h.
+ *
+ * \note This VFD was designed to be a "demo" VFD that shows how to write
+ * your own VFD. Most applications should not use this VFD and should instead
+ * use the POSIX I/O VFD (sec2).
*
* \since 1.4.0
*
diff --git a/src/H5FDsubfiling/H5FDsubfiling.c b/src/H5FDsubfiling/H5FDsubfiling.c
index a2daba0..461fa16 100644
--- a/src/H5FDsubfiling/H5FDsubfiling.c
+++ b/src/H5FDsubfiling/H5FDsubfiling.c
@@ -2551,6 +2551,12 @@ H5FD__subfiling_ctl(H5FD_t *_file, uint64_t op_code, uint64_t flags, const void
**((MPI_Comm **)output) = file->ext_comm;
break;
+ case H5FD_CTL_GET_MPI_INFO_OPCODE:
+ assert(output);
+ assert(*output);
+ **((MPI_Info **)output) = file->info;
+ break;
+
case H5FD_CTL_GET_MPI_RANK_OPCODE:
assert(output);
assert(*output);
diff --git a/src/H5FDwindows.h b/src/H5FDwindows.h
index 14f6985..673d1c9 100644
--- a/src/H5FDwindows.h
+++ b/src/H5FDwindows.h
@@ -11,11 +11,16 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
- * Purpose: The public header file for the Windows driver
+ * Purpose: The public header file for the Windows virtual file driver (VFD)
+ *
+ * This VFD uses no Win32 API calls directly (though it may be
+ * rewritten to do so in the future). It is currently defined to
+ * be the sec2 VFD.
*/
#ifndef H5FDwindows_H
#define H5FDwindows_H
+/** Initializer for the Windows VFD */
#define H5FD_WINDOWS (H5FD_sec2_init())
#ifdef __cplusplus
diff --git a/src/H5Fint.c b/src/H5Fint.c
index 4093b4b..8738026 100644
--- a/src/H5Fint.c
+++ b/src/H5Fint.c
@@ -410,11 +410,11 @@ H5F_get_access_plist(H5F_t *f, bool app_ref)
if (H5P_set(new_plist, H5F_ACS_MPI_PARAMS_COMM_NAME, &mpi_comm) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set MPI communicator");
- /* Retrieve and set MPI info object */
- if (H5P_get(old_plist, H5F_ACS_MPI_PARAMS_INFO_NAME, &mpi_info) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTGET, H5I_INVALID_HID, "can't get MPI info object");
+ /* Retrieve and set MPI info */
+ if (MPI_INFO_NULL == (mpi_info = H5F_mpi_get_info(f)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, H5I_INVALID_HID, "can't get MPI info");
if (H5P_set(new_plist, H5F_ACS_MPI_PARAMS_INFO_NAME, &mpi_info) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set MPI info object");
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set MPI info");
}
#endif /* H5_HAVE_PARALLEL */
if (H5P_set(new_plist, H5F_ACS_META_CACHE_INIT_IMAGE_CONFIG_NAME, &(f->shared->mdc_initCacheImageCfg)) <
diff --git a/src/H5Fmpi.c b/src/H5Fmpi.c
index 8a8fdc1..7a535e9 100644
--- a/src/H5Fmpi.c
+++ b/src/H5Fmpi.c
@@ -97,11 +97,10 @@ done:
/*-------------------------------------------------------------------------
* Function: H5F_mpi_get_comm
*
- * Purpose: Retrieves the file's communicator
+ * Purpose: Retrieves the file's MPI_Comm communicator object
*
- * Return: Success: The communicator (non-negative)
- *
- * Failure: Negative
+ * Return: Success: The communicator object
+ * Failure: MPI_COMM_NULL
*
*-------------------------------------------------------------------------
*/
@@ -123,6 +122,33 @@ done:
} /* end H5F_mpi_get_comm() */
/*-------------------------------------------------------------------------
+ * Function: H5F_mpi_get_info
+ *
+ * Purpose: Retrieves the file's MPI_Info info object
+ *
+ * Return: Success: The info object
+ * Failure: MPI_INFO_NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+MPI_Info
+H5F_mpi_get_info(const H5F_t *f)
+{
+ MPI_Info ret_value = MPI_INFO_NULL;
+
+ FUNC_ENTER_NOAPI(MPI_INFO_NULL)
+
+ assert(f && f->shared);
+
+ /* Dispatch to driver */
+ if ((ret_value = H5FD_mpi_get_info(f->shared->lf)) == MPI_INFO_NULL)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, MPI_INFO_NULL, "driver get_info request failed");
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_mpi_get_info() */
+
+/*-------------------------------------------------------------------------
* Function: H5F_shared_mpi_get_size
*
* Purpose: Retrieves the size of an MPI process.
diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h
index 9adbf3a..682e938 100644
--- a/src/H5Fprivate.h
+++ b/src/H5Fprivate.h
@@ -640,6 +640,7 @@ H5_DLL herr_t H5F_eoa_dirty(H5F_t *f);
#ifdef H5_HAVE_PARALLEL
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 MPI_Info H5F_mpi_get_info(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);
diff --git a/src/H5Smpio.c b/src/H5Smpio.c
index 1e0fef5..46e6c33 100644
--- a/src/H5Smpio.c
+++ b/src/H5Smpio.c
@@ -989,7 +989,7 @@ H5S__mpio_span_hyper_type(const H5S_t *space, size_t elmt_size, MPI_Datatype *ne
&type_list, 0, 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)
+ HMPI_GOTO_ERROR(FAIL, "MPI_Type_dup failed", mpi_code)
if (MPI_SUCCESS != (mpi_code = MPI_Type_commit(new_type)))
HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code)
diff --git a/src/H5T.c b/src/H5T.c
index 2627a01..4a5c7cf 100644
--- a/src/H5T.c
+++ b/src/H5T.c
@@ -2500,7 +2500,7 @@ H5T__register(H5T_pers_t pers, const char *name, H5T_t *src, H5T_t *dst, H5T_con
H5T_g.asoft = na;
H5T_g.soft = x;
} /* end if */
- strncpy(H5T_g.soft[H5T_g.nsoft].name, name, (size_t)H5T_NAMELEN);
+ strncpy(H5T_g.soft[H5T_g.nsoft].name, name, (size_t)H5T_NAMELEN - 1);
H5T_g.soft[H5T_g.nsoft].name[H5T_NAMELEN - 1] = '\0';
H5T_g.soft[H5T_g.nsoft].src = src->shared->type;
H5T_g.soft[H5T_g.nsoft].dst = dst->shared->type;
@@ -2549,7 +2549,7 @@ H5T__register(H5T_pers_t pers, const char *name, H5T_t *src, H5T_t *dst, H5T_con
/* Create a new conversion path */
if (NULL == (new_path = H5FL_CALLOC(H5T_path_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
- strncpy(new_path->name, name, (size_t)H5T_NAMELEN);
+ strncpy(new_path->name, name, (size_t)H5T_NAMELEN - 1);
new_path->name[H5T_NAMELEN - 1] = '\0';
if (NULL == (new_path->src = H5T_copy(old_path->src, H5T_COPY_ALL)) ||
NULL == (new_path->dst = H5T_copy(old_path->dst, H5T_COPY_ALL)))
@@ -4952,7 +4952,7 @@ H5T__path_find_real(const H5T_t *src, const H5T_t *dst, const char *name, H5T_co
if (NULL == (path = H5FL_CALLOC(H5T_path_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for type conversion path");
if (name && *name) {
- strncpy(path->name, name, (size_t)H5T_NAMELEN);
+ strncpy(path->name, name, (size_t)H5T_NAMELEN - 1);
path->name[H5T_NAMELEN - 1] = '\0';
} /* end if */
else
diff --git a/src/H5Tinit_float.c b/src/H5Tinit_float.c
index 3b9e127..02bb3ba 100644
--- a/src/H5Tinit_float.c
+++ b/src/H5Tinit_float.c
@@ -51,19 +51,23 @@
* Function: DETECT_F
*
* Purpose: This macro takes a floating point type like `double' and
- * a base name like `natd' and detects byte order, mantissa
- * location, exponent location, sign bit location, presence or
- * absence of implicit mantissa bit, and exponent bias and
- * initializes a detected_t structure with those properties.
+ * detects byte order, mantissa location, exponent location,
+ * sign bit location, presence or absence of implicit mantissa
+ * bit, and exponent bias and initializes a detected_t structure
+ * with those properties.
+ *
+ * Note that these operations can raise floating-point
+ * exceptions and building with some compiler options
+ * (especially Fortran) can cause problems.
*-------------------------------------------------------------------------
*/
-#define DETECT_F(TYPE, VAR, INFO) \
+#define DETECT_F(TYPE, INFO) \
do { \
- TYPE _v1, _v2, _v3; \
- unsigned char _buf1[sizeof(TYPE)], _buf3[sizeof(TYPE)]; \
- unsigned char _pad_mask[sizeof(TYPE)]; \
- unsigned char _byte_mask; \
- int _i, _j, _last = (-1); \
+ TYPE _v1, _v2, _v3; \
+ uint8_t _buf1[sizeof(TYPE)], _buf3[sizeof(TYPE)]; \
+ uint8_t _pad_mask[sizeof(TYPE)]; \
+ uint8_t _byte_mask; \
+ int _i, _j, _last = -1; \
\
memset(&INFO, 0, sizeof(INFO)); \
INFO.size = sizeof(TYPE); \
@@ -81,7 +85,7 @@
_v1 = (TYPE)4.0L; \
H5MM_memcpy(_buf1, (const void *)&_v1, sizeof(TYPE)); \
for (_i = 0; _i < (int)sizeof(TYPE); _i++) \
- for (_byte_mask = (unsigned char)1; _byte_mask; _byte_mask = (unsigned char)(_byte_mask << 1)) { \
+ for (_byte_mask = (uint8_t)1; _byte_mask; _byte_mask = (uint8_t)(_byte_mask << 1)) { \
_buf1[_i] ^= _byte_mask; \
H5MM_memcpy((void *)&_v2, (const void *)_buf1, sizeof(TYPE)); \
H5_GCC_CLANG_DIAG_OFF("float-equal") \
@@ -118,7 +122,7 @@
_v1 = (TYPE)1.0L; \
_v2 = (TYPE)-1.0L; \
if (H5T__bit_cmp(sizeof(TYPE), INFO.perm, &_v1, &_v2, _pad_mask, &(INFO.sign)) < 0) \
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "failed to detect byte order"); \
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "failed to determine sign bit"); \
\
/* Mantissa */ \
INFO.mpos = 0; \
@@ -126,12 +130,11 @@
_v1 = (TYPE)1.0L; \
_v2 = (TYPE)1.5L; \
if (H5T__bit_cmp(sizeof(TYPE), INFO.perm, &_v1, &_v2, _pad_mask, &(INFO.msize)) < 0) \
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "failed to detect byte order"); \
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "failed to determine mantissa"); \
INFO.msize += 1 + (unsigned)(INFO.imp ? 0 : 1) - INFO.mpos; \
\
/* Exponent */ \
- INFO.epos = INFO.mpos + INFO.msize; \
- \
+ INFO.epos = INFO.mpos + INFO.msize; \
INFO.esize = INFO.sign - INFO.epos; \
\
_v1 = (TYPE)1.0L; \
@@ -456,17 +459,24 @@ H5T__set_precision(H5T_fpoint_det_t *d)
herr_t H5_NO_UBSAN
H5T__init_native_float_types(void)
{
+ fenv_t saved_fenv;
H5T_fpoint_det_t det;
H5T_t *dt = NULL;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
+ /* Turn off floating-point exceptions while initializing to avoid
+ * tripping over signaling NaNs while looking at "don't care" bits.
+ */
+ if (feholdexcept(&saved_fenv) != 0)
+ HSYS_GOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "can't save floating-point environment");
+
/* H5T_NATIVE_FLOAT */
/* Get the type's characteristics */
memset(&det, 0, sizeof(H5T_fpoint_det_t));
- DETECT_F(float, FLOAT, det);
+ DETECT_F(float, det);
/* Allocate and fill type structure */
if (NULL == (dt = H5T__alloc()))
@@ -497,7 +507,7 @@ H5T__init_native_float_types(void)
/* Get the type's characteristics */
memset(&det, 0, sizeof(H5T_fpoint_det_t));
- DETECT_F(double, DOUBLE, det);
+ DETECT_F(double, det);
/* Allocate and fill type structure */
if (NULL == (dt = H5T__alloc()))
@@ -528,7 +538,7 @@ H5T__init_native_float_types(void)
/* Get the type's characteristics */
memset(&det, 0, sizeof(H5T_fpoint_det_t));
- DETECT_F(long double, LDOUBLE, det);
+ DETECT_F(long double, det);
/* Allocate and fill type structure */
if (NULL == (dt = H5T__alloc()))
@@ -561,6 +571,14 @@ H5T__init_native_float_types(void)
H5T_native_order_g = det.order;
done:
+ /* Clear any FE_INVALID exceptions from NaN handling */
+ if (feclearexcept(FE_INVALID) != 0)
+ HSYS_GOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "can't clear floating-point exceptions");
+
+ /* Restore the original environment */
+ if (feupdateenv(&saved_fenv) != 0)
+ HSYS_GOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "can't restore floating-point environment");
+
if (ret_value < 0) {
if (dt != NULL) {
dt->shared = H5FL_FREE(H5T_shared_t, dt->shared);
diff --git a/src/H5Tvlen.c b/src/H5Tvlen.c
index 68087a8..651ff8f 100644
--- a/src/H5Tvlen.c
+++ b/src/H5Tvlen.c
@@ -503,7 +503,7 @@ H5T__vlen_mem_seq_write(H5VL_object_t H5_ATTR_UNUSED *file, const H5T_vlen_alloc
if (seq_len) {
size_t len = seq_len * base_size; /* Sequence size */
- /* Use the user's memory allocation routine is one is defined */
+ /* Use the user's memory allocation routine if 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_DATATYPE, H5E_CANTALLOC, FAIL,
diff --git a/src/H5Z.c b/src/H5Z.c
index b514f62..720aa43 100644
--- a/src/H5Z.c
+++ b/src/H5Z.c
@@ -485,19 +485,30 @@ done:
*-------------------------------------------------------------------------
*/
static int
-H5Z__check_unregister_group_cb(void *obj_ptr, hid_t H5_ATTR_UNUSED obj_id, void *key)
+H5Z__check_unregister_group_cb(void H5_ATTR_UNUSED *obj_ptr, hid_t obj_id, void *key)
{
- hid_t ocpl_id = -1;
- H5Z_object_t *object = (H5Z_object_t *)key;
- htri_t filter_in_pline = false;
- int ret_value = false; /* Return value */
+ hid_t ocpl_id = -1;
+ H5Z_object_t *object = (H5Z_object_t *)key;
+ H5VL_object_t *vol_obj; /* Object for loc_id */
+ H5VL_group_get_args_t vol_cb_args; /* Arguments to VOL callback */
+ htri_t filter_in_pline = false;
+ int ret_value = false; /* Return value */
FUNC_ENTER_PACKAGE
- assert(obj_ptr);
-
/* Get the group creation property */
- if ((ocpl_id = H5G_get_create_plist((H5G_t *)obj_ptr)) < 0)
+ if (NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(obj_id, H5I_GROUP)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid group identifier");
+
+ /* Set up VOL callback arguments */
+ vol_cb_args.op_type = H5VL_GROUP_GET_GCPL;
+ vol_cb_args.args.get_gcpl.gcpl_id = H5I_INVALID_HID;
+
+ /* Get the group creation property list */
+ if (H5VL_group_get(vol_obj, &vol_cb_args, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
+ HGOTO_ERROR(H5E_PLINE, H5E_CANTGET, H5I_INVALID_HID, "unable to get group creation properties");
+
+ if ((ocpl_id = vol_cb_args.args.get_gcpl.gcpl_id) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_CANTGET, FAIL, "can't get group creation property list");
/* Check if the filter is in the group creation property list */
@@ -535,19 +546,30 @@ done:
*-------------------------------------------------------------------------
*/
static int
-H5Z__check_unregister_dset_cb(void *obj_ptr, hid_t H5_ATTR_UNUSED obj_id, void *key)
+H5Z__check_unregister_dset_cb(void H5_ATTR_UNUSED *obj_ptr, hid_t obj_id, void *key)
{
- hid_t ocpl_id = -1;
- H5Z_object_t *object = (H5Z_object_t *)key;
- htri_t filter_in_pline = false;
- int ret_value = false; /* Return value */
+ hid_t ocpl_id = -1;
+ H5Z_object_t *object = (H5Z_object_t *)key;
+ H5VL_object_t *vol_obj; /* Object for loc_id */
+ H5VL_dataset_get_args_t vol_cb_args; /* Arguments to VOL callback */
+ htri_t filter_in_pline = false;
+ int ret_value = false; /* Return value */
FUNC_ENTER_PACKAGE
- assert(obj_ptr);
-
/* Get the dataset creation property */
- if ((ocpl_id = H5D_get_create_plist((H5D_t *)obj_ptr)) < 0)
+ if (NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(obj_id, H5I_DATASET)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid dataset identifier");
+
+ /* Set up VOL callback arguments */
+ vol_cb_args.op_type = H5VL_DATASET_GET_DCPL;
+ vol_cb_args.args.get_dcpl.dcpl_id = H5I_INVALID_HID;
+
+ /* Get the dataset creation property list */
+ if (H5VL_dataset_get(vol_obj, &vol_cb_args, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, H5I_INVALID_HID, "unable to get dataset creation properties");
+
+ if ((ocpl_id = vol_cb_args.args.get_dcpl.dcpl_id) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_CANTGET, FAIL, "can't get dataset creation property list");
/* Check if the filter is in the dataset creation property list */
@@ -581,51 +603,83 @@ done:
*-------------------------------------------------------------------------
*/
static int
-H5Z__flush_file_cb(void *obj_ptr, hid_t H5_ATTR_UNUSED obj_id, void H5_ATTR_PARALLEL_USED *key)
+H5Z__flush_file_cb(void H5_ATTR_UNUSED *obj_ptr, hid_t obj_id, void H5_ATTR_PARALLEL_USED *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 */
+#endif /* H5_HAVE_PARALLEL */
+ int ret_value = false; /* Return value */
+ H5VL_file_specific_args_t vol_cb_args_specific; /* Arguments to VOL callback */
+ H5VL_object_t *vol_obj; /* File for file_id */
+ H5VL_file_get_args_t vol_cb_args; /* Arguments to VOL callback */
+ bool is_native_vol_obj = true;
+ unsigned int intent = 0;
FUNC_ENTER_PACKAGE
/* Sanity checks */
- assert(obj_ptr);
assert(key);
+ /* Get the internal file structure */
+ if (NULL == (vol_obj = (H5VL_object_t *)H5I_object(obj_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier");
+
+ /* Get intent */
+ vol_cb_args.op_type = H5VL_FILE_GET_INTENT;
+ vol_cb_args.args.get_intent.flags = &intent;
+
+ /* Get the flags */
+ if (H5VL_file_get(vol_obj, &vol_cb_args, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get file's intent flags");
+
+ if (H5VL_object_is_native(vol_obj, &is_native_vol_obj) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, H5I_INVALID_HID,
+ "can't determine if VOL object is native connector object");
+
/* Do a global flush if the file is opened for write */
- if (H5F_ACC_RDWR & H5F_INTENT(f)) {
+ if (H5F_ACC_RDWR & intent) {
#ifdef H5_HAVE_PARALLEL
- /* Check if MPIO driver is used */
- if (H5F_HAS_FEATURE(f, H5FD_FEAT_HAS_MPI)) {
- /* 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)
- */
- if (H5_coll_api_sanity_check_g && !object->sanity_checked) {
- MPI_Comm mpi_comm; /* File's communicator */
+ /* Checking MPI flag requires native VOL */
+ if (is_native_vol_obj) {
+ H5F_t *f = (H5F_t *)obj_ptr; /* File object for native VOL operation */
+
+ /* Check if MPIO driver is used */
+ if (H5F_HAS_FEATURE(f, H5FD_FEAT_HAS_MPI)) {
- /* Retrieve the file communicator */
- if (MPI_COMM_NULL == (mpi_comm = H5F_mpi_get_comm(f)))
- HGOTO_ERROR(H5E_PLINE, H5E_CANTGET, FAIL, "can't get MPI communicator");
+ /* 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)
+ */
+ if (H5_coll_api_sanity_check_g && !object->sanity_checked) {
+ MPI_Comm mpi_comm; /* File's communicator */
- /* Issue the barrier */
- if (mpi_comm != MPI_COMM_NULL)
- MPI_Barrier(mpi_comm);
+ /* Retrieve the file communicator */
+ if (H5F_mpi_retrieve_comm(obj_id, H5P_DEFAULT, &mpi_comm) < 0)
+ HGOTO_ERROR(H5E_PLINE, H5E_CANTGET, FAIL, "can't get MPI communicator");
- /* Set the "sanity checked" flag */
- object->sanity_checked = true;
- } /* end if */
- } /* end if */
-#endif /* H5_HAVE_PARALLEL */
+ /* Issue the barrier */
+ if (mpi_comm != MPI_COMM_NULL)
+ MPI_Barrier(mpi_comm);
+
+ /* Set the "sanity checked" flag */
+ object->sanity_checked = true;
+ } /* end if */
+ } /* end if */
+ }
+#endif /* H5_HAVE_PARALLEL */
/* Call the flush routine for mounted file hierarchies */
- if (H5F_flush_mounts((H5F_t *)obj_ptr) < 0)
- HGOTO_ERROR(H5E_PLINE, H5E_CANTFLUSH, FAIL, "unable to flush file hierarchy");
+ vol_cb_args_specific.op_type = H5VL_FILE_FLUSH;
+ vol_cb_args_specific.args.flush.obj_type = H5I_FILE;
+ vol_cb_args_specific.args.flush.scope = H5F_SCOPE_GLOBAL;
+
+ /* Flush the object */
+ if (H5VL_file_specific(vol_obj, &vol_cb_args_specific, H5P_DATASET_XFER_DEFAULT, NULL) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush file hierarchy");
+
} /* end if */
done:
diff --git a/src/H5mpi.c b/src/H5mpi.c
index 2725ec5..cf7e33d 100644
--- a/src/H5mpi.c
+++ b/src/H5mpi.c
@@ -380,9 +380,9 @@ H5_mpi_info_cmp(MPI_Info info1, MPI_Info info2, int *result)
/* 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))))
+ if (NULL == (value1 = (char *)H5MM_malloc((MPI_MAX_INFO_VAL + 1) * sizeof(char))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
- if (NULL == (value2 = (char *)H5MM_malloc(MPI_MAX_INFO_VAL * sizeof(char))))
+ if (NULL == (value2 = (char *)H5MM_malloc((MPI_MAX_INFO_VAL + 1) * sizeof(char))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
/* Iterate over the keys, comparing them */
diff --git a/src/H5private.h b/src/H5private.h
index 14a0ac3..3aaa0d5 100644
--- a/src/H5private.h
+++ b/src/H5private.h
@@ -26,6 +26,7 @@
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
+#include <fenv.h>
#include <float.h>
#include <math.h>
#include <setjmp.h>
diff --git a/src/H5system.c b/src/H5system.c
index 30a89a1..be886ae 100644
--- a/src/H5system.c
+++ b/src/H5system.c
@@ -807,13 +807,12 @@ H5_nanosleep(uint64_t nanosec)
#ifdef H5_HAVE_WIN32_API
DWORD dwMilliseconds = (DWORD)ceil(nanosec / 1.0e6);
- DWORD ignore;
/* Windows can't sleep at a ns resolution. Best we can do is ~1 ms. We
* don't care about the return value since the second parameter
* (bAlertable) is false, so it will always be zero.
*/
- ignore = SleepEx(dwMilliseconds, false);
+ SleepEx(dwMilliseconds, false);
#else