diff options
author | mainzer <mainzer#hdfgroup.org> | 2020-06-29 16:09:40 (GMT) |
---|---|---|
committer | mainzer <mainzer#hdfgroup.org> | 2020-06-29 16:09:40 (GMT) |
commit | 5a6d9b3a4e12cc399ce27361755f0c8d069e256b (patch) | |
tree | 5967c6050e8fc4295c3d5090423bb71e562c135a | |
parent | 96e912c842d0b2c517df78614f319a68c47efd61 (diff) | |
download | hdf5-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.c | 151 | ||||
-rw-r--r-- | src/H5FDcore.c | 2 | ||||
-rw-r--r-- | src/H5FDdirect.c | 2 | ||||
-rw-r--r-- | src/H5FDfamily.c | 2 | ||||
-rw-r--r-- | src/H5FDhdfs.c | 2 | ||||
-rw-r--r-- | src/H5FDint.c | 253 | ||||
-rw-r--r-- | src/H5FDlog.c | 2 | ||||
-rw-r--r-- | src/H5FDmirror.c | 2 | ||||
-rw-r--r-- | src/H5FDmpio.c | 2 | ||||
-rw-r--r-- | src/H5FDmulti.c | 2 | ||||
-rw-r--r-- | src/H5FDprivate.h | 6 | ||||
-rw-r--r-- | src/H5FDpublic.h | 12 | ||||
-rw-r--r-- | src/H5FDros3.c | 2 | ||||
-rw-r--r-- | src/H5FDsec2.c | 2 | ||||
-rw-r--r-- | src/H5FDsplitter.c | 2 | ||||
-rw-r--r-- | src/H5FDstdio.c | 2 | ||||
-rw-r--r-- | test/vfd.c | 761 |
17 files changed, 1194 insertions, 13 deletions
@@ -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 */ @@ -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", |