diff options
-rw-r--r-- | release_docs/RELEASE.txt | 3 | ||||
-rw-r--r-- | src/H5Dio.c | 31 | ||||
-rw-r--r-- | src/H5Ofill.c | 4 | ||||
-rw-r--r-- | src/H5Pdcpl.c | 3 | ||||
-rw-r--r-- | test/Makefile.in | 12 | ||||
-rw-r--r-- | test/tvlstr.c | 131 |
6 files changed, 160 insertions, 24 deletions
diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index 5bc4152..c3fc3ad 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -101,6 +101,9 @@ Bug Fixes since HDF5-1.6.0 release Library ------- + - Fixed bug that caused variable-length datatypes (strings or sequences) + used for datasets in files with objects that were unlinked to + fail to be read/written to a file. QAK - 2004/01/13 - Fixed small internal memory leak of fill-value information. QAK - 2004/01/06 - Detect situation where szip 'pixels per block' is larger than the diff --git a/src/H5Dio.c b/src/H5Dio.c index 562ee22..f1d6890 100644 --- a/src/H5Dio.c +++ b/src/H5Dio.c @@ -220,14 +220,11 @@ H5D_fill(const void *fill, const H5T_t *fill_type, void *buf, const H5T_t *buf_t FUNC_ENTER_NOAPI_NOINIT(H5D_fill) /* Check args */ + assert(fill_type); assert(buf); assert(buf_type); assert(space); - /* Check for "default" fill value */ - if(fill_type==NULL) - fill_type=buf_type; - /* Get the memory and file datatype sizes */ src_type_size = H5T_get_size(fill_type); dst_type_size = H5T_get_size(buf_type); @@ -245,19 +242,20 @@ H5D_fill(const void *fill, const H5T_t *fill_type, void *buf, const H5T_t *buf_t /* Copy the user's data into the buffer for conversion */ HDmemcpy(tconv_buf,fill,src_type_size); - /* Convert memory buffer into disk buffer */ /* Set up type conversion function */ - if (NULL == (tpath = H5T_path_find(fill_type, buf_type, NULL, NULL, dxpl_id))) { + if (NULL == (tpath = H5T_path_find(fill_type, buf_type, NULL, NULL, dxpl_id))) HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dest data types") - } else if (!H5T_path_noop(tpath)) { + + /* Convert memory buffer into disk buffer */ + if (!H5T_path_noop(tpath)) { if ((src_id = H5I_register(H5I_DATATYPE, H5T_copy(fill_type, H5T_COPY_ALL)))<0 || (dst_id = H5I_register(H5I_DATATYPE, H5T_copy(buf_type, H5T_COPY_ALL)))<0) HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register types for conversion") - } - /* Perform data type conversion */ - if (H5T_convert(tpath, src_id, dst_id, (hsize_t)1, 0, 0, tconv_buf, bkg_buf, dxpl_id)<0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "data type conversion failed") + /* Perform data type conversion */ + if (H5T_convert(tpath, src_id, dst_id, (hsize_t)1, 0, 0, tconv_buf, bkg_buf, dxpl_id)<0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "data type conversion failed") + } /* end if */ } /* end if */ /* Fill the selection in the memory buffer */ @@ -600,7 +598,7 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, HGOTO_DONE(SUCCEED) /* Go fill the user's selection with the dataset's fill value */ - if(H5D_fill(fill.buf,fill.type,buf,mem_type,mem_space, dxpl_id)<0) + if(H5D_fill(fill.buf,dataset->type,buf,mem_type,mem_space, dxpl_id)<0) HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "filling buf failed") else HGOTO_DONE(SUCCEED) @@ -819,13 +817,20 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, if(nelmts > 0 && dataset->efl.nused==0 && dataset->layout.type!=H5D_COMPACT && dataset->layout.addr==HADDR_UNDEF) { hssize_t file_nelmts; /* Number of elements in file dataset's dataspace */ + hbool_t full_overwrite; /* Whether we are over-writing all the elements */ /* Get the number of elements in file dataset's dataspace */ if((file_nelmts=H5S_get_simple_extent_npoints(file_space))<0) HGOTO_ERROR (H5E_DATASET, H5E_BADVALUE, FAIL, "can't retrieve number of elements in file dataset") + /* Always allow fill values to be written if the dataset has a VL datatype */ + if(H5T_detect_class(dataset->type, H5T_VLEN)) + full_overwrite=FALSE; + else + full_overwrite=(hsize_t)file_nelmts==nelmts ? TRUE : FALSE; + /* Allocate storage */ - if(H5D_alloc_storage(dataset->ent.file,dxpl_id,dataset,H5D_ALLOC_WRITE, TRUE, (hbool_t)((hsize_t)file_nelmts==nelmts ? TRUE : FALSE))<0) + if(H5D_alloc_storage(dataset->ent.file,dxpl_id,dataset,H5D_ALLOC_WRITE, TRUE, full_overwrite)<0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize storage") } /* end if */ diff --git a/src/H5Ofill.c b/src/H5Ofill.c index ec34202..521b94d 100644 --- a/src/H5Ofill.c +++ b/src/H5Ofill.c @@ -883,9 +883,9 @@ H5O_fill_convert(void *_fill, H5T_t *dset_type, hid_t dxpl_id) /* Don't bother doing anything if there will be no actual conversion */ if (!H5T_path_noop(tpath)) { if ((src_id = H5I_register(H5I_DATATYPE, - H5T_copy(fill->type, H5T_COPY_TRANSIENT)))<0 || + H5T_copy(fill->type, H5T_COPY_ALL)))<0 || (dst_id = H5I_register(H5I_DATATYPE, - H5T_copy(dset_type, H5T_COPY_TRANSIENT)))<0) + H5T_copy(dset_type, H5T_COPY_ALL)))<0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy/register data type"); /* diff --git a/src/H5Pdcpl.c b/src/H5Pdcpl.c index f61ebf0..6307a07 100644 --- a/src/H5Pdcpl.c +++ b/src/H5Pdcpl.c @@ -741,8 +741,7 @@ H5Pget_filter(hid_t plist_id, unsigned idx, unsigned int *flags/*out*/, #endif /* H5_WANT_H5_V1_6_COMPAT */ /* Check args */ - if (cd_nelmts || cd_values) -{ + if (cd_nelmts || cd_values) { if (cd_nelmts && *cd_nelmts>256) /* * It's likely that users forget to initialize this on input, so diff --git a/test/Makefile.in b/test/Makefile.in index cde5dde..15421e7 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -59,12 +59,12 @@ MOSTLYCLEAN=cmpd_dset.h5 compact_dataset.h5 dataset.h5 extend.h5 istore.h5 \ links.h5 links[1-3].h5 big.data big[0-9][0-9][0-9][0-9][0-9].h5 \ dtypes[1-3].h5 tattr.h5 tselect.h5 mtime.h5 unlink.h5 \ fillval_[0-9].h5 fillval.raw mount_[0-9].h5 testmeta.h5 ttime.h5 \ - trefer[1-3].h5 tvltypes.h5 tvlstr.h5 flush.h5 enum1.h5 \ - titerate.h5 ttsafe.h5 tarray1.h5 tgenprop.h5 tmisc[0-9]*.h5 \ - set_extent_read.h5 set_extent_create.h5 getname.h5 \ - getname[1-3].h5 sec2_file.h5 family_file000[0-3][0-9].h5 \ - multi_file-[rs].h5 core_file new_move_[ab].h5 ntypes.h5 \ - dangle.h5 error_test.h5 err_compat.h5 + trefer[1-3].h5 tvltypes.h5 tvlstr.h5 tvlstr2.h5 flush.h5 \ + enum1.h5 titerate.h5 ttsafe.h5 tarray1.h5 tgenprop.h5 \ + tmisc[0-9]*.h5 set_extent_read.h5 set_extent_create.h5 \ + getname.h5 getname[1-3].h5 sec2_file.h5 \ + family_file000[0-3][0-9].h5 multi_file-[rs].h5 core_file \ + new_move_[ab].h5 ntypes.h5 dangle.h5 error_test.h5 err_compat.h5 CLEAN=$(TIMINGS) diff --git a/test/tvlstr.c b/test/tvlstr.c index 2031865..52d883b 100644 --- a/test/tvlstr.c +++ b/test/tvlstr.c @@ -29,6 +29,7 @@ #include "hdf5.h" #define DATAFILE "tvlstr.h5" +#define DATAFILE2 "tvlstr2.h5" /* 1-D dataset with fixed dimensions */ #define SPACE1_NAME "Space1" @@ -43,6 +44,9 @@ #define VLSTR_TYPE "vl_string_type" +/* Definitions for the VL re-writing test */ +#define REWRITE_NDATASETS 32 + /* String for testing attributes */ static const char *string_att = "This is the string for the attribute"; static char *string_att_write=NULL; @@ -713,6 +717,127 @@ static void test_read_vl_string_attribute(void) return; } +/* Helper routine for test_vl_rewrite() */ +static void write_scalar_dset(hid_t file, hid_t type, hid_t space, char *name, char *data) +{ + hid_t dset; + herr_t ret; + + dset = H5Dcreate (file, name, type, space, H5P_DEFAULT); + CHECK(dset, FAIL, "H5Dcreate"); + + ret = H5Dwrite(dset, type, space, space, H5P_DEFAULT, &data); + CHECK(ret, FAIL, "H5Dwrite"); + + ret = H5Dclose(dset); + CHECK(ret, FAIL, "H5Dclose"); +} + +/* Helper routine for test_vl_rewrite() */ +static void read_scalar_dset(hid_t file, hid_t type, hid_t space, char *name, char *data) +{ + hid_t dset; + herr_t ret; + char *data_read; + + dset = H5Dopen (file, name); + CHECK(dset, FAIL, "H5Dopen"); + + ret = H5Dread(dset, type, space, space, H5P_DEFAULT, &data_read); + CHECK(ret, FAIL, "H5Dread"); + + ret = H5Dclose(dset); + CHECK(ret, FAIL, "H5Dclose"); + + if(HDstrcmp(data, data_read)) + TestErrPrintf("Expected %s for dataset %s but read %s\n", data, name, data_read); + + HDfree(data_read); +} + +/**************************************************************** +** +** test_vl_rewrite(): Test basic VL string code. +** Tests I/O on VL strings when lots of objects in the file +** have been linked/unlinked. +** +****************************************************************/ +static void test_vl_rewrite(void) +{ + hid_t file1, file2; /* File IDs */ + hid_t type; /* VL string datatype ID */ + hid_t space; /* Scalar dataspace */ + char name[256]; /* Buffer for names & data */ + int i; /* Local index variable */ + herr_t ret; /* Generic return value */ + + /* Create the VL string datatype */ + type = H5Tcopy(H5T_C_S1); + CHECK(type, FAIL, "H5Tcopy"); + + ret = H5Tset_size(type, H5T_VARIABLE); + CHECK(ret, FAIL, "H5Tset_size"); + + /* Create the scalar dataspace */ + space = H5Screate(H5S_SCALAR); + CHECK(space, FAIL, "H5Screate"); + + /* Open the files */ + file1 = H5Fcreate(DATAFILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + CHECK(file1, FAIL, "H5Fcreate"); + + file2 = H5Fcreate(DATAFILE2, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + CHECK(file1, FAIL, "H5Fcreate"); + + /* Create in file 1 */ + for(i=0; i<REWRITE_NDATASETS; i++) { + sprintf(name, "/set_%d", i); + write_scalar_dset(file1, type, space, name, name); + } + + /* Effectively copy data from file 1 to 2 */ + for(i=0; i<REWRITE_NDATASETS; i++) { + sprintf(name, "/set_%d", i); + read_scalar_dset(file1, type, space, name, name); + write_scalar_dset(file2, type, space, name, name); + } + + /* Read back from file 2 */ + for(i=0; i<REWRITE_NDATASETS; i++) { + sprintf(name, "/set_%d", i); + read_scalar_dset(file2, type, space, name, name); + } + + /* Remove from file 2. */ + for(i=0; i<REWRITE_NDATASETS; i++) { + sprintf(name, "/set_%d", i); + ret = H5Gunlink(file2, name); + CHECK(ret, FAIL, "H5Gunlink"); + } + + /* Effectively copy from file 1 to file 2 */ + for(i=0; i<REWRITE_NDATASETS; i++) { + sprintf(name, "/set_%d", i); + read_scalar_dset(file1, type, space, name, name); + write_scalar_dset(file2, type, space, name, name); + } + + /* Close everything */ + ret = H5Tclose(type); + CHECK(ret, FAIL, "H5Tclose"); + + ret = H5Sclose(space); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Fclose(file1); + CHECK(ret, FAIL, "H5Fclose"); + + ret = H5Fclose(file2); + CHECK(ret, FAIL, "H5Fclose"); + + return; +} /* end test_vl_rewrite() */ + /**************************************************************** ** ** test_vlstrings(): Main VL string testing routine. @@ -734,6 +859,9 @@ test_vlstrings(void) /* Test using VL strings in attributes */ test_write_vl_string_attribute(); test_read_vl_string_attribute(); + + /* Test writing VL datasets in files with lots of unlinking */ + test_vl_rewrite(); } /* test_vlstrings() */ @@ -754,6 +882,7 @@ test_vlstrings(void) void cleanup_vlstrings(void) { - remove(DATAFILE); + HDremove(DATAFILE); + HDremove(DATAFILE2); } |