summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MANIFEST1
-rw-r--r--test/Makefile.am4
-rw-r--r--test/accum.c224
3 files changed, 227 insertions, 2 deletions
diff --git a/MANIFEST b/MANIFEST
index ae8e0a3..960fcde 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -884,6 +884,7 @@
./test/H5srcdir_str.h.in
./test/Makefile.am
./test/accum.c
+./test/accum_swmr_reader.c
./test/app_ref.c
./test/bad_compound.h5
./test/be_data.h5
diff --git a/test/Makefile.am b/test/Makefile.am
index 380043a..d3f9df6 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -53,12 +53,13 @@ TEST_PROG= testhdf5 cache cache_api cache_tagging lheap ohdr stab gheap \
# List programs to be built when testing here.
# error_test and err_compat are built at the same time as the other tests, but executed by testerror.sh.
# tcheck_version is used by testcheck_version.sh.
+# accum_swmr_reader is used by accum.c.
# links_env is used by testlinks_env.sh
# 'make check' doesn't run them directly, so they are not included in TEST_PROG.
# Also build testmeta, which is used for timings test. It builds quickly,
# and this lets automake keep all its test programs in one place.
check_PROGRAMS=$(TEST_PROG) error_test err_compat tcheck_version \
- testmeta \
+ testmeta accum_swmr_reader \
links_env
if HAVE_SHARED_CONDITIONAL
check_PROGRAMS+= plugin
@@ -162,6 +163,7 @@ CHECK_CLEANFILES+=accum.h5 cmpd_dset.h5 compact_dataset.h5 dataset.h5 dset_offse
split_get_file_image_test-m.h5 split_get_file_image_test-r.h5 \
file_image_core_test.h5.copy unregister_filter_1.h5 unregister_filter_2.h5 \
vds_virt.h5 vds_dapl.h5 vds_src_[0-1].h5 \
+ accum_swmr_big.h5 \
cache_logging.h5 cache_logging.out \
swmr[0-2].h5
# Sources for testhdf5 executable
diff --git a/test/accum.c b/test/accum.c
index 3b9f9e6..1fcd051 100644
--- a/test/accum.c
+++ b/test/accum.c
@@ -18,13 +18,20 @@
#include "h5test.h"
#define H5F_FRIEND /*suppress error about including H5Fpkg */
+#define H5FD_FRIEND /*suppress error about including H5FDpkg */
+#define H5FD_TESTING
#include "H5Fpkg.h"
-#include "H5FDprivate.h"
+#include "H5FDpkg.h"
#include "H5Iprivate.h"
/* Filename */
#define FILENAME "accum.h5"
+/* The file name is the same as the define in accum_swmr_reader.c */
+#define SWMR_FILENAME "accum_swmr_big.h5"
+/* The reader forked by test_swmr_write_big() */
+#define SWMR_READER "accum_swmr_reader"
+
/* "big" I/O test values */
#define BIG_BUF_SIZE (6 * 1024 * 1024)
@@ -50,6 +57,7 @@ unsigned test_read_after(const H5F_io_info_t *fio_info);
unsigned test_free(const H5F_io_info_t *fio_info);
unsigned test_big(const H5F_io_info_t *fio_info);
unsigned test_random_write(const H5F_io_info_t *fio_info);
+unsigned test_swmr_write_big(hbool_t newest_format);
/* Helper Function Prototypes */
void accum_printf(void);
@@ -124,6 +132,10 @@ main(void)
if(H5Fclose(fid) < 0) TEST_ERROR
HDremove(FILENAME);
+ /* This test uses a different file */
+ nerrors += test_swmr_write_big(TRUE);
+ nerrors += test_swmr_write_big(FALSE);
+
if(nerrors)
goto error;
puts("All metadata accumulator tests passed.");
@@ -1777,6 +1789,216 @@ error:
return 1;
} /* end test_random_write() */
+/*-------------------------------------------------------------------------
+ * Function: test_swmr_write_big
+ *
+ * Purpose: A SWMR test: verifies that writing "large" metadata to a file
+ * opened with SWMR_WRITE will flush the existing metadata in the
+ * accumulator to disk first before writing the "large" metadata
+ * to disk.
+ * This test will fork and exec a reader "accum_swmr_reader" which
+ * opens the same file with SWMR_READ and verifies that the correct
+ * metadata is read from disk.
+ *
+ * Return: Success: 0
+ * Failure: 1
+ *
+ * Programmer: Vailin Choi; April 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+unsigned
+test_swmr_write_big(hbool_t newest_format)
+{
+ hid_t fid = -1; /* File ID */
+ hid_t fapl = -1; /* File access property list */
+ H5F_t *rf = NULL; /* File pointer */
+ uint8_t *wbuf2 = NULL, *rbuf = NULL; /* Buffers for reading & writing */
+ uint8_t wbuf[1024]; /* Buffer for reading & writing */
+ unsigned u; /* Local index variable */
+#ifdef H5_HAVE_UNISTD_H
+ pid_t pid; /* Process ID */
+#endif /* H5_HAVE_UNISTD_H */
+ int status; /* Status returned from child process */
+ H5F_io_info_t fio_info; /* I/O info for operation */
+ char *new_argv[] = {NULL};
+ char *driver = NULL; /* VFD string (from env variable) */
+
+ if(newest_format) {
+ TESTING("SWMR write of large metadata: with latest format");
+ } else {
+ TESTING("SWMR write of large metadata: with non-latest-format");
+ } /* end if */
+
+#if !(defined(H5_HAVE_FORK) && defined(H5_HAVE_WAITPID))
+
+ SKIPPED();
+ HDputs(" Test skipped due to fork or waitpid not defined.");
+ return 0;
+
+#else /* defined(H5_HAVE_FORK && defined(H5_HAVE_WAITPID) */
+
+ /* Skip this test if SWMR I/O is not supported for the VFD specified
+ * by the environment variable.
+ */
+ driver = HDgetenv("HDF5_DRIVER");
+ if (!H5FD_supports_swmr_test(driver)) {
+ SKIPPED();
+ HDputs(" Test skipped due to VFD not supporting SWMR I/O.");
+ return 0;
+ } /* end if */
+
+ /* File access property list */
+ if((fapl = h5_fileaccess()) < 0)
+ FAIL_STACK_ERROR
+
+ /* Both cases will result in v3 superblock and version 2 object header for SWMR */
+ if(newest_format) { /* latest format */
+ if(H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0)
+ FAIL_STACK_ERROR
+
+ if((fid = H5Fcreate(SWMR_FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ FAIL_STACK_ERROR
+ } else { /* non-latest-format */
+ if((fid = H5Fcreate(SWMR_FILENAME, H5F_ACC_TRUNC|H5F_ACC_SWMR_WRITE, H5P_DEFAULT, fapl)) < 0)
+ FAIL_STACK_ERROR
+ } /* end if */
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR
+
+ /* Open the file with SWMR_WRITE */
+ if((fid = H5Fopen(SWMR_FILENAME, H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE, fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Get H5F_t * to internal file structure */
+ if(NULL == (rf = (H5F_t *)H5I_object(fid))) FAIL_STACK_ERROR
+
+ /* Set up I/O info for operation */
+ fio_info.f = rf;
+ if(NULL == (fio_info.dxpl = (H5P_genplist_t *)H5I_object(H5AC_ind_read_dxpl_id)))
+ FAIL_STACK_ERROR
+
+ /* We'll be writing lots of garbage data, so extend the
+ file a ways. 10MB should do. */
+ if(H5FD_set_eoa(rf->shared->lf, H5FD_MEM_DEFAULT, (haddr_t)(1024*1024*10)) < 0)
+ FAIL_STACK_ERROR
+
+ if(H5Fflush(fid, H5F_SCOPE_GLOBAL) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Reset metadata accumulator for the file */
+ if(accum_reset(&fio_info) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Allocate space for the write & read buffers */
+ if((wbuf2 = (uint8_t *)HDmalloc((size_t)BIG_BUF_SIZE)) == NULL)
+ FAIL_STACK_ERROR;
+ if((rbuf = (uint8_t *)HDmalloc((size_t)BIG_BUF_SIZE)) == NULL)
+ FAIL_STACK_ERROR;
+
+ /* Initialize wbuf with "0, 1, 2...1024"*/
+ for(u = 0; u < 1024; u++)
+ wbuf[u] = (uint8_t)u;
+
+ /* Write [1024, 1024] bytes with wbuf */
+ if(H5F_block_write(rf, H5FD_MEM_DEFAULT, (haddr_t)1024, (size_t)1024, H5AC_ind_read_dxpl_id, wbuf) < 0)
+ FAIL_STACK_ERROR;
+ /* Read the data */
+ if(H5F_block_read(rf, H5FD_MEM_DEFAULT, (haddr_t)1024, (size_t)1024, H5AC_ind_read_dxpl_id, rbuf) < 0)
+ FAIL_STACK_ERROR;
+ /* Verify the data read is correct */
+ if(HDmemcmp(wbuf, rbuf, (size_t)1024) != 0)
+ TEST_ERROR;
+ /* Flush the data to disk */
+ if(accum_reset(&fio_info) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Initialize wbuf with all 1s */
+ for(u = 0; u < 1024; u++)
+ wbuf[u] = (uint8_t)1;
+
+ /* Initialize wbuf2 */
+ for(u = 0; u < BIG_BUF_SIZE; u++)
+ wbuf2[u] = (uint8_t)(u + 1);
+
+ /* Write [1024,1024] with wbuf--all 1s */
+ if(H5F_block_write(rf, H5FD_MEM_DEFAULT, (haddr_t)1024, (size_t)1024, H5AC_ind_read_dxpl_id, wbuf) < 0)
+ FAIL_STACK_ERROR;
+ /* Read the data */
+ if(H5F_block_read(rf, H5FD_MEM_DEFAULT, (haddr_t)1024, (size_t)1024, H5AC_ind_read_dxpl_id, rbuf) < 0)
+ FAIL_STACK_ERROR;
+ /* Verify the data read is correct */
+ if(HDmemcmp(wbuf, rbuf, (size_t)1024) != 0)
+ TEST_ERROR;
+ /* The data stays in the accumulator */
+
+ /* Write a large piece of metadata [2048, BIG_BUF_SIZE] with wbuf2 */
+ if(H5F_block_write(rf, H5FD_MEM_DEFAULT, (haddr_t)2048, (size_t)BIG_BUF_SIZE, H5AC_ind_read_dxpl_id, wbuf2) < 0)
+ FAIL_STACK_ERROR;
+ /* Read the data */
+ if(H5F_block_read(rf, H5FD_MEM_DEFAULT, (haddr_t)2048, (size_t)BIG_BUF_SIZE, H5AC_ind_read_dxpl_id, rbuf) < 0)
+ FAIL_STACK_ERROR;
+ /* Verify the data read is correct */
+ if(HDmemcmp(wbuf2, rbuf, (size_t)BIG_BUF_SIZE) != 0)
+ TEST_ERROR;
+
+ /* Fork child process to verify that the data at [1024, 2014] does get written to disk */
+ if((pid = HDfork()) < 0) {
+ HDperror("fork");
+ FAIL_STACK_ERROR;
+ } else if(0 == pid) { /* Child process */
+ /* Run the reader */
+ status = HDexecv(SWMR_READER, new_argv);
+ printf("errno from execv = %s\n", strerror(errno));
+ FAIL_STACK_ERROR;
+ } /* end if */
+
+ /* Parent process -- wait for the child process to complete */
+ while(pid != HDwaitpid(pid, &status, 0))
+ /*void*/;
+
+ /* Check if child process terminates normally and its return value */
+ if(WIFEXITED(status) && !WEXITSTATUS(status)) {
+ /* Flush the accumulator */
+ if(accum_reset(&fio_info) < 0)
+ FAIL_STACK_ERROR;
+ /* Close the property list */
+ if(H5Pclose(fapl) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Close and remove the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+ HDremove(SWMR_FILENAME);
+
+ /* Release memory */
+ if(wbuf2)
+ HDfree(wbuf2);
+ if(rbuf)
+ HDfree(rbuf);
+ PASSED();
+ return 0;
+ } /* end if */
+
+error:
+ /* Closing and remove the file */
+ H5Pclose(fapl);
+ H5Fclose(fid);
+ HDremove(SWMR_FILENAME);
+ /* Release memory */
+ if(wbuf2)
+ HDfree(wbuf2);
+ if(rbuf)
+ HDfree(rbuf);
+
+ return 1;
+
+#endif
+
+} /* end test_swmr_write_big() */
+
/*-------------------------------------------------------------------------
* Function: accum_printf