summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormainzer <mainzer#hdfgroup.org>2020-06-29 16:09:40 (GMT)
committermainzer <mainzer#hdfgroup.org>2020-06-29 16:09:40 (GMT)
commit5a6d9b3a4e12cc399ce27361755f0c8d069e256b (patch)
tree5967c6050e8fc4295c3d5090423bb71e562c135a
parent96e912c842d0b2c517df78614f319a68c47efd61 (diff)
downloadhdf5-5a6d9b3a4e12cc399ce27361755f0c8d069e256b.zip
hdf5-5a6d9b3a4e12cc399ce27361755f0c8d069e256b.tar.gz
hdf5-5a6d9b3a4e12cc399ce27361755f0c8d069e256b.tar.bz2
Added support for vector I/O to the VFD layer, and associated test code
in test/vfd.c. Note that this test uses only sec2 and stdio at present. Since no VFDs support vector I/O at present, the vector I/O VFD calls are translated to regular read/write calls in the VFD layer. Tested serial and parallel, debug and production on charis, parallel debug on jelly. Some seemingly un-related issues, but after consultation with Richard, I'm proceeding with the checkin.
-rw-r--r--src/H5FD.c151
-rw-r--r--src/H5FDcore.c2
-rw-r--r--src/H5FDdirect.c2
-rw-r--r--src/H5FDfamily.c2
-rw-r--r--src/H5FDhdfs.c2
-rw-r--r--src/H5FDint.c253
-rw-r--r--src/H5FDlog.c2
-rw-r--r--src/H5FDmirror.c2
-rw-r--r--src/H5FDmpio.c2
-rw-r--r--src/H5FDmulti.c2
-rw-r--r--src/H5FDprivate.h6
-rw-r--r--src/H5FDpublic.h12
-rw-r--r--src/H5FDros3.c2
-rw-r--r--src/H5FDsec2.c2
-rw-r--r--src/H5FDsplitter.c2
-rw-r--r--src/H5FDstdio.c2
-rw-r--r--test/vfd.c761
17 files changed, 1194 insertions, 13 deletions
diff --git a/src/H5FD.c b/src/H5FD.c
index 2e80c7f..85ad025 100644
--- a/src/H5FD.c
+++ b/src/H5FD.c
@@ -1478,6 +1478,157 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5FDread_vector
+ *
+ * Purpose: Perform count reads from the specified file at the offsets
+ * provided in the addrs array, with the lengths and memory
+ * types provided in the sizes and types arrays. Data read
+ * is returned in the buffers provided in the bufs array.
+ *
+ * All reads are done according to the data transfer property
+ * list dxpl_id (which may be the constant H5P_DEFAULT).
+ *
+ * Return: Success: SUCCEED
+ * All reads have completed successfully, and
+ * the results havce been into the supplied
+ * buffers.
+ *
+ * Failure: FAIL
+ * The contents of supplied buffers are undefined.
+ *
+ * Programmer: JRM -- 6/10/20
+ *
+ * Changes: None.
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FDread_vector(H5FD_t *file, hid_t dxpl_id, uint32_t count,
+ H5FD_mem_t types[], haddr_t addrs[], size_t sizes[],
+ void *bufs[] /* out */)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE7("e", "*xiIu*Mt*a*zx", file, dxpl_id, count, types, addrs, sizes, bufs);
+
+ /* Check arguments */
+ if(!file)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file pointer cannot be NULL")
+
+ if(!file->cls)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file class pointer cannot be NULL")
+
+ if((!types) && (count > 0))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "types parameter can't be NULL if count is positive")
+
+ if((!addrs) && (count > 0))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "addrs parameter can't be NULL if count is positive")
+
+ if((!sizes) && (count > 0))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "sizes parameter can't be NULL if count is positive")
+
+ if((!bufs) && (count > 0))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "bufs parameter can't be NULL if count is positive")
+
+ /* Get the default dataset transfer property list if the user
+ * didn't provide one
+ */
+ if(H5P_DEFAULT == dxpl_id) {
+ dxpl_id = H5P_DATASET_XFER_DEFAULT;
+ } else {
+ if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data transfer property list")
+ }
+
+ /* Set DXPL for operation */
+ H5CX_set_dxpl(dxpl_id);
+
+ /* Call private function */
+ /* JRM -- review this */
+ /* (Note compensating for base addresses addition in internal routine) */
+ if(H5FD_read_vector(file, count, types, addrs, sizes, bufs) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "file vector read request failed")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5FDread_vector() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FDwrite_vector
+ *
+ * Purpose: Perform count writes to the specified file at the offsets
+ * provided in the addrs array, with the lengths and memory
+ * types provided in the sizes and types arrays. Data to be
+ * written is in the buffers provided in the bufs array.
+ *
+ * All writes are done according to the data transfer property
+ * list dxpl_id (which may be the constant H5P_DEFAULT).
+ *
+ * Return: Success: SUCCEED
+ * All writes have completed successfully
+ *
+ * Failure: FAIL
+ * One or more of the writes failed.
+ *
+ * Programmer: JRM -- 6/10/20
+ *
+ * Changes: None.
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FDwrite_vector(H5FD_t *file, hid_t dxpl_id, uint32_t count,
+ H5FD_mem_t types[], haddr_t addrs[], size_t sizes[],
+ void *bufs[] /* in */)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE7("e", "*xiIu*Mt*a*z*x", file, dxpl_id, count, types, addrs, sizes, bufs);
+
+ /* Check arguments */
+ if(!file)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file pointer cannot be NULL")
+
+ if(!file->cls)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file class pointer cannot be NULL")
+
+ if((!types) && (count > 0))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "types parameter can't be NULL if count is positive")
+
+ if((!addrs) && (count > 0))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "addrs parameter can't be NULL if count is positive")
+
+ if((!sizes) && (count > 0))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "sizes parameter can't be NULL if count is positive")
+
+ if((!bufs) && (count > 0))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "bufs parameter can't be NULL if count is positive")
+
+ /* Get the default dataset transfer property list if the user didn't provide one */
+ if(H5P_DEFAULT == dxpl_id) {
+ dxpl_id = H5P_DATASET_XFER_DEFAULT;
+ } else {
+ if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data transfer property list")
+ }
+
+ /* Set DXPL for operation */
+ H5CX_set_dxpl(dxpl_id);
+
+ /* Call private function */ /* JRM -- review this */
+ /* (Note compensating for base address addition in internal routine) */
+ if(H5FD_write_vector(file, count, types, addrs, sizes, bufs) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "file vector write request failed")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5FDwrite_vector() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5FDflush
*
* Purpose: Notify driver to flush all cached data. If the driver has no
diff --git a/src/H5FDcore.c b/src/H5FDcore.c
index 0551dd0..4e581bf 100644
--- a/src/H5FDcore.c
+++ b/src/H5FDcore.c
@@ -175,6 +175,8 @@ static const H5FD_class_t H5FD_core_g = {
H5FD__core_get_handle, /* get_handle */
H5FD__core_read, /* read */
H5FD__core_write, /* write */
+ NULL, /* read_vector */
+ NULL, /* write_vector */
H5FD__core_flush, /* flush */
H5FD__core_truncate, /* truncate */
H5FD_core_lock, /* lock */
diff --git a/src/H5FDdirect.c b/src/H5FDdirect.c
index 34c4346..3b82cce 100644
--- a/src/H5FDdirect.c
+++ b/src/H5FDdirect.c
@@ -167,6 +167,8 @@ static const H5FD_class_t H5FD_direct_g = {
H5FD_direct_get_handle, /*get_handle */
H5FD_direct_read, /*read */
H5FD_direct_write, /*write */
+ NULL, /* read_vector */
+ NULL, /* write_vector */
NULL, /*flush */
H5FD_direct_truncate, /*truncate */
H5FD_direct_lock, /*lock */
diff --git a/src/H5FDfamily.c b/src/H5FDfamily.c
index d110ef7..683f706 100644
--- a/src/H5FDfamily.c
+++ b/src/H5FDfamily.c
@@ -135,6 +135,8 @@ static const H5FD_class_t H5FD_family_g = {
H5FD_family_get_handle, /*get_handle */
H5FD_family_read, /*read */
H5FD_family_write, /*write */
+ NULL, /*read_vector */
+ NULL, /*write_vector */
H5FD_family_flush, /*flush */
H5FD_family_truncate, /*truncate */
H5FD_family_lock, /*lock */
diff --git a/src/H5FDhdfs.c b/src/H5FDhdfs.c
index 3d086ea..b9f0527 100644
--- a/src/H5FDhdfs.c
+++ b/src/H5FDhdfs.c
@@ -517,6 +517,8 @@ static const H5FD_class_t H5FD_hdfs_g = {
H5FD_hdfs_get_handle, /* get_handle */
H5FD_hdfs_read, /* read */
H5FD_hdfs_write, /* write */
+ NULL, /* read_vector */
+ NULL, /* write_vector */
NULL, /* flush */
H5FD_hdfs_truncate, /* truncate */
H5FD_hdfs_lock, /* lock */
diff --git a/src/H5FDint.c b/src/H5FDint.c
index 8a2148a..13fa1ac 100644
--- a/src/H5FDint.c
+++ b/src/H5FDint.c
@@ -254,6 +254,259 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5FD_read_vector
+ *
+ * Purpose: Private version of H5FDread_vector()
+ *
+ * Perform count reads from the specified file at the offsets
+ * provided in the addrs array, with the lengths and memory
+ * types provided in the sizes and types arrays. Data read
+ * is returned in the buffers provided in the bufs array.
+ *
+ * If the underlying VFD supports vector reads, pass the
+ * call through directly.
+ *
+ * If it doesn't, convert the vector read into a sequence
+ * of individual reads.
+ *
+ * Note that it is not in general possible to convert a
+ * vector read into a selection read, because each element
+ * in the vector read may have a different memory type.
+ * In contrast, selection reads are of a single type.
+ *
+ * Return: Success: SUCCEED
+ * All reads have completed successfully, and
+ * the results havce been into the supplied
+ * buffers.
+ *
+ * Failure: FAIL
+ * The contents of supplied buffers are undefined.
+ *
+ * Programmer: JRM -- 6/10/20
+ *
+ * Changes: None
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FD_read_vector(H5FD_t *file, uint32_t count, H5FD_mem_t types[],
+ haddr_t addrs[], size_t sizes[], void * bufs[] /* out */)
+{
+ hbool_t addrs_cooked = FALSE;
+ uint32_t i;
+ hid_t dxpl_id = H5I_INVALID_HID; /* DXPL for operation */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(file);
+ HDassert(file->cls);
+ HDassert((types) || (count == 0));
+ HDassert((addrs) || (count == 0));
+ HDassert((sizes) || (count == 0));
+ HDassert((bufs) || (count == 0));
+
+ /* Get proper DXPL for I/O */
+ dxpl_id = H5CX_get_dxpl();
+
+#ifndef H5_HAVE_PARALLEL
+ /* The no-op case
+ *
+ * Do not return early for Parallel mode since the I/O could be a
+ * collective transfer.
+ */
+ if(0 == count) {
+ HGOTO_DONE(SUCCEED)
+ }
+#endif /* H5_HAVE_PARALLEL */
+
+ if ( file->base_addr > 0 ) {
+
+ /* apply the base_addr offset to the addrs array. Must undo before
+ * we return.
+ */
+ for ( i = 0; i < count; i++ ) {
+
+ addrs[i] += file->base_addr;
+ }
+ addrs_cooked = TRUE;
+ }
+
+ /* If the file is open for SWMR read access, allow access to data past
+ * the end of the allocated space (the 'eoa'). This is done because the
+ * eoa stored in the file's superblock might be out of sync with the
+ * objects being written within the file by the application performing
+ * SWMR write operations.
+ */
+ if(!(file->access_flags & H5F_ACC_SWMR_READ)) {
+ haddr_t eoa;
+
+ for ( i = 0; i < count; i++ ) {
+
+ if(HADDR_UNDEF == (eoa = (file->cls->get_eoa)(file, types[i])))
+ HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver get_eoa request failed")
+
+ if((addrs[i] + sizes[i]) > eoa)
+
+ HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, FAIL, "addr overflow, addrs[%d] = %llu, sizes[%d] = %llu, eoa = %llu", (int)i, (unsigned long long)(addrs[i]), (int)i, (unsigned long long)sizes[i], (unsigned long long)eoa)
+ }
+ }
+
+ /* if the underlying VFD supports vector read, make the call */
+ if (file->cls->read_vector) {
+
+ if ((file->cls->read_vector)(file, dxpl_id, count, types, addrs, sizes, bufs) < 0)
+
+ HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "driver read vector request failed")
+ } else {
+ /* otherwise, implement the vector read as a sequence of regular
+ * read calls.
+ */
+ for ( i = 0; i < count; i++ ) {
+
+ if((file->cls->read)(file, types[i], dxpl_id, addrs[i], sizes[i], bufs[i]) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "driver read request failed")
+ }
+ }
+
+done:
+ /* undo the base addr offset to the addrs array if necessary */
+ if ( addrs_cooked ) {
+
+ HDassert(file->base_addr > 0);
+
+ for ( i = 0; i < count; i++ ) {
+
+ addrs[i] -= file->base_addr;
+ }
+ }
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_read_vector() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_write_vector
+ *
+ * Purpose: Private version of H5FDwrite_vector()
+ *
+ * Perform count writes to the specified file at the offsets
+ * provided in the addrs array, with the lengths and memory
+ * types provided in the sizes and types arrays. Data written
+ * is taken from the buffers provided in the bufs array.
+ *
+ * If the underlying VFD supports vector writes, pass the
+ * call through directly.
+ *
+ * If it doesn't, convert the vector write into a sequence
+ * of individual writes.
+ *
+ * Note that it is not in general possible to convert a
+ * vector write into a selection write, because each element
+ * in the vector read may have a different memory type.
+ * In contrast, selection writes are of a single type.
+ *
+ * Return: Success: SUCCEED
+ * All writes have completed successfully.
+ *
+ * Failure: FAIL
+ * One or more writes failed.
+ *
+ * Programmer: JRM -- 6/10/20
+ *
+ * Changes: None
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FD_write_vector(H5FD_t *file, uint32_t count, H5FD_mem_t types[],
+ haddr_t addrs[], size_t sizes[], void * bufs[] /* out */)
+{
+ hbool_t addrs_cooked = FALSE;
+ uint32_t i;
+ hid_t dxpl_id; /* DXPL for operation */
+ haddr_t eoa = HADDR_UNDEF; /* EOA for file */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(file);
+ HDassert(file->cls);
+ HDassert((types) || (count == 0));
+ HDassert((addrs) || (count == 0));
+ HDassert((sizes) || (count == 0));
+ HDassert((bufs) || (count == 0));
+
+ /* Get proper DXPL for I/O */
+ dxpl_id = H5CX_get_dxpl();
+
+#ifndef H5_HAVE_PARALLEL
+ /* The no-op case
+ *
+ * Do not return early for Parallel mode since the I/O could be a
+ * collective transfer.
+ */
+ if(0 == count)
+ HGOTO_DONE(SUCCEED)
+#endif /* H5_HAVE_PARALLEL */
+
+ if ( file->base_addr > 0 ) {
+
+ /* apply the base_addr offset to the addrs array. Must undo before
+ * we return.
+ */
+ for ( i = 0; i < count; i++ ) {
+
+ addrs[i] += file->base_addr;
+ }
+ addrs_cooked = TRUE;
+ }
+
+ for ( i = 0; i < count; i++ ) {
+
+ if(HADDR_UNDEF == (eoa = (file->cls->get_eoa)(file, types[i])))
+
+ HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver get_eoa request failed")
+
+ if((addrs[i] + sizes[i]) > eoa)
+
+ HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, FAIL, "addr overflow, addrs[%d] = %llu, sizes[%d] = %llu, eoa = %llu", (int)i, (unsigned long long)(addrs[i]), (int)i, (unsigned long long)sizes[i], (unsigned long long)eoa)
+ }
+
+ /* if the underlying VFD supports vector write, make the call */
+ if (file->cls->write_vector) {
+
+ if ((file->cls->write_vector)(file, dxpl_id, count, types, addrs, sizes, bufs) < 0)
+
+ HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "driver write vector request failed")
+ } else {
+ /* otherwise, implement the vector write as a sequence of regular
+ * write calls.
+ */
+ for ( i = 0; i < count; i++ ) {
+
+ if((file->cls->write)(file, types[i], dxpl_id, addrs[i], sizes[i], bufs[i]) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "driver write request failed")
+ }
+ }
+
+done:
+ /* undo the base addr offset to the addrs array if necessary */
+ if ( addrs_cooked ) {
+
+ HDassert(file->base_addr > 0);
+
+ for ( i = 0; i < count; i++ ) {
+
+ addrs[i] -= file->base_addr;
+ }
+ }
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_write() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5FD_set_eoa
*
* Purpose: Private version of H5FDset_eoa()
diff --git a/src/H5FDlog.c b/src/H5FDlog.c
index f649bc4..3a563d0 100644
--- a/src/H5FDlog.c
+++ b/src/H5FDlog.c
@@ -211,6 +211,8 @@ static const H5FD_class_t H5FD_log_g = {
H5FD_log_get_handle, /*get_handle */
H5FD_log_read, /*read */
H5FD_log_write, /*write */
+ NULL, /*read_vector */
+ NULL, /*write_vector */
NULL, /*flush */
H5FD_log_truncate, /*truncate */
H5FD_log_lock, /*lock */
diff --git a/src/H5FDmirror.c b/src/H5FDmirror.c
index ef035c1..1ed3372 100644
--- a/src/H5FDmirror.c
+++ b/src/H5FDmirror.c
@@ -193,6 +193,8 @@ static const H5FD_class_t H5FD_mirror_g = {
NULL, /* get_handle */
H5FD_mirror_read, /* read */
H5FD_mirror_write, /* write */
+ NULL, /* read_vector */
+ NULL, /* write_vector */
NULL, /* flush */
H5FD_mirror_truncate, /* truncate */
H5FD_mirror_lock, /* lock */
diff --git a/src/H5FDmpio.c b/src/H5FDmpio.c
index 3d2e0cf..e85a8c2 100644
--- a/src/H5FDmpio.c
+++ b/src/H5FDmpio.c
@@ -123,6 +123,8 @@ static const H5FD_class_mpi_t H5FD_mpio_g = {
H5FD__mpio_get_handle, /*get_handle */
H5FD__mpio_read, /*read */
H5FD__mpio_write, /*write */
+ NULL, /*read_vector */
+ NULL, /*write_vector */
H5FD__mpio_flush, /*flush */
H5FD__mpio_truncate, /*truncate */
NULL, /*lock */
diff --git a/src/H5FDmulti.c b/src/H5FDmulti.c
index 72f4da5..3c31d72 100644
--- a/src/H5FDmulti.c
+++ b/src/H5FDmulti.c
@@ -166,6 +166,8 @@ static const H5FD_class_t H5FD_multi_g = {
H5FD_multi_get_handle, /*get_handle */
H5FD_multi_read, /*read */
H5FD_multi_write, /*write */
+ NULL, /*read_vector */
+ NULL, /*write_vector */
H5FD_multi_flush, /*flush */
H5FD_multi_truncate, /*truncate */
H5FD_multi_lock, /*lock */
diff --git a/src/H5FDprivate.h b/src/H5FDprivate.h
index 2e3d3ce..3bea38b 100644
--- a/src/H5FDprivate.h
+++ b/src/H5FDprivate.h
@@ -137,6 +137,12 @@ H5_DLL herr_t H5FD_set_feature_flags(H5FD_t *file, unsigned long feature_flags);
H5_DLL herr_t H5FD_get_fs_type_map(const H5FD_t *file, H5FD_mem_t *type_map);
H5_DLL herr_t H5FD_read(H5FD_t *file, H5FD_mem_t type, haddr_t addr, size_t size, void *buf/*out*/);
H5_DLL herr_t H5FD_write(H5FD_t *file, H5FD_mem_t type, haddr_t addr, size_t size, const void *buf);
+H5_DLL herr_t H5FD_read_vector(H5FD_t *file, uint32_t count,
+ H5FD_mem_t types[], haddr_t addrs[], size_t sizes[],
+ void * bufs[] /* out */);
+H5_DLL herr_t H5FD_write_vector(H5FD_t *file, uint32_t count,
+ H5FD_mem_t types[], haddr_t addrs[], size_t sizes[],
+ void * bufs[] /* out */);
H5_DLL herr_t H5FD_flush(H5FD_t *file, hbool_t closing);
H5_DLL herr_t H5FD_truncate(H5FD_t *file, hbool_t closing);
H5_DLL herr_t H5FD_lock(H5FD_t *file, hbool_t rw);
diff --git a/src/H5FDpublic.h b/src/H5FDpublic.h
index 61bf212..b740899 100644
--- a/src/H5FDpublic.h
+++ b/src/H5FDpublic.h
@@ -298,6 +298,12 @@ typedef struct H5FD_class_t {
haddr_t addr, size_t size, void *buffer);
herr_t (*write)(H5FD_t *file, H5FD_mem_t type, hid_t dxpl,
haddr_t addr, size_t size, const void *buffer);
+ herr_t (*read_vector)(H5FD_t *file, hid_t dxpl, uint32_t count,
+ H5FD_mem_t types[], haddr_t addrs[],
+ size_t sizes[], void * bufs[]);
+ herr_t (*write_vector)(H5FD_t *file, hid_t dxpl, uint32_t count,
+ H5FD_mem_t types[], haddr_t addrs[],
+ size_t sizes[], void * bufs[]);
herr_t (*flush)(H5FD_t *file, hid_t dxpl_id, hbool_t closing);
herr_t (*truncate)(H5FD_t *file, hid_t dxpl_id, hbool_t closing);
herr_t (*lock)(H5FD_t *file, hbool_t rw);
@@ -381,6 +387,12 @@ H5_DLL herr_t H5FDread(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id,
haddr_t addr, size_t size, void *buf/*out*/);
H5_DLL herr_t H5FDwrite(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id,
haddr_t addr, size_t size, const void *buf);
+H5_DLL herr_t H5FDread_vector(H5FD_t *file, hid_t dxpl_id, uint32_t count,
+ H5FD_mem_t types[], haddr_t addrs[],
+ size_t sizes[], void * bufs[] /* out */);
+H5_DLL herr_t H5FDwrite_vector(H5FD_t *file, hid_t dxpl_id, uint32_t count,
+ H5FD_mem_t types[], haddr_t addrs[],
+ size_t sizes[], void * bufs[] /* in */);
H5_DLL herr_t H5FDflush(H5FD_t *file, hid_t dxpl_id, hbool_t closing);
H5_DLL herr_t H5FDtruncate(H5FD_t *file, hid_t dxpl_id, hbool_t closing);
H5_DLL herr_t H5FDlock(H5FD_t *file, hbool_t rw);
diff --git a/src/H5FDros3.c b/src/H5FDros3.c
index d99272c..1432e02 100644
--- a/src/H5FDros3.c
+++ b/src/H5FDros3.c
@@ -268,6 +268,8 @@ static const H5FD_class_t H5FD_ros3_g = {
H5FD_ros3_get_handle, /* get_handle */
H5FD_ros3_read, /* read */
H5FD_ros3_write, /* write */
+ NULL, /* read_vector */
+ NULL, /* write_vector */
NULL, /* flush */
H5FD_ros3_truncate, /* truncate */
H5FD_ros3_lock, /* lock */
diff --git a/src/H5FDsec2.c b/src/H5FDsec2.c
index 3551905..cdc3d83 100644
--- a/src/H5FDsec2.c
+++ b/src/H5FDsec2.c
@@ -167,6 +167,8 @@ static const H5FD_class_t H5FD_sec2_g = {
H5FD_sec2_get_handle, /* get_handle */
H5FD_sec2_read, /* read */
H5FD_sec2_write, /* write */
+ NULL, /* read_vector */
+ NULL, /* write_vector */
NULL, /* flush */
H5FD_sec2_truncate, /* truncate */
H5FD_sec2_lock, /* lock */
diff --git a/src/H5FDsplitter.c b/src/H5FDsplitter.c
index 4ed3c4a..fc056f1 100644
--- a/src/H5FDsplitter.c
+++ b/src/H5FDsplitter.c
@@ -160,6 +160,8 @@ static const H5FD_class_t H5FD_splitter_g = {
H5FD_splitter_get_handle, /* get_handle */
H5FD_splitter_read, /* read */
H5FD_splitter_write, /* write */
+ NULL, /* read_vector */
+ NULL, /* write_vector */
H5FD_splitter_flush, /* flush */
H5FD_splitter_truncate, /* truncate */
H5FD_splitter_lock, /* lock */
diff --git a/src/H5FDstdio.c b/src/H5FDstdio.c
index d29a1b4..0d4188a 100644
--- a/src/H5FDstdio.c
+++ b/src/H5FDstdio.c
@@ -205,6 +205,8 @@ static const H5FD_class_t H5FD_stdio_g = {
H5FD_stdio_get_handle, /* get_handle */
H5FD_stdio_read, /* read */
H5FD_stdio_write, /* write */
+ NULL, /* read_vector */
+ NULL, /* write_vector */
H5FD_stdio_flush, /* flush */
H5FD_stdio_truncate, /* truncate */
H5FD_stdio_lock, /* lock */
diff --git a/test/vfd.c b/test/vfd.c
index d94aec6..bcc5bdb 100644
--- a/test/vfd.c
+++ b/test/vfd.c
@@ -3268,7 +3268,737 @@ error:
#undef SPLITTER_TEST_FAULT
+
+/*****************************************************************************
+ *
+ * Function setup_rand()
+ *
+ * Purpose: Use gettimeofday() to obtain a seed for rand(), print the
+ * seed to stdout, and then pass it to srand().
+ *
+ * This is a version of the same routine in
+ * testpar/t_cache.c modified for use in serial tests.
+ *
+ * Return: void.
+ *
+ * Programmer: JRM -- 6/20/20
+ *
+ * Modifications:
+ *
+ * None.
+ *
+ *****************************************************************************/
+static void
+setup_rand(void)
+{
+ hbool_t use_predefined_seed = FALSE;
+ unsigned predefined_seed = 18669;
+ unsigned seed;
+ struct timeval tv;
+
+ if ( use_predefined_seed ) {
+
+ seed = predefined_seed;
+
+ HDfprintf(stdout, "\n%s: predefined_seed = %d.\n\n", FUNC, seed);
+ HDfflush(stdout);
+
+ HDsrand(seed);
+
+ } else {
+
+ if ( HDgettimeofday(&tv, NULL) != 0 ) {
+
+ HDfprintf(stdout,
+ "\n%s: gettimeofday() failed -- srand() not called.\n\n",
+ FUNC);
+ HDfflush(stdout);
+
+ } else {
+
+ seed = (unsigned)tv.tv_usec;
+
+ HDfprintf(stdout, "\n%s: seed = %d.\n\n", FUNC, seed);
+ HDfflush(stdout);
+
+ HDsrand(seed);
+ }
+ }
+
+ return;
+
+} /* setup_rand() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_vector_io__setup_v
+ *
+ * Purpose: Construct and initialize a vector of I/O requests used
+ * to test vector I/O. Note that while the vectors are
+ * allocated and initialized, they are not assigned
+ * base addresses.
+ *
+ * All arrays parameters are presumed to be of length
+ * count.
+ *
+ * Return: Return TRUE if sucessful, and FALSE if any errors
+ * are encountered.
+ *
+ * Programmer: John Mainzer
+ * 6/21/20
+ *
+ * Modifications:
+ *
+ * None.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static hbool_t
+test_vector_io__setup_v(uint32_t count, H5FD_mem_t types[], haddr_t addrs[],
+ size_t sizes[], void * write_bufs[], void * read_bufs[],
+ char base_fill_char)
+{
+ hbool_t result = TRUE; /* will set to FALSE on failure */
+ char fill_char = base_fill_char;
+ uint32_t i;
+ uint32_t j;
+ H5FD_mem_t mem_types[6] = {H5FD_MEM_SUPER, H5FD_MEM_BTREE, H5FD_MEM_DRAW,
+ H5FD_MEM_GHEAP, H5FD_MEM_LHEAP, H5FD_MEM_OHDR};
+
+ /* set the arrays of pointers to the write and read buffers to NULL,
+ * so that we can release memory on failure.
+ */
+ for ( i = 0; i < count; i++ ) {
+
+ write_bufs[i] = NULL;
+ read_bufs[i] = NULL;
+ }
+
+ for ( i = 0; i < count; i++ ) {
+
+ types[i] = mem_types[i % 6];
+
+ addrs[i] = HADDR_UNDEF;
+
+ sizes[i] = (size_t)((rand() & 1023) + 1);
+
+ write_bufs[i] = HDmalloc(sizes[i] + 1);
+ read_bufs[i] = HDmalloc(sizes[i] + 1);
+
+ if ( ( NULL == write_bufs[i] ) || ( NULL == read_bufs[i] ) ) {
+
+ HDfprintf(stderr, "%s: can't malloc read / write bufs.\n", FUNC);
+ result = FALSE;
+ break;
+ }
+
+ for ( j = 0; j < sizes[i]; j++ ) {
+
+ ((char *)(write_bufs[i]))[j] = fill_char;
+ ((char *)(read_bufs[i]))[j] = '\0';
+ }
+
+ ((char *)(write_bufs[i]))[sizes[i]] = '\0';
+ ((char *)(read_bufs[i]))[sizes[i]] = '\0';
+
+ fill_char++;
+ }
+
+ if ( ! result ) { /* free buffers */
+
+ for ( i = 0; i < count; i++ ) {
+
+ if ( write_bufs[i] ) {
+
+ HDfree(write_bufs[i]);
+ write_bufs[i] = NULL;
+ }
+
+ if ( read_bufs[i] ) {
+
+ HDfree(read_bufs[i]);
+ read_bufs[i] = NULL;
+ }
+ }
+ }
+
+ return(result);
+
+} /* end test_vector_io__setup_v() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_vector_io__read_v_indiv
+ *
+ * Purpose: Read the supplied vector as a sequence of individual
+ * reads.
+ *
+ * All arrays parameters are presumed to be of length
+ * count.
+ *
+ * Return: Return TRUE if sucessful, and FALSE if any errors
+ * are encountered.
+ *
+ * Programmer: John Mainzer
+ * 6/21/20
+ *
+ * Modifications:
+ *
+ * None.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static hbool_t
+test_vector_io__read_v_indiv(H5FD_t * lf, uint32_t count, H5FD_mem_t types[],
+ haddr_t addrs[], size_t sizes[], void * read_bufs[])
+{
+ hbool_t result = TRUE; /* will set to FALSE on failure */
+ hbool_t verbose = FALSE;
+ uint32_t i;
+
+ for ( i = 0; i < count; i++ ) {
+
+ if ( H5FDread(lf, types[i], H5P_DEFAULT, addrs[i], sizes[i],
+ read_bufs[i]) < 0 ) {
+
+ if ( verbose ) {
+
+ HDfprintf(stdout, "%s: HDread() failed on entry %d.\n",
+ FUNC, i);
+ }
+ result = FALSE;
+ break;
+ }
+ }
+
+ return(result);
+
+} /* end test_vector_io__read_v_indiv() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_vector_io__write_v_indiv
+ *
+ * Purpose: Write the supplied vector as a sequence of individual
+ * writes.
+ *
+ * All arrays parameters are presumed to be of length
+ * count.
+ *
+ * Return: Return TRUE if sucessful, and FALSE if any errors
+ * are encountered.
+ *
+ * Programmer: John Mainzer
+ * 6/21/20
+ *
+ * Modifications:
+ *
+ * None.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static hbool_t
+test_vector_io__write_v_indiv(H5FD_t * lf, uint32_t count, H5FD_mem_t types[],
+ haddr_t addrs[], size_t sizes[], void * write_bufs[])
+{
+ hbool_t result = TRUE; /* will set to FALSE on failure */
+ hbool_t verbose = FALSE;
+ uint32_t i;
+
+ for ( i = 0; i < count; i++ ) {
+
+ if ( H5FDwrite(lf, types[i], H5P_DEFAULT, addrs[i], sizes[i],
+ write_bufs[i]) < 0 ) {
+
+ if ( verbose ) {
+
+ HDfprintf(stdout, "%s: HDwrite() failed on entry %d.\n",
+ FUNC, i);
+ }
+ result = FALSE;
+ break;
+ }
+ }
+
+ return(result);
+
+} /* end test_vector_io__write_v_indiv() */
+
+
+/*-------------------------------------------------------------------------
+ *
+ * Function: test_vector_io__verify_v
+ *
+ * Purpose: Verify that the read and write buffers of the supplied
+ * vectors are identical.
+ *
+ * Return: TRUE if the read and write vectors are identical, and
+ * FALSE otherwise.
+ *
+ * Programmer: John Mainzer
+ * 6/21/20
+ *
+ * Changes: None.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static hbool_t
+test_vector_io__verify_v(uint32_t count, H5FD_mem_t types[],
+ size_t sizes[], void * write_bufs[], void * read_bufs[], const char * name)
+{
+ hbool_t identical = TRUE;
+ hbool_t verbose = FALSE;
+ uint32_t i;
+ uint32_t j;
+ uint32_t buf_size;
+ char * w_buf;
+ char * r_buf;
+ const char * mem_type_names[7] = {"H5FD_MEM_DEFAULT", "H5FD_MEM_SUPER",
+ "H5FD_MEM_BTREE", "H5FD_MEM_DRAW",
+ "H5FD_MEM_GHEAP", "H5FD_MEM_LHEAP",
+ "H5FD_MEM_OHDR"};
+
+ i = 0;
+
+ while ( ( i < count ) && ( identical ) ) {
+
+ buf_size = (uint32_t)(sizes[i]);
+
+ w_buf = (char *)(write_bufs[i]);
+ r_buf = (char *)(read_bufs[i]);
+
+ j = 0;
+ while ( ( j < buf_size ) && ( identical ) ) {
+
+ if ( w_buf[j] != r_buf[j] ) {
+
+ identical = FALSE;
+
+ if ( verbose ) {
+
+ HDfprintf(stdout,
+ "\n\nread/write buf mismatch in vector/entry");
+ HDfprintf(stdout,
+ "\"%s\"/%d at offset %d/%d w/r = %c/%c type = %s\n\n",
+ name, i, j, buf_size, w_buf[j], r_buf[j],
+ mem_type_names[types[i]]);
+ }
+ }
+ j++;
+ }
+ i++;
+ }
+
+ return(identical);
+
+} /* end test_vector_io__verify_v() */
+
+
+/*-------------------------------------------------------------------------
+ *
+ * Function: test_vector_io__dump_test_vectors
+ *
+ * Purpose: Print a set of test vectors to stdout.
+ * Vectors are assumed to be of length count, and
+ * buffers must be either NULL, or null terminate strings
+ * of char.
+ *
+ * Return: void.
+ *
+ * Programmer: John Mainzer
+ * 6/21/20
+ *
+ * Changes: None.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static void
+test_vector_io__dump_test_vectors(uint32_t count, H5FD_mem_t types[],
+ haddr_t addrs[], size_t sizes[], void * write_bufs[], void * read_bufs[],
+ const char * name)
+{
+ uint32_t i;
+ const char * mem_type_names[7] = {"H5FD_MEM_DEFAULT", "H5FD_MEM_SUPER",
+ "H5FD_MEM_BTREE", "H5FD_MEM_DRAW",
+ "H5FD_MEM_GHEAP", "H5FD_MEM_LHEAP",
+ "H5FD_MEM_OHDR"};
+ char * w_buf;
+ char * r_buf;
+
+ HDfprintf(stdout, "\n\nDumping test vector \"%s\" of length %d\n\n",
+ name, count);
+
+ for ( i = 0; i < count; i++ ) {
+
+ HDassert((H5FD_MEM_DEFAULT <= types[i]) &&
+ (types[i] <= H5FD_MEM_OHDR));
+
+ w_buf = (char *)(write_bufs[i]);
+
+ if ( read_bufs ) {
+
+ r_buf = (char *)(read_bufs[i]);
+
+ } else {
+
+ r_buf = NULL;
+ }
+
+ HDfprintf(stdout,
+ "%d: addr/len = %lld/%lld, type = %s, w_buf = \"%s\"\n",
+ i, (long long)(addrs[i]), (long long)(sizes[i]),
+ mem_type_names[types[i]], w_buf);
+
+ if ( r_buf ) {
+
+ HDfprintf(stdout, " r_buf = \"%s\"\n", r_buf);
+ }
+ }
+
+ return;
+
+} /* end test_vector_io__dump_test_vectors() */
+
+/*-------------------------------------------------------------------------
+ * Function: test_vector_io
+ *
+ * Purpose: Test I/O using the vector I/O VFD public VFD calls.
+ *
+ * Test proceeds as follows:
+ *
+ * 1) read / write vectors and verify results
+ *
+ * 2) write individual / read vector and verify results
+ *
+ * 3) write vector / read individual and verify results
+ *
+ * 4) Close and then re-open the file, verify data written
+ * above.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ * Programmer: John Mainzer
+ * 6/20/20
+ *
+ * Changes: None.
+ *
+ *-------------------------------------------------------------------------
+ */
+#define VECTOR_LEN 16
+
+static herr_t
+test_vector_io(const char * vfd_name)
+{
+ char test_title[80];
+ hbool_t verbose = FALSE;
+ hid_t fapl_id = -1; /* file access property list ID */
+ haddr_t eoa; /* file eoa */
+ char filename[1024]; /* filename */
+ char * buf; /* tmp ptr to buf */
+ unsigned flags = 0; /* file open flags */
+ H5FD_t * lf; /* VFD struct ptr */
+ uint32_t i; /* index */
+ uint32_t j; /* index */
+ uint32_t count = VECTOR_LEN; /* length of vectors */
+ H5FD_mem_t types_0[VECTOR_LEN]; /* types vector */
+ H5FD_mem_t types_1[VECTOR_LEN]; /* types vector */
+ H5FD_mem_t types_2[VECTOR_LEN]; /* types vector */
+ haddr_t addrs_0[VECTOR_LEN]; /* addresses vector */
+ haddr_t addrs_1[VECTOR_LEN]; /* addresses vector */
+ haddr_t addrs_2[VECTOR_LEN]; /* addresses vector */
+ size_t sizes_0[VECTOR_LEN]; /* sizes vector */
+ size_t sizes_1[VECTOR_LEN]; /* sizes vector */
+ size_t sizes_2[VECTOR_LEN]; /* sizes vector */
+ void * write_bufs_0[VECTOR_LEN]; /* write bufs vector */
+ void * write_bufs_1[VECTOR_LEN]; /* write bufs vector */
+ void * write_bufs_2[VECTOR_LEN]; /* write bufs vector */
+ void * read_bufs_0[VECTOR_LEN]; /* read bufs vector */
+ void * read_bufs_1[VECTOR_LEN]; /* read bufs vector */
+ void * read_bufs_2[VECTOR_LEN]; /* read bufs vector */
+
+ sprintf(test_title, "vector I/O with %s VFD", vfd_name);
+
+ TESTING(test_title);
+
+ /* Set property list and file name for target driver */
+
+ if((fapl_id = H5Pcreate(H5P_FILE_ACCESS)) < 0)
+ TEST_ERROR;
+
+ if ( strcmp(vfd_name, "sec2") == 0 ) {
+
+ if(H5Pset_fapl_sec2(fapl_id) < 0)
+ TEST_ERROR;
+
+ h5_fixname(FILENAME[0], fapl_id, filename, sizeof(filename));
+
+ } else if ( strcmp(vfd_name, "stdio") == 0 ) {
+
+ if(H5Pset_fapl_stdio(fapl_id) < 0)
+ TEST_ERROR;
+
+ h5_fixname(FILENAME[7], fapl_id, filename, sizeof filename);
+
+ } else {
+
+ HDfprintf(stdout, "un-supported VFD\n");
+ TEST_ERROR
+ }
+
+ /* setup the test vectors -- note that addresses are not set until
+ * we allocate space via the file driver.
+ */
+ if ( ! ( test_vector_io__setup_v(count, types_0, addrs_0, sizes_0,
+ write_bufs_0, read_bufs_0, 'a') &&
+ test_vector_io__setup_v(count, types_1, addrs_1, sizes_1,
+ write_bufs_1, read_bufs_1, 'e') &&
+ test_vector_io__setup_v(count, types_2, addrs_2, sizes_2,
+ write_bufs_2, read_bufs_2, 'A') ) )
+ TEST_ERROR;
+
+
+ flags = H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC;
+
+ if ( NULL == (lf = H5FDopen(filename, flags, fapl_id, HADDR_UNDEF)))
+ TEST_ERROR;
+
+ /* allocate space for the data in the test vectors */
+ for ( i = 0; i < count; i++ ) {
+
+ addrs_0[i] = H5FDalloc(lf, types_0[i], H5P_DEFAULT,
+ (hsize_t)(sizes_0[i]));
+ addrs_1[i] = H5FDalloc(lf, types_1[i], H5P_DEFAULT,
+ (hsize_t)(sizes_1[i]));
+ addrs_2[i] = H5FDalloc(lf, types_2[i], H5P_DEFAULT,
+ (hsize_t)(sizes_2[i]));
+
+ if ( ( addrs_0[i] == HADDR_UNDEF ) ||
+ ( addrs_1[i] == HADDR_UNDEF ) ||
+ ( addrs_2[i] == HADDR_UNDEF ) )
+ TEST_ERROR;
+ }
+
+ if ( verbose ) {
+
+ test_vector_io__dump_test_vectors(count, types_0, addrs_0, sizes_0,
+ write_bufs_0, NULL, "zero");
+
+ test_vector_io__dump_test_vectors(count, types_1, addrs_1, sizes_1,
+ write_bufs_1, NULL, "one");
+
+ test_vector_io__dump_test_vectors(count, types_2, addrs_2, sizes_2,
+ write_bufs_2, NULL, "two");
+ }
+
+
+ /* write and then read using vector I/O. First, read/write vector
+ * of length 1, then of length 2, then remainder of vector
+ */
+ if ( H5FDwrite_vector(lf, H5P_DEFAULT, 1, &(types_0[0]), &(addrs_0[0]),
+ &(sizes_0[0]), &(write_bufs_0[0])) < 0 )
+ TEST_ERROR;
+
+ if ( H5FDread_vector(lf, H5P_DEFAULT, 1, &(types_0[0]), &(addrs_0[0]),
+ &(sizes_0[0]), &(read_bufs_0[0])) < 0 )
+ TEST_ERROR;
+
+ if ( H5FDwrite_vector(lf, H5P_DEFAULT, 2, &(types_0[1]), &(addrs_0[1]),
+ &(sizes_0[1]), &(write_bufs_0[1])) < 0 )
+ TEST_ERROR;
+
+ if ( H5FDread_vector(lf, H5P_DEFAULT, 2, &(types_0[1]), &(addrs_0[1]),
+ &(sizes_0[1]), &(read_bufs_0[1])) < 0 )
+ TEST_ERROR;
+
+ if ( H5FDwrite_vector(lf, H5P_DEFAULT, count - 3, &(types_0[3]),
+ &(addrs_0[3]), &(sizes_0[3]), &(write_bufs_0[3])) < 0 )
+ TEST_ERROR;
+
+ if ( H5FDread_vector(lf, H5P_DEFAULT, count - 3, &(types_0[3]),
+ &(addrs_0[3]), &(sizes_0[3]), &(read_bufs_0[3])) < 0 )
+ TEST_ERROR;
+
+
+ /* verify that the expected data is read */
+ if ( ! test_vector_io__verify_v(count, types_0, sizes_0,
+ write_bufs_0, read_bufs_0, "zero") )
+ TEST_ERROR;
+
+
+ /* write the contents of a vector individually, and then read it back
+ * in several vector reads.
+ */
+ if ( ! test_vector_io__write_v_indiv(lf, count, types_1, addrs_1,
+ sizes_1, write_bufs_1) )
+ TEST_ERROR;
+
+ if ( H5FDread_vector(lf, H5P_DEFAULT, 1, &(types_1[0]), &(addrs_1[0]),
+ &(sizes_1[0]), &(read_bufs_1[0])) < 0 )
+ TEST_ERROR;
+
+ if ( H5FDread_vector(lf, H5P_DEFAULT, 2, &(types_1[1]), &(addrs_1[1]),
+ &(sizes_1[1]), &(read_bufs_1[1])) < 0 )
+ TEST_ERROR;
+
+ if ( H5FDread_vector(lf, H5P_DEFAULT, count - 3, &(types_1[3]),
+ &(addrs_1[3]), &(sizes_1[3]), &(read_bufs_1[3])) < 0 )
+ TEST_ERROR;
+
+
+ /* verify that the expected data is read */
+ if ( ! test_vector_io__verify_v(count, types_1, sizes_1,
+ write_bufs_1, read_bufs_1, "one") )
+ TEST_ERROR;
+
+
+ /* Write the contents of a vector as several vector writes, then
+ * read it back in idividual reads.
+ */
+ if ( H5FDwrite_vector(lf, H5P_DEFAULT, 1, &(types_2[0]), &(addrs_2[0]),
+ &(sizes_2[0]), &(write_bufs_2[0])) < 0 )
+ TEST_ERROR;
+
+ if ( H5FDwrite_vector(lf, H5P_DEFAULT, 2, &(types_2[1]), &(addrs_2[1]),
+ &(sizes_2[1]), &(write_bufs_2[1])) < 0 )
+ TEST_ERROR;
+
+ if ( H5FDwrite_vector(lf, H5P_DEFAULT, count - 3, &(types_2[3]),
+ &(addrs_2[3]), &(sizes_2[3]), &(write_bufs_2[3])) < 0 )
+ TEST_ERROR;
+
+ if ( ! test_vector_io__read_v_indiv(lf, count, types_2, addrs_2,
+ sizes_2, read_bufs_2) )
+ TEST_ERROR;
+
+
+ /* verify that the expected data is read */
+ if ( ! test_vector_io__verify_v(count, types_2, sizes_2,
+ write_bufs_2, read_bufs_2, "two") )
+ TEST_ERROR;
+
+ /* make note of eoa -- needed after we re-open the file */
+ if ( HADDR_UNDEF == (eoa = H5FDget_eoa(lf, H5FD_MEM_DEFAULT)))
+ TEST_ERROR;
+
+ /* close the file and then re-open it */
+ if ( H5FDclose(lf) < 0 )
+ TEST_ERROR;
+
+ flags = H5F_ACC_RDWR ;
+
+ if ( NULL == (lf = H5FDopen(filename, flags, fapl_id, HADDR_UNDEF)))
+ TEST_ERROR;
+
+ /* The EOA is set to 0 on open. To avoid errors, we must set it
+ * to its correct value before we do any reads.
+ *
+ * Note: In the context of using the VFD layer without the HDF5
+ * library on top, this doesn't make much sense. Consider
+ * adding an open flag that sets the EOA to the current file
+ * size.
+ */
+ if ( H5FDset_eoa(lf, H5FD_MEM_DEFAULT, eoa) < 0 )
+ TEST_ERROR;
+
+
+ /* Null the read vectors */
+ for ( i = 0 ; i < count; i++ ) {
+
+ buf = read_bufs_0[i];
+ for ( j = 0; j < sizes_0[i]; j++ ) {
+ buf[j] = '\0';
+ }
+
+ buf = read_bufs_1[i];
+ for ( j = 0; j < sizes_1[i]; j++ ) {
+ buf[j] = '\0';
+ }
+
+ buf = read_bufs_2[i];
+ for ( j = 0; j < sizes_2[i]; j++ ) {
+ buf[j] = '\0';
+ }
+ }
+
+
+ /* read the contents of the file */
+ if ( H5FDread_vector(lf, H5P_DEFAULT, count, types_0,
+ addrs_0, sizes_0, read_bufs_0) < 0 )
+ TEST_ERROR;
+
+ if ( H5FDread_vector(lf, H5P_DEFAULT, count, types_1,
+ addrs_1, sizes_1, read_bufs_1) < 0 )
+ TEST_ERROR;
+
+ if ( H5FDread_vector(lf, H5P_DEFAULT, count, types_2,
+ addrs_2, sizes_2, read_bufs_2) < 0 )
+ TEST_ERROR;
+
+ /* verify the contents. */
+ if ( ! test_vector_io__verify_v(count, types_0, sizes_0,
+ write_bufs_0, read_bufs_0, "zero-") )
+ TEST_ERROR;
+
+ if ( ! test_vector_io__verify_v(count, types_1, sizes_1,
+ write_bufs_1, read_bufs_1, "one-") )
+ TEST_ERROR;
+
+ if ( ! test_vector_io__verify_v(count, types_2, sizes_2,
+ write_bufs_2, read_bufs_2, "two-") )
+ TEST_ERROR;
+
+
+ if ( H5FDclose(lf) < 0 )
+ TEST_ERROR;
+
+ h5_delete_test_file(FILENAME[0], fapl_id);
+
+ /* Close the fapl */
+ if(H5Pclose(fapl_id) < 0)
+ TEST_ERROR;
+
+ /* discard the read and write buffers */
+
+ for ( i = 0; i < count; i++ ) {
+
+ HDfree(write_bufs_0[i]);
+ write_bufs_0[i] = NULL;
+
+ HDfree(write_bufs_1[i]);
+ write_bufs_1[i] = NULL;
+
+ HDfree(write_bufs_2[i]);
+ write_bufs_2[i] = NULL;
+
+ HDfree(read_bufs_0[i]);
+ read_bufs_0[i] = NULL;
+
+ HDfree(read_bufs_1[i]);
+ read_bufs_1[i] = NULL;
+
+ HDfree(read_bufs_2[i]);
+ read_bufs_2[i] = NULL;
+ }
+
+ PASSED();
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Pclose(fapl_id);
+ H5FDclose(lf);
+ } H5E_END_TRY;
+ return -1;
+} /* end test_vector_io() */
+
+
/*-------------------------------------------------------------------------
* Function: main
*
@@ -3288,19 +4018,24 @@ main(void)
HDprintf("Testing basic Virtual File Driver functionality.\n");
- nerrors += test_sec2() < 0 ? 1 : 0;
- nerrors += test_core() < 0 ? 1 : 0;
- nerrors += test_direct() < 0 ? 1 : 0;
- nerrors += test_family() < 0 ? 1 : 0;
- nerrors += test_family_compat() < 0 ? 1 : 0;
- nerrors += test_family_member_fapl() < 0 ? 1 : 0;
- nerrors += test_multi() < 0 ? 1 : 0;
- nerrors += test_multi_compat() < 0 ? 1 : 0;
- nerrors += test_log() < 0 ? 1 : 0;
- nerrors += test_stdio() < 0 ? 1 : 0;
- nerrors += test_windows() < 0 ? 1 : 0;
- nerrors += test_ros3() < 0 ? 1 : 0;
- nerrors += test_splitter() < 0 ? 1 : 0;
+ setup_rand();
+
+ nerrors += test_sec2() < 0 ? 1 : 0;
+ nerrors += test_core() < 0 ? 1 : 0;
+ nerrors += test_direct() < 0 ? 1 : 0;
+ nerrors += test_family() < 0 ? 1 : 0;
+ nerrors += test_family_compat() < 0 ? 1 : 0;
+ nerrors += test_family_member_fapl() < 0 ? 1 : 0;
+ nerrors += test_multi() < 0 ? 1 : 0;
+ nerrors += test_multi_compat() < 0 ? 1 : 0;
+ nerrors += test_log() < 0 ? 1 : 0;
+ nerrors += test_stdio() < 0 ? 1 : 0;
+ nerrors += test_windows() < 0 ? 1 : 0;
+ nerrors += test_ros3() < 0 ? 1 : 0;
+ nerrors += test_splitter() < 0 ? 1 : 0;
+ nerrors += test_vector_io("sec2") < 0 ? 1 : 0;
+ nerrors += test_vector_io("stdio") < 0 ? 1 : 0;
+
if(nerrors) {
HDprintf("***** %d Virtual File Driver TEST%s FAILED! *****\n",