From a89130553de2d043eb69b65d75162af5b97df3bf Mon Sep 17 00:00:00 2001 From: Songyu Lu Date: Fri, 30 Nov 2018 09:02:03 -0600 Subject: HDFFV-10635: Allowing to write the same variable-length element more than once. --- src/H5HG.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/H5HG.c b/src/H5HG.c index b9d8dc3..63d482e 100644 --- a/src/H5HG.c +++ b/src/H5HG.c @@ -785,7 +785,13 @@ H5HG_remove (H5F_t *f, H5HG_t *hobj) HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect global heap") HDassert(hobj->idx < heap->nused); - HDassert(heap->obj[hobj->idx].begin); + + /* When the application selects the same location to rewrite the element by using H5Sselect_elements, + * it can happen that the entry has been removed by first rewrite. Here we simply skip the removal of + * the entry and let the second rewrite happen. */ + if(heap->obj[hobj->idx].nrefs == 0 && heap->obj[hobj->idx].size == 0 && !heap->obj[hobj->idx].begin) + HGOTO_DONE(ret_value) + obj_start = heap->obj[hobj->idx].begin; /* Include object header size */ need = H5HG_ALIGN(heap->obj[hobj->idx].size) + H5HG_SIZEOF_OBJHDR(f); -- cgit v0.12 From 19a94503f39dfd1a6b88caf4d76d3f4e9ce6f362 Mon Sep 17 00:00:00 2001 From: Songyu Lu Date: Wed, 5 Dec 2018 16:48:47 -0600 Subject: HDFFV-10635: add a test case. --- test/tvlstr.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 102 insertions(+), 2 deletions(-) diff --git a/test/tvlstr.c b/test/tvlstr.c index 3315d68..cc5a9c4 100644 --- a/test/tvlstr.c +++ b/test/tvlstr.c @@ -23,12 +23,17 @@ #define DATAFILE "tvlstr.h5" #define DATAFILE2 "tvlstr2.h5" +#define DATAFILE3 "sel2el.h5" + +#define DATASET "1Darray" /* 1-D dataset with fixed dimensions */ #define SPACE1_RANK 1 #define SPACE1_DIM1 4 +#define SPACE1_DIM2 2 +#define NUMP 2 -#define VLSTR_TYPE "vl_string_type" +#define VLSTR_TYPE "vl_string_type" /* Definitions for the VL re-writing test */ #define REWRITE_NDATASETS 32 @@ -846,6 +851,99 @@ static void test_vl_rewrite(void) } /* end test_vl_rewrite() */ /**************************************************************** + ** + ** test_write_same_element(): + ** Tests writing to the same element of VL string using + ** H5Sselect_element. + ** + ****************************************************************/ +static void test_write_same_element(void) +{ + hid_t file1, dataset1; + hid_t mspace, fspace, dtype; + hsize_t fdim[] = {SPACE1_DIM1}; + char *val[SPACE1_DIM2] = {"not", "bad"}; + hsize_t marray[] = {2}; + hsize_t coord[SPACE1_RANK][NUMP]; + herr_t ret; + + char *wdata[SPACE1_DIM1] = {"Parting", "is such", "sweet", "sorrow."}; + + file1 = H5Fcreate (DATAFILE3, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + CHECK(file1, FAIL, "H5Fcreate"); + + dtype = H5Tcopy (H5T_C_S1); + CHECK(dtype, FAIL, "H5Tcopy"); + + ret = H5Tset_size (dtype, H5T_VARIABLE); + CHECK(ret, FAIL, "H5Tset_size"); + + fspace = H5Screate_simple (SPACE1_RANK, fdim, NULL); + CHECK(fspace, FAIL, "H5Screate_simple"); + + dataset1 = H5Dcreate (file1, DATASET, dtype, fspace, H5P_DEFAULT, + H5P_DEFAULT, H5P_DEFAULT); + CHECK(dataset1, FAIL, "H5Dcreate"); + + ret = H5Dwrite(dataset1, dtype, H5S_ALL, H5S_ALL, H5P_DEFAULT, wdata); + CHECK(ret, FAIL, "H5Dwrite"); + + ret = H5Dclose (dataset1); + CHECK(ret, FAIL, "H5Dclose"); + + ret = H5Tclose (dtype); + CHECK(ret, FAIL, "H5Tclose"); + + ret = H5Sclose (fspace); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Fclose (file1); + CHECK(ret, FAIL, "H5Fclose"); + + /* + * Open the file. Select the same two points, write values to those point locations. + */ + file1 = H5Fopen (DATAFILE3, H5F_ACC_RDWR, H5P_DEFAULT); + CHECK(file1, FAIL, "H5Fopen"); + + dataset1 = H5Dopen (file1, DATASET, H5P_DEFAULT); + CHECK(dataset1, FAIL, "H5Dopen"); + + fspace = H5Dget_space (dataset1); + CHECK(fspace, FAIL, "H5Dget_space"); + + dtype = H5Dget_type (dataset1); + CHECK(dtype, FAIL, "H5Dget_type"); + + mspace = H5Screate_simple(1, marray, NULL); + CHECK(mspace, FAIL, "H5Screate_simple"); + + coord[0][0] = 3; + coord[0][1] = 3; + + ret = H5Sselect_elements (fspace, H5S_SELECT_SET, NUMP, (const hsize_t *)&coord); + CHECK(ret, FAIL, "H5Sselect_elements"); + + ret = H5Dwrite (dataset1, dtype, mspace, fspace, H5P_DEFAULT, val); + CHECK(ret, FAIL, "H5Dwrite"); + + ret = H5Tclose (dtype); + CHECK(ret, FAIL, "H5Tclose"); + + ret = H5Dclose (dataset1); + CHECK(ret, FAIL, "H5Dclose"); + + ret = H5Sclose (fspace); + CHECK(ret, FAIL, "H5Dclose"); + + ret = H5Sclose (mspace); + CHECK(ret, FAIL, "H5Sclose"); + + ret = H5Fclose (file1); + CHECK(ret, FAIL, "H5Fclose"); +} /* test_write_same_element */ + +/**************************************************************** ** ** test_vlstrings(): Main VL string testing routine. ** @@ -869,9 +967,10 @@ test_vlstrings(void) /* Test writing VL datasets in files with lots of unlinking */ test_vl_rewrite(); + /* Test writing to the same element more than once using H5Sselect_elements */ + test_write_same_element(); } /* test_vlstrings() */ - /*------------------------------------------------------------------------- * Function: cleanup_vlstrings * @@ -891,5 +990,6 @@ cleanup_vlstrings(void) { HDremove(DATAFILE); HDremove(DATAFILE2); + HDremove(DATAFILE3); } -- cgit v0.12 From 3e8599591504c95d8a97100b9546174f6132dc97 Mon Sep 17 00:00:00 2001 From: Songyu Lu Date: Thu, 6 Dec 2018 17:36:34 -0600 Subject: HDFFV-10635: Some minor changes to the test case and the comments in the library. --- src/H5HG.c | 5 +++-- test/tvlstr.c | 57 +++++++++++++++++++++++++++++---------------------------- 2 files changed, 32 insertions(+), 30 deletions(-) diff --git a/src/H5HG.c b/src/H5HG.c index 63d482e..df1c82d 100644 --- a/src/H5HG.c +++ b/src/H5HG.c @@ -786,9 +786,10 @@ H5HG_remove (H5F_t *f, H5HG_t *hobj) HDassert(hobj->idx < heap->nused); - /* When the application selects the same location to rewrite the element by using H5Sselect_elements, + /* When the application selects the same location to rewrite the VL element by using H5Sselect_elements, * it can happen that the entry has been removed by first rewrite. Here we simply skip the removal of - * the entry and let the second rewrite happen. */ + * the entry and let the second rewrite happen (see HDFFV-10635). In the future, it'd be nice to handle + * this situation in H5T_conv_vlen in H5Tconv.c instead of this level (HDFFV-10648). */ if(heap->obj[hobj->idx].nrefs == 0 && heap->obj[hobj->idx].size == 0 && !heap->obj[hobj->idx].begin) HGOTO_DONE(ret_value) diff --git a/test/tvlstr.c b/test/tvlstr.c index cc5a9c4..68d1070 100644 --- a/test/tvlstr.c +++ b/test/tvlstr.c @@ -30,8 +30,7 @@ /* 1-D dataset with fixed dimensions */ #define SPACE1_RANK 1 #define SPACE1_DIM1 4 -#define SPACE1_DIM2 2 -#define NUMP 2 +#define NUMP 4 #define VLSTR_TYPE "vl_string_type" @@ -862,84 +861,86 @@ static void test_write_same_element(void) hid_t file1, dataset1; hid_t mspace, fspace, dtype; hsize_t fdim[] = {SPACE1_DIM1}; - char *val[SPACE1_DIM2] = {"not", "bad"}; - hsize_t marray[] = {2}; + char *val[SPACE1_DIM1] = {"But", "reuniting", "is a", "great joy"}; + hsize_t marray[] = {NUMP}; hsize_t coord[SPACE1_RANK][NUMP]; herr_t ret; - char *wdata[SPACE1_DIM1] = {"Parting", "is such", "sweet", "sorrow."}; + char *wdata[SPACE1_DIM1] = {"Parting", "is such a", "sweet", "sorrow."}; - file1 = H5Fcreate (DATAFILE3, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + file1 = H5Fcreate(DATAFILE3, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); CHECK(file1, FAIL, "H5Fcreate"); - dtype = H5Tcopy (H5T_C_S1); + dtype = H5Tcopy(H5T_C_S1); CHECK(dtype, FAIL, "H5Tcopy"); - ret = H5Tset_size (dtype, H5T_VARIABLE); + ret = H5Tset_size(dtype, H5T_VARIABLE); CHECK(ret, FAIL, "H5Tset_size"); - fspace = H5Screate_simple (SPACE1_RANK, fdim, NULL); + fspace = H5Screate_simple(SPACE1_RANK, fdim, NULL); CHECK(fspace, FAIL, "H5Screate_simple"); - dataset1 = H5Dcreate (file1, DATASET, dtype, fspace, H5P_DEFAULT, + dataset1 = H5Dcreate(file1, DATASET, dtype, fspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); CHECK(dataset1, FAIL, "H5Dcreate"); ret = H5Dwrite(dataset1, dtype, H5S_ALL, H5S_ALL, H5P_DEFAULT, wdata); CHECK(ret, FAIL, "H5Dwrite"); - ret = H5Dclose (dataset1); + ret = H5Dclose(dataset1); CHECK(ret, FAIL, "H5Dclose"); - ret = H5Tclose (dtype); + ret = H5Tclose(dtype); CHECK(ret, FAIL, "H5Tclose"); - ret = H5Sclose (fspace); + ret = H5Sclose(fspace); CHECK(ret, FAIL, "H5Sclose"); - ret = H5Fclose (file1); + ret = H5Fclose(file1); CHECK(ret, FAIL, "H5Fclose"); /* - * Open the file. Select the same two points, write values to those point locations. + * Open the file. Select the same points, write values to those point locations. */ - file1 = H5Fopen (DATAFILE3, H5F_ACC_RDWR, H5P_DEFAULT); + file1 = H5Fopen(DATAFILE3, H5F_ACC_RDWR, H5P_DEFAULT); CHECK(file1, FAIL, "H5Fopen"); - dataset1 = H5Dopen (file1, DATASET, H5P_DEFAULT); + dataset1 = H5Dopen(file1, DATASET, H5P_DEFAULT); CHECK(dataset1, FAIL, "H5Dopen"); - fspace = H5Dget_space (dataset1); + fspace = H5Dget_space(dataset1); CHECK(fspace, FAIL, "H5Dget_space"); - dtype = H5Dget_type (dataset1); + dtype = H5Dget_type(dataset1); CHECK(dtype, FAIL, "H5Dget_type"); mspace = H5Screate_simple(1, marray, NULL); CHECK(mspace, FAIL, "H5Screate_simple"); - coord[0][0] = 3; - coord[0][1] = 3; + coord[0][0] = 0; + coord[0][1] = 2; + coord[0][2] = 2; + coord[0][3] = 0; - ret = H5Sselect_elements (fspace, H5S_SELECT_SET, NUMP, (const hsize_t *)&coord); + ret = H5Sselect_elements(fspace, H5S_SELECT_SET, NUMP, (const hsize_t *)&coord); CHECK(ret, FAIL, "H5Sselect_elements"); - ret = H5Dwrite (dataset1, dtype, mspace, fspace, H5P_DEFAULT, val); + ret = H5Dwrite(dataset1, dtype, mspace, fspace, H5P_DEFAULT, val); CHECK(ret, FAIL, "H5Dwrite"); - ret = H5Tclose (dtype); + ret = H5Tclose(dtype); CHECK(ret, FAIL, "H5Tclose"); - ret = H5Dclose (dataset1); + ret = H5Dclose(dataset1); CHECK(ret, FAIL, "H5Dclose"); - ret = H5Sclose (fspace); + ret = H5Sclose(fspace); CHECK(ret, FAIL, "H5Dclose"); - ret = H5Sclose (mspace); + ret = H5Sclose(mspace); CHECK(ret, FAIL, "H5Sclose"); - ret = H5Fclose (file1); + ret = H5Fclose(file1); CHECK(ret, FAIL, "H5Fclose"); } /* test_write_same_element */ -- cgit v0.12