diff options
author | Raymond Lu <songyulu@hdfgroup.org> | 2010-09-09 18:15:36 (GMT) |
---|---|---|
committer | Raymond Lu <songyulu@hdfgroup.org> | 2010-09-09 18:15:36 (GMT) |
commit | 073eb187d6589e5741065038d3f4ca3f634381d9 (patch) | |
tree | c8907e2e4ea22075a85b8ea8d264a53d10c681c3 /test | |
parent | bed127641399ec6c6e1479b7c394fd3a4eb56438 (diff) | |
download | hdf5-073eb187d6589e5741065038d3f4ca3f634381d9.zip hdf5-073eb187d6589e5741065038d3f4ca3f634381d9.tar.gz hdf5-073eb187d6589e5741065038d3f4ca3f634381d9.tar.bz2 |
[svn-r19363] When mandatory filter failed to write data chunks, the dataset
couldn't close (bug 1260). The fix releases all resources and closes
the dataset but returns a failure.
Tested with h5committest - jam, heiwa, amani.
Diffstat (limited to 'test')
-rw-r--r-- | test/Makefile.am | 4 | ||||
-rw-r--r-- | test/Makefile.in | 46 | ||||
-rw-r--r-- | test/filter_fail.c | 382 | ||||
-rw-r--r-- | test/tid.c | 4 |
4 files changed, 413 insertions, 23 deletions
diff --git a/test/Makefile.am b/test/Makefile.am index 07df450..c4eb616 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -38,8 +38,8 @@ SCRIPT_DEPEND = error_test$(EXEEXT) err_compat$(EXEEXT) # other current library code tests. TEST_PROG=testhdf5 lheap ohdr stab gheap cache cache_api cache_tagging \ pool hyperslab istore bittests dt_arith \ - dtypes dsets cmpd_dset extend external objcopy links unlink big mtime \ - fillval mount flush1 flush2 app_ref enum \ + dtypes dsets cmpd_dset filter_fail extend external objcopy links unlink \ + big mtime fillval mount flush1 flush2 app_ref enum \ set_extent ttsafe \ getname vfd ntypes dangle dtransform reserved cross_read \ freespace mf farray earray btree2 fheap diff --git a/test/Makefile.in b/test/Makefile.in index e441918..80c5bc4 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -80,9 +80,9 @@ am__EXEEXT_1 = testhdf5$(EXEEXT) lheap$(EXEEXT) ohdr$(EXEEXT) \ cache_tagging$(EXEEXT) pool$(EXEEXT) hyperslab$(EXEEXT) \ istore$(EXEEXT) bittests$(EXEEXT) dt_arith$(EXEEXT) \ dtypes$(EXEEXT) dsets$(EXEEXT) cmpd_dset$(EXEEXT) \ - extend$(EXEEXT) external$(EXEEXT) objcopy$(EXEEXT) \ - links$(EXEEXT) unlink$(EXEEXT) big$(EXEEXT) mtime$(EXEEXT) \ - fillval$(EXEEXT) mount$(EXEEXT) flush1$(EXEEXT) \ + filter_fail$(EXEEXT) extend$(EXEEXT) external$(EXEEXT) \ + objcopy$(EXEEXT) links$(EXEEXT) unlink$(EXEEXT) big$(EXEEXT) \ + mtime$(EXEEXT) fillval$(EXEEXT) mount$(EXEEXT) flush1$(EXEEXT) \ flush2$(EXEEXT) app_ref$(EXEEXT) enum$(EXEEXT) \ set_extent$(EXEEXT) ttsafe$(EXEEXT) getname$(EXEEXT) \ vfd$(EXEEXT) ntypes$(EXEEXT) dangle$(EXEEXT) \ @@ -190,6 +190,10 @@ fillval_SOURCES = fillval.c fillval_OBJECTS = fillval.$(OBJEXT) fillval_LDADD = $(LDADD) fillval_DEPENDENCIES = libh5test.la $(LIBHDF5) +filter_fail_SOURCES = filter_fail.c +filter_fail_OBJECTS = filter_fail.$(OBJEXT) +filter_fail_LDADD = $(LDADD) +filter_fail_DEPENDENCIES = libh5test.la $(LIBHDF5) flush1_SOURCES = flush1.c flush1_OBJECTS = flush1.$(OBJEXT) flush1_LDADD = $(LDADD) @@ -385,24 +389,24 @@ SOURCES = $(libh5test_la_SOURCES) app_ref.c big.c bittests.c btree2.c \ cache.c cache_api.c cache_tagging.c cmpd_dset.c cross_read.c \ dangle.c dsets.c dt_arith.c dtransform.c dtypes.c earray.c \ enum.c err_compat.c error_test.c extend.c external.c farray.c \ - fheap.c fillval.c flush1.c flush2.c freespace.c gen_bad_ohdr.c \ - gen_bogus.c gen_cross.c gen_deflate.c gen_filespace.c \ - gen_filters.c gen_new_array.c gen_new_fill.c gen_new_group.c \ - gen_new_mtime.c gen_new_super.c gen_noencoder.c \ - gen_nullspace.c gen_sizes_lheap.c gen_specmetaread.c \ - gen_udlinks.c getname.c gheap.c hyperslab.c istore.c lheap.c \ - links.c mf.c mount.c mtime.c ntypes.c objcopy.c ohdr.c pool.c \ - reserved.c set_extent.c space_overflow.c stab.c \ - tcheck_version.c $(testhdf5_SOURCES) testmeta.c \ - $(ttsafe_SOURCES) unlink.c vfd.c + fheap.c fillval.c filter_fail.c flush1.c flush2.c freespace.c \ + gen_bad_ohdr.c gen_bogus.c gen_cross.c gen_deflate.c \ + gen_filespace.c gen_filters.c gen_new_array.c gen_new_fill.c \ + gen_new_group.c gen_new_mtime.c gen_new_super.c \ + gen_noencoder.c gen_nullspace.c gen_sizes_lheap.c \ + gen_specmetaread.c gen_udlinks.c getname.c gheap.c hyperslab.c \ + istore.c lheap.c links.c mf.c mount.c mtime.c ntypes.c \ + objcopy.c ohdr.c pool.c reserved.c set_extent.c \ + space_overflow.c stab.c tcheck_version.c $(testhdf5_SOURCES) \ + testmeta.c $(ttsafe_SOURCES) unlink.c vfd.c DIST_SOURCES = $(libh5test_la_SOURCES) app_ref.c big.c bittests.c \ btree2.c cache.c cache_api.c cache_tagging.c cmpd_dset.c \ cross_read.c dangle.c dsets.c dt_arith.c dtransform.c dtypes.c \ earray.c enum.c err_compat.c error_test.c extend.c external.c \ - farray.c fheap.c fillval.c flush1.c flush2.c freespace.c \ - gen_bad_ohdr.c gen_bogus.c gen_cross.c gen_deflate.c \ - gen_filespace.c gen_filters.c gen_new_array.c gen_new_fill.c \ - gen_new_group.c gen_new_mtime.c gen_new_super.c \ + farray.c fheap.c fillval.c filter_fail.c flush1.c flush2.c \ + freespace.c gen_bad_ohdr.c gen_bogus.c gen_cross.c \ + gen_deflate.c gen_filespace.c gen_filters.c gen_new_array.c \ + gen_new_fill.c gen_new_group.c gen_new_mtime.c gen_new_super.c \ gen_noencoder.c gen_nullspace.c gen_sizes_lheap.c \ gen_specmetaread.c gen_udlinks.c getname.c gheap.c hyperslab.c \ istore.c lheap.c links.c mf.c mount.c mtime.c ntypes.c \ @@ -717,8 +721,8 @@ SCRIPT_DEPEND = error_test$(EXEEXT) err_compat$(EXEEXT) # other current library code tests. TEST_PROG = testhdf5 lheap ohdr stab gheap cache cache_api cache_tagging \ pool hyperslab istore bittests dt_arith \ - dtypes dsets cmpd_dset extend external objcopy links unlink big mtime \ - fillval mount flush1 flush2 app_ref enum \ + dtypes dsets cmpd_dset filter_fail extend external objcopy links unlink \ + big mtime fillval mount flush1 flush2 app_ref enum \ set_extent ttsafe \ getname vfd ntypes dangle dtransform reserved cross_read \ freespace mf farray earray btree2 fheap @@ -916,6 +920,9 @@ fheap$(EXEEXT): $(fheap_OBJECTS) $(fheap_DEPENDENCIES) fillval$(EXEEXT): $(fillval_OBJECTS) $(fillval_DEPENDENCIES) @rm -f fillval$(EXEEXT) $(LINK) $(fillval_OBJECTS) $(fillval_LDADD) $(LIBS) +filter_fail$(EXEEXT): $(filter_fail_OBJECTS) $(filter_fail_DEPENDENCIES) + @rm -f filter_fail$(EXEEXT) + $(LINK) $(filter_fail_OBJECTS) $(filter_fail_LDADD) $(LIBS) flush1$(EXEEXT): $(flush1_OBJECTS) $(flush1_DEPENDENCIES) @rm -f flush1$(EXEEXT) $(LINK) $(flush1_OBJECTS) $(flush1_LDADD) $(LIBS) @@ -1073,6 +1080,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/farray.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fheap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fillval.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/filter_fail.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flush1.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flush2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/freespace.Po@am__quote@ diff --git a/test/filter_fail.c b/test/filter_fail.c new file mode 100644 index 0000000..abb25cd --- /dev/null +++ b/test/filter_fail.c @@ -0,0 +1,382 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Programmer: Raymond Lu <songyulu@hdfgroup.org> + * 7 September 2010 + * + * Purpose: Make sure dataset, file, and library can close properly when a + * mandatory filter fails. + */ + +#include "h5test.h" +#include "H5srcdir.h" + +#define DSET_NAME "dset_fail" +#define ONE_MB 1048576 +#define H5Z_FILTER_FAIL_TEST 312 +#define DIM 10 +#define FILTER_CHUNK_DIM 2 + +const char *FILENAME[] = { + "filter_fail", + NULL +}; + +static size_t filter_fail(unsigned int flags, size_t cd_nelmts, + const unsigned int *cd_values, size_t nbytes, size_t *buf_size, void **buf); + +/* This message derives from H5Z */ +const H5Z_class2_t H5Z_FAIL_TEST[1] = {{ + H5Z_CLASS_T_VERS, /* H5Z_class_t version */ + H5Z_FILTER_FAIL_TEST, /* Filter id number */ + 1, 1, /* Encoding and decoding enabled */ + "filter_fail_test", /* Filter name for debugging */ + NULL, /* The "can apply" callback */ + NULL, /* The "set local" callback */ + filter_fail, /* The actual filter function */ +}}; + + +/*------------------------------------------------------------------------- + * Function: filter_fail + * + * Purpose: For testing library's behavior when a mandatory filter + * fails to write a chunk. + * + * Return: Success: Data chunk size + * Failure: 0 + * + * Programmer: Raymond Lu + * 7 September 2010 + * + *------------------------------------------------------------------------- + */ +static size_t +filter_fail(unsigned int flags, size_t cd_nelmts, + const unsigned int *cd_values, size_t nbytes, + size_t *buf_size, void **buf) +{ + int *dst = (int*)(*buf); + unsigned int offset; + unsigned int length; + unsigned int value; + size_t ret_value = 0; + + if(flags & H5Z_FLAG_REVERSE) { /* do nothing during read */ + *buf_size = nbytes; + ret_value = nbytes; + } /* end if */ + else { /* Write data */ + /* If it's the last chunk, pretend to fail. Otherwise, do nothing. */ + if(*dst == 8 || *dst == 9) { + ret_value = 0; + } else { + *buf_size = nbytes; + ret_value = *buf_size; + } + } /* end else */ + +error: + return ret_value; +} /* end filter_fail() */ + + +/*------------------------------------------------------------------------- + * Function: test_filter_write_failure + * + * Purpose: Tests the library's behavior when a mandate filter returns + * failure. There're only 5 chunks with each of them having + * 2 integers. The filter will fail in the last chunk. The + * dataset should release all resources even though the last + * chunk can't be flushed to file. The file should close + * successfully. + * + * Return: + * Success: 0 + * Failure: -1 + * + * Programmer: Raymond Lu + * 25 August 2010 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +test_filter_write(char *file_name, hid_t my_fapl) +{ + char filename[1024]; + hid_t file = -1; + hid_t dataset=-1; /* dataset ID */ + hid_t sid=-1; /* dataspace ID */ + hid_t dcpl=-1; /* dataset creation property list ID */ + hsize_t dims[1]={DIM}; /* dataspace dimension - 10*/ + hsize_t chunk_dims[1]={FILTER_CHUNK_DIM}; /* chunk dimension - 2*/ + int nfilters; /* number of filters in DCPL */ + unsigned flags; /* flags for filter */ + int points[DIM]; /* Data */ + int rbuf[DIM]; /* Data */ + herr_t ret; /* generic return value */ + int i; + + TESTING("data writing when a mandatory filter fails"); + + /* Create file */ + if((file = H5Fcreate(file_name, H5F_ACC_TRUNC, H5P_DEFAULT, my_fapl)) < 0) TEST_ERROR + + /* create the data space */ + if((sid = H5Screate_simple(1, dims, NULL)) < 0) TEST_ERROR + + /* Create dcpl and register the filter */ + if((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0) TEST_ERROR + + if(H5Pset_chunk(dcpl, 1, chunk_dims) < 0) TEST_ERROR + + if(H5Zregister (H5Z_FAIL_TEST) < 0) TEST_ERROR + + /* Check that the filter was registered */ + if(TRUE != H5Zfilter_avail(H5Z_FILTER_FAIL_TEST)) FAIL_STACK_ERROR + + /* Enable the filter as mandatory */ + if(H5Pset_filter(dcpl, H5Z_FILTER_FAIL_TEST, 0, (size_t)0, NULL) < 0) + TEST_ERROR + + /* create a dataset */ + if((dataset = H5Dcreate2(file, DSET_NAME, H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0) TEST_ERROR + + /* Initialize the write buffer */ + for(i = 0; i < DIM; i++) + points[i] = i; + + /* Write data */ + if(H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, sid, H5P_DEFAULT, points) < 0) TEST_ERROR + + /* clean up objects used for this test */ + if(H5Pclose (dcpl) < 0) TEST_ERROR + if(H5Sclose (sid) < 0) TEST_ERROR + + /* Dataset closing should fail */ + H5E_BEGIN_TRY { + ret = H5Dclose (dataset); + } H5E_END_TRY; + if(ret >= 0) { + H5_FAILED(); + puts(" Dataset is supposed to fail because the chunk can't be flushed to file."); + TEST_ERROR + } + + /* Even though H5Dclose fails, it should release all resources. + * So the file should close successfully. */ + if(H5Fclose (file) < 0) TEST_ERROR + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + H5Pclose(dcpl); + H5Sclose(sid); + H5Dclose(dataset); + H5Fclose(file); + } H5E_END_TRY; + return -1; +} /* end test_filter_write() */ + + +/*------------------------------------------------------------------------- + * Function: test_filter_read + * + * Purpose: Tests the library's behavior when a mandate filter returns + * failure. The first 4 chunks should be in the file. The + * last chunk should not. + * + * Return: + * Success: 0 + * Failure: -1 + * + * Programmer: Raymond Lu + * 25 August 2010 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +test_filter_read(char *file_name, hid_t my_fapl) +{ + hid_t file = -1; + hid_t dataset=-1; /* dataset ID */ + hid_t sid = -1; + hid_t mspace = -1; + hsize_t dims[1]={DIM}; /* dataspace dimension - 10*/ + hsize_t chunk_dims[1]={FILTER_CHUNK_DIM}; /* chunk dimension - 2*/ + int rbuf[DIM]; /* Data */ + hsize_t dset_size = 0; /* Dataset storage size */ + hsize_t hs_offset[H5S_MAX_RANK]; + hsize_t hs_size[H5S_MAX_RANK]; + hsize_t stride[1] = {2}; + hsize_t zero[8]; + hsize_t nelmts = DIM/2; + int i; + + TESTING("data reading when a mandatory filter fails"); + + /* Open file */ + if((file = H5Fopen(file_name, H5F_ACC_RDONLY, my_fapl)) < 0) TEST_ERROR + + /* Open dataset */ + if((dataset = H5Dopen2(file, DSET_NAME, H5P_DEFAULT)) < 0) TEST_ERROR + + /* Verify the storage size is equal to 4 chunks */ + if((dset_size = H5Dget_storage_size(dataset)) == 0) TEST_ERROR + + if(dset_size != 4 * FILTER_CHUNK_DIM * sizeof(int)) TEST_ERROR + + /* Read the chunks */ + HDmemset(rbuf, 0, DIM * sizeof(int)); + if(H5Dread(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, rbuf) < 0) + TEST_ERROR + + /* Check that the values read are the same as the values written. + * The last chunk should not be in the file. */ + for(i = 0; i < DIM; i++) { + if(i < DIM-2 && rbuf[i] != i) { + H5_FAILED(); + printf(" Read different values than written.\n"); + printf(" At index %d\n", i); + printf(" rbuf[%d]=%d\n", i, rbuf[i]); + TEST_ERROR + } else if(i >= DIM-2 && rbuf[i] != 0) { + H5_FAILED(); + printf(" No value should be read.\n"); + printf(" At index %d\n", i); + printf(" rbuf[%d]=%d\n", i, rbuf[i]); + TEST_ERROR + } + } + + /* Try to read in hyperslab simulating the h5dump's way of printing data */ + if((sid = H5Dget_space(dataset)) < 0) TEST_ERROR + + HDmemset(hs_offset, 0, sizeof(hs_offset)); + HDmemset(hs_size, 0, sizeof(hs_size)); + hs_size[0] = DIM/2; + + if(H5Sselect_hyperslab(sid, H5S_SELECT_SET, hs_offset, stride, hs_size, NULL) < 0) + TEST_ERROR + + /* create the data space */ + if((mspace = H5Screate_simple(1, dims, NULL)) < 0) TEST_ERROR + + HDmemset(zero, 0, sizeof zero); + + if(H5Sselect_hyperslab(mspace, H5S_SELECT_SET, zero, stride, &nelmts, NULL) < 0) + TEST_ERROR + + HDmemset(rbuf, 0, DIM * sizeof(int)); + if(H5Dread(dataset, H5T_NATIVE_INT, H5S_ALL, sid, H5P_DEFAULT, rbuf) < 0) + TEST_ERROR + + /* Check that the values read are the same as the values written. + * The last chunk should not be in the file. */ + for(i = 0; i < DIM; i+=2) { + if(i < DIM-2 && rbuf[i] != i) { + H5_FAILED(); + printf(" Read different values than written.\n"); + printf(" At index %d\n", i); + printf(" rbuf[%d]=%d\n", i, rbuf[i]); + TEST_ERROR + } else if(i >= DIM-2 && rbuf[i] != 0) { + H5_FAILED(); + printf(" No value should be read.\n"); + printf(" At index %d\n", i); + printf(" rbuf[%d]=%d\n", i, rbuf[i]); + TEST_ERROR + } + } + + if(H5Sclose (sid) < 0) TEST_ERROR + if(H5Sclose (mspace) < 0) TEST_ERROR + if(H5Dclose (dataset) < 0) TEST_ERROR + if(H5Fclose (file) < 0) TEST_ERROR + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + H5Sclose(sid); + H5Sclose(mspace); + H5Dclose(dataset); + H5Fclose(file); + } H5E_END_TRY; + return -1; +} /* end test_filter_read() */ + +/*------------------------------------------------------------------------- + * Function: main + * + * Purpose: Tests the library's behavior when a mandate filter returns + * failure. + * + * Return: Success: exit(0) + * Failure: exit(1) + * + * Programmer: Raymond Lu + * 25 August 2010 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +int main(void) +{ + hid_t fapl; + int mdc_nelmts = 0; + size_t rdcc_nelmts = 521; + size_t rdcc_nbytes = ONE_MB; + double rdcc_w0 = 0.75; + char filename[1024]; + unsigned nerrors = 0; + + h5_reset(); + fapl = h5_fileaccess(); + + h5_fixname(FILENAME[0], fapl, filename, sizeof filename); + + /* Make sure the chunk cache is used. All values are default. */ + if(H5Pset_cache(fapl, mdc_nelmts, rdcc_nelmts, rdcc_nbytes, rdcc_w0) < 0) + TEST_ERROR + + nerrors += (test_filter_write(filename, fapl) < 0 ? 1 : 0); + nerrors += (test_filter_read(filename, fapl) < 0 ? 1 : 0); + + h5_cleanup(FILENAME, fapl); + + /* Make sure we can close the library */ + if(H5close() < 0) TEST_ERROR + + if (nerrors) TEST_ERROR + + return 0; + +error: + if (nerrors) { + printf("***** %u FAILURE%s! *****\n", + nerrors, 1==nerrors?"":"S"); + HDexit(1); + } +} @@ -361,7 +361,7 @@ static int test_is_valid(void) CHECK(ret, FAIL, "H5I_inc_ref"); if (ret < 0) goto out; - ret = H5I_dec_ref(dtype, TRUE); + ret = H5I_dec_ref(dtype, TRUE, FALSE); CHECK(ret, FAIL, "H5I_dec_ref"); if (ret < 0) goto out; @@ -377,7 +377,7 @@ static int test_is_valid(void) CHECK(nmembs1, FAIL, "H5I_nmembers"); if (nmembs1 < 0) goto out; - ret = H5I_dec_ref(dtype, FALSE); + ret = H5I_dec_ref(dtype, FALSE, FALSE); CHECK(ret, FAIL, "H5I_dec_ref"); if (ret < 0) goto out; |