From b772be716d4ac50a087407577358a35452ad0afa Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Sun, 18 Dec 2016 00:41:13 -0800 Subject: Merge SWMR-oriented accumulator tests from revise_chunks to develop. --- MANIFEST | 1 + test/Makefile.am | 4 +- test/accum.c | 224 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 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 -- cgit v0.12