diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2002-04-17 16:47:47 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2002-04-17 16:47:47 (GMT) |
commit | fa314a767ea91db101f8e36e97d89e7bb589bcf5 (patch) | |
tree | bfb90a313c5e86aa9dc73faccd9973489a7e0675 | |
parent | ee56e5272c4151a4a41cae16b46b97e817071548 (diff) | |
download | hdf5-fa314a767ea91db101f8e36e97d89e7bb589bcf5.zip hdf5-fa314a767ea91db101f8e36e97d89e7bb589bcf5.tar.gz hdf5-fa314a767ea91db101f8e36e97d89e7bb589bcf5.tar.bz2 |
[svn-r5191] Purpose:
Bug fix
Description:
When several level deep nested compound & VL datatypes are used, the data
in the nested compound datatypes is incorrectly sharing the same "background
buffer", causing data corruption when the data is written to the file.
Solution:
Allocate a separate background buffer for each level of the nested types
to convert. (Also allocate temporary background buffers for array
datatypes, where this sort of problem could occur also)
Added more regression tests to check for these errors.
Platforms tested:
FreeBSD 4.5 (sleipnir) & Solaris 2.6 (baldric)
-rw-r--r-- | release_docs/RELEASE.txt | 3 | ||||
-rw-r--r-- | src/H5D.c | 1 | ||||
-rw-r--r-- | src/H5Tconv.c | 95 | ||||
-rw-r--r-- | test/Makefile.in | 2 | ||||
-rw-r--r-- | test/tarray.c | 39 | ||||
-rw-r--r-- | test/tmisc.c | 359 |
6 files changed, 463 insertions, 36 deletions
diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index f9acb56..e103899 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -35,6 +35,9 @@ Bug Fixes since HDF5-1.4.2 Library ------- + * Fixed bug where the data for several level deep nested compound & + variable-length datatypes used for datasets were getting corrupted when + written to the file. QAK - 2002/04/17 * Fixed bug where selection offset was being ignored for certain hyperslab selections when optimized I/O was being performed. QAK - 2002/04/02 * Added serial multi-gigabyte file size test. "test/big -h" shows @@ -3007,6 +3007,7 @@ printf("%s: check 2.0, src_type_size=%d, dst_type_size=%d, target_size=%d\n",FUN #ifdef QAK printf("%s: check 4.0, nelmts=%d, request_nelmts=%d, need_bkg=%d\n", FUNC,(int)nelmts,(int)request_nelmts,(int)need_bkg); + printf("%s: check 4.1, tconv_buf=%p, bkg_buf=%p\n",FUNC,tconv_buf,bkg_buf); #endif /* Start strip mining... */ diff --git a/src/H5Tconv.c b/src/H5Tconv.c index 16fc719..00cde28 100644 --- a/src/H5Tconv.c +++ b/src/H5Tconv.c @@ -45,6 +45,9 @@ static int interface_initialize_g = 0; /* Declare a free list to manage pieces of vlen data */ H5FL_BLK_DEFINE_STATIC(vlen_seq); +/* Declare a free list to manage pieces of array data */ +H5FL_BLK_DEFINE_STATIC(array_seq); + /* * These macros are for the bodies of functions that convert buffers of one * integer type to another using hardware. They all start with `H5T_CONV_' @@ -1175,10 +1178,7 @@ H5T_conv_b_b(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, * Purpose: Check whether the source or destination datatypes require a * background buffer for the conversion. * - * Currently, only compound datatypes require a background buffer, - * but since they can be embedded in variable-length or array datatypes, - * those types must ask for a background buffer if they have compound - * components. + * Currently, only compound datatypes require a background buffer. * * Return: Non-negative on success/Negative on failure * @@ -1198,14 +1198,8 @@ H5T_conv_need_bkg (H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata) assert(dst); assert(cdata); - /* Compound datatypes only need a "temp" buffer */ + /* Compound datatypes need a buffer */ if (H5T_detect_class(src,H5T_COMPOUND)==TRUE || H5T_detect_class(dst,H5T_COMPOUND)==TRUE) - cdata->need_bkg = H5T_BKG_TEMP; - - /* Compound datatypes need a "yes" buffer though */ - if (H5T_detect_class(src,H5T_VLEN)==TRUE || H5T_detect_class(dst,H5T_VLEN)==TRUE) - cdata->need_bkg = H5T_BKG_YES; - if (H5T_detect_class(src,H5T_ARRAY)==TRUE || H5T_detect_class(dst,H5T_ARRAY)==TRUE) cdata->need_bkg = H5T_BKG_YES; FUNC_LEAVE (SUCCEED); @@ -2200,7 +2194,7 @@ H5T_conv_enum(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, herr_t H5T_conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, size_t buf_stride, size_t bkg_stride, void *_buf, - void *_bkg, hid_t dset_xfer_plist) + void UNUSED *_bkg, hid_t dset_xfer_plist) { H5T_path_t *tpath; /* Type conversion path */ hid_t tsrc_id = -1, tdst_id = -1;/*temporary type atoms */ @@ -2208,15 +2202,17 @@ H5T_conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, H5T_t *dst = NULL; /*destination data type */ hsize_t olap; /*num overlapping elements */ uint8_t *s, *sp, *d, *dp; /*source and dest traversal ptrs */ - uint8_t **dptr; /*pointer to correct destination pointer*/ + uint8_t **dptr; /*pointer to correct destination pointer*/ size_t src_delta, dst_delta; /*source & destination stride */ - hssize_t seq_len; /*the number of elements in the current sequence*/ + hssize_t seq_len; /*the number of elements in the current sequence*/ size_t src_base_size, dst_base_size;/*source & destination base size*/ - size_t src_size, dst_size;/*source & destination total size in bytes*/ + size_t src_size, dst_size; /*source & destination total size in bytes*/ void *conv_buf=NULL; /*temporary conversion buffer */ - size_t conv_buf_size; /*size of conversion buffer in bytes */ + hsize_t conv_buf_size=0; /*size of conversion buffer in bytes */ + void *bkg_buf=NULL; /*temporary background buffer */ + hsize_t bkg_buf_size=0; /*size of background buffer in bytes */ uint8_t dbuf[64],*dbuf_ptr=dbuf;/*temp destination buffer */ - int direction; /*direction of traversal */ + int direction; /*direction of traversal */ hsize_t elmtno; /*element number counter */ FUNC_ENTER (H5T_conv_vlen, FAIL); @@ -2239,8 +2235,8 @@ H5T_conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, assert (H5T_VLEN==src->type); assert (H5T_VLEN==dst->type); - /* Check if we need a background buffer */ - H5T_conv_need_bkg (src, dst, cdata); + /* Variable-length types don't need a background buffer */ + cdata->need_bkg = H5T_BKG_NO; break; @@ -2320,6 +2316,14 @@ H5T_conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, } } + /* Check if we need a background buffer for this conversion */ + if(tpath->cdata.need_bkg) { + /* Set up initial background buffer */ + bkg_buf_size=MAX(src_base_size,dst_base_size); + if ((bkg_buf=H5FL_BLK_ALLOC(vlen_seq,bkg_buf_size,0))==NULL) + HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion"); + } /* end if */ + for (elmtno=0; elmtno<nelmts; elmtno++) { s = sp; d = *dptr; @@ -2345,10 +2349,19 @@ H5T_conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, HRETURN_ERROR(H5E_DATATYPE, H5E_READERROR, FAIL, "can't read VL data"); + /* Check if background buffer is large enough, resize if necessary */ + /* (Chain off the conversion buffer size) */ + if(tpath->cdata.need_bkg && bkg_buf_size<conv_buf_size) { + /* Set up initial background buffer */ + bkg_buf_size=conv_buf_size; + if((bkg_buf=H5FL_BLK_REALLOC(vlen_seq,bkg_buf,bkg_buf_size))==NULL) + HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion"); + } /* end if */ + /* Convert VL sequence */ H5_CHECK_OVERFLOW(seq_len,hssize_t,hsize_t); if (H5T_convert(tpath, tsrc_id, tdst_id, (hsize_t)seq_len, 0, bkg_stride, - conv_buf, _bkg, dset_xfer_plist)<0) + conv_buf, bkg_buf, dset_xfer_plist)<0) HRETURN_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "datatype conversion failed"); @@ -2376,9 +2389,13 @@ H5T_conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, } /* end if */ } - /* Release the conversion buffer */ + /* Release the conversion buffer (always allocated) */ H5FL_BLK_FREE(vlen_seq,conv_buf); + /* Release the background buffer, if we have one */ + if(bkg_buf!=NULL) + H5FL_BLK_FREE(vlen_seq,bkg_buf); + /* Release the temporary datatype IDs used */ if (tsrc_id >= 0) H5I_dec_ref(tsrc_id); @@ -2413,17 +2430,19 @@ H5T_conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, herr_t H5T_conv_array(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, size_t buf_stride, size_t bkg_stride, void *_buf, - void *_bkg, hid_t dset_xfer_plist) + void UNUSED *_bkg, hid_t dset_xfer_plist) { - H5T_path_t *tpath; /* Type conversion path */ - hid_t tsrc_id = -1, tdst_id = -1;/*temporary type atoms */ - H5T_t *src = NULL; /*source data type */ - H5T_t *dst = NULL; /*destination data type */ - uint8_t *sp, *dp; /*source and dest traversal ptrs */ + H5T_path_t *tpath; /* Type conversion path */ + hid_t tsrc_id = -1, tdst_id = -1;/*temporary type atoms */ + H5T_t *src = NULL; /*source data type */ + H5T_t *dst = NULL; /*destination data type */ + uint8_t *sp, *dp; /*source and dest traversal ptrs */ size_t src_delta, dst_delta; /*source & destination stride */ - int direction; /*direction of traversal */ + int direction; /*direction of traversal */ hsize_t elmtno; /*element number counter */ - int i; /* local index variable */ + int i; /* local index variable */ + void *bkg_buf=NULL; /*temporary background buffer */ + hsize_t bkg_buf_size=0; /*size of background buffer in bytes */ FUNC_ENTER (H5T_conv_array, FAIL); @@ -2457,8 +2476,8 @@ H5T_conv_array(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, HRETURN_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "array datatypes do not have the same dimension permutations"); #endif /* LATER */ - /* Check if we need a background buffer */ - H5T_conv_need_bkg (src, dst, cdata); + /* Array datatypes don't need a background buffer */ + cdata->need_bkg = H5T_BKG_NO; break; @@ -2509,13 +2528,21 @@ H5T_conv_array(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, } } + /* Check if we need a background buffer for this conversion */ + if(tpath->cdata.need_bkg) { + /* Allocate background buffer */ + bkg_buf_size=src->u.array.nelem*MAX(src->size,dst->size); + if ((bkg_buf=H5FL_BLK_ALLOC(array_seq,bkg_buf_size,0))==NULL) + HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion"); + } /* end if */ + /* Perform the actual conversion */ for (elmtno=0; elmtno<nelmts; elmtno++) { /* Copy the source array into the correct location for the destination */ HDmemmove(dp, sp, src->size); /* Convert array */ - if (H5T_convert(tpath, tsrc_id, tdst_id, (hsize_t)src->u.array.nelem, 0, bkg_stride, dp, _bkg, dset_xfer_plist)<0) + if (H5T_convert(tpath, tsrc_id, tdst_id, (hsize_t)src->u.array.nelem, 0, bkg_stride, dp, bkg_buf, dset_xfer_plist)<0) HRETURN_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "datatype conversion failed"); /* Advance the source & destination pointers */ @@ -2523,6 +2550,10 @@ H5T_conv_array(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, dp += dst_delta; } + /* Release the background buffer, if we have one */ + if(bkg_buf!=NULL) + H5FL_BLK_FREE(array_seq,bkg_buf); + /* Release the temporary datatype IDs used */ if (tsrc_id >= 0) H5I_dec_ref(tsrc_id); diff --git a/test/Makefile.in b/test/Makefile.in index 97d8302..5707005 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -50,7 +50,7 @@ MOSTLYCLEAN=cmpd_dset.h5 dataset.h5 extend.h5 istore.h5 tfile1.h5 tfile2.h5 \ mount_[0-9].h5 testmeta.h5 ttime.h5 trefer[12].h5 tvltypes.h5 \ tvlstr.h5 flush.h5 enum1.h5 titerate.h5 ttsafe.h5 tarray1.h5 \ tgenprop.h5 tmisc.h5 tmisc2a.h5 tmisc2b.h5 tmisc3.h5 tmisc4a.h5 \ - tmisc4b.h5 set_extent_read.h5 set_extent_create.h5 + tmisc4b.h5 tmisc5.h5 set_extent_read.h5 set_extent_create.h5 CLEAN=$(TIMINGS) ## Source and object files for programs... The TEST_SRC list contains all the diff --git a/test/tarray.c b/test/tarray.c index 6b5e556..05bc8e0 100644 --- a/test/tarray.c +++ b/test/tarray.c @@ -1684,6 +1684,7 @@ test_array_bkg(void) status = H5Dwrite (dataset, type, H5S_ALL, H5S_ALL, H5P_DEFAULT, fld); CHECK(status, FAIL, "H5Dwrite"); + /* Read just the field changed */ status = H5Dread (dataset, type, H5S_ALL, H5S_ALL, H5P_DEFAULT, fldr); CHECK(status, FAIL, "H5Dread"); @@ -1695,15 +1696,47 @@ test_array_bkg(void) continue; } - status = H5Dclose(dataset); - CHECK(status, FAIL, "H5Dclose"); - status = H5Tclose (type); CHECK(status, FAIL, "H5Tclose"); status = H5Tclose (array_dt); CHECK(status, FAIL, "H5Tclose"); + type = H5Dget_type(dataset); + CHECK(type, FAIL, "H5Dget_type"); + + /* Read the entire dataset again */ + status = H5Dread(dataset, type, H5S_ALL, H5S_ALL, H5P_DEFAULT, cfr); + CHECK(status, FAIL, "H5Dread"); + + /* Verify correct data */ + /* ------------------- */ + for (i = 0; i < LENGTH; i++) { + for (j = 0; j < ALEN; j++) { + if(cf[i].a[j]!=cfr[i].a[j]) { + num_errs++; + printf("Field a data doesn't match, cf[%d].a[%d]=%d, cfr[%d].a[%d]=%d\n",(int)i,(int)j,(int)cf[i].a[j],(int)i,(int)j,(int)cfr[i].a[j]); + continue; + } + if(cf[i].b[j]!=cfr[i].b[j]) { + num_errs++; + printf("Field b data doesn't match, cf[%d].b[%d]=%f, cfr[%d].b[%d]=%f\n",(int)i,(int)j,(float)cf[i].b[j],(int)i,(int)j,(float)cfr[i].b[j]); + continue; + } + if(cf[i].c[j]!=cfr[i].c[j]) { + num_errs++; + printf("Field c data doesn't match, cf[%d].b[%d]=%f, cfr[%d].b[%d]=%f\n",(int)i,(int)j,(float)cf[i].c[j],(int)i,(int)j,(float)cfr[i].c[j]); + continue; + } + } + } + + status = H5Dclose(dataset); + CHECK(status, FAIL, "H5Dclose"); + + status = H5Tclose (type); + CHECK(status, FAIL, "H5Tclose"); + status = H5Fclose(fid); CHECK(status, FAIL, "H5Fclose"); diff --git a/test/tmisc.c b/test/tmisc.c index 03ce311..3112e98 100644 --- a/test/tmisc.c +++ b/test/tmisc.c @@ -57,6 +57,55 @@ typedef struct { #define MISC4_GROUP_1 "/Group1" #define MISC4_GROUP_2 "/Group2" +/* Definitions for misc. test #5 */ +#define MISC5_FILE "tmisc5.h5" +#define MISC5_DSETNAME "dset1" +#define MISC5_DSETRANK 1 +#define MISC5_NELMTOPLVL 1 +#define MISC5_DBGNELM1 2 +#define MISC5_DBGNELM2 1 +#define MISC5_DBGNELM3 1 +#define MISC5_DBGELVAL1 999999999 +#define MISC5_DBGELVAL2 888888888 +#define MISC5_DBGELVAL3 777777777 + +typedef struct +{ + int st1_el1; + hvl_t st1_el2; +} misc5_struct1; + +typedef struct +{ + int st2_el1; + hvl_t st2_el2; +} misc5_struct2; + +typedef struct +{ + int st3_el1; +} misc5_struct3; + +typedef struct +{ + hid_t st3h_base; + hid_t st3h_id; +} misc5_struct3_hndl; + +typedef struct +{ + hid_t st2h_base; + hid_t st2h_id; + misc5_struct3_hndl *st2h_st3hndl; +} misc5_struct2_hndl; + +typedef struct +{ + hid_t st1h_base; + hid_t st1h_id; + misc5_struct2_hndl *st1h_st2hndl; +} misc5_struct1_hndl; + /**************************************************************** ** ** test_misc1(): test unlinking a dataset from a group and immediately @@ -440,6 +489,314 @@ test_misc4(void) /**************************************************************** ** +** test_misc5(): Test several level deep nested compound & VL datatypes +** +****************************************************************/ + +/*********************** struct3 ***********************/ + +static misc5_struct3_hndl * +create_struct3(void) +{ + misc5_struct3_hndl *str3hndl; /* New 'struct3' created */ + herr_t ret; /* For error checking */ + + str3hndl=malloc(sizeof(misc5_struct3_hndl)); + CHECK(str3hndl,NULL,"malloc"); + + str3hndl->st3h_base=H5Tcreate( H5T_COMPOUND, sizeof(misc5_struct3)); + CHECK(str3hndl->st3h_base,FAIL,"H5Tcreate"); + + ret=H5Tinsert(str3hndl->st3h_base, "st3_el1", HOFFSET( misc5_struct3, st3_el1), H5T_NATIVE_INT); + CHECK(ret,FAIL,"H5Tinsert"); + + str3hndl->st3h_id=H5Tvlen_create(str3hndl->st3h_base); + CHECK(str3hndl->st3h_id,FAIL,"H5Tvlen_create"); + + return(str3hndl); +} + +static void +delete_struct3(misc5_struct3_hndl *str3hndl) +{ + herr_t ret; /* For error checking */ + + ret=H5Tclose(str3hndl->st3h_id); + CHECK(ret,FAIL,"H5Tclose"); + + ret=H5Tclose(str3hndl->st3h_base); + CHECK(ret,FAIL,"H5Tclose"); + + free(str3hndl); +} + +static void +set_struct3(misc5_struct3 *buf) +{ + buf->st3_el1=MISC5_DBGELVAL3; +} + +/*********************** struct2 ***********************/ + +static misc5_struct2_hndl * +create_struct2(void) +{ + misc5_struct2_hndl *str2hndl; /* New 'struct2' created */ + herr_t ret; /* For error checking */ + + str2hndl=malloc(sizeof(misc5_struct2_hndl)); + CHECK(str2hndl,NULL,"malloc"); + + str2hndl->st2h_base=H5Tcreate( H5T_COMPOUND, sizeof(misc5_struct2)); + CHECK(str2hndl->st2h_base,FAIL,"H5Tcreate"); + + ret=H5Tinsert(str2hndl->st2h_base, "st2_el1", HOFFSET( misc5_struct2, st2_el1), H5T_NATIVE_INT); + CHECK(ret,FAIL,"H5Tinsert"); + + str2hndl->st2h_st3hndl=create_struct3(); + CHECK(str2hndl->st2h_st3hndl,NULL,"create_struct3"); + + ret=H5Tinsert(str2hndl->st2h_base, "st2_el2", HOFFSET(misc5_struct2, st2_el2), str2hndl->st2h_st3hndl->st3h_id); + CHECK(ret,FAIL,"H5Tinsert"); + + str2hndl->st2h_id= H5Tvlen_create(str2hndl->st2h_base); + CHECK(str2hndl->st2h_id,FAIL,"H5Tvlen_create"); + + return(str2hndl); +} + +static void +delete_struct2(misc5_struct2_hndl *str2hndl) +{ + herr_t ret; /* For error checking */ + + ret=H5Tclose(str2hndl->st2h_id); + CHECK(ret,FAIL,"H5Tclose"); + + delete_struct3(str2hndl->st2h_st3hndl); + + H5Tclose(str2hndl->st2h_base); + CHECK(ret,FAIL,"H5Tclose"); + + free(str2hndl); +} + +static void +set_struct2(misc5_struct2 *buf) +{ + unsigned i; /* Local index variable */ + + buf->st2_el1=MISC5_DBGELVAL2; + buf->st2_el2.len=MISC5_DBGNELM3; + + buf->st2_el2.p=malloc((buf->st2_el2.len)*sizeof(misc5_struct3)); + CHECK(buf->st2_el2.p,NULL,"malloc"); + + for(i=0; i<(buf->st2_el2.len); i++) + set_struct3(&(((misc5_struct3 *)(buf->st2_el2.p))[i])); +} + +static void +clear_struct2(misc5_struct2 *buf) +{ + free(buf->st2_el2.p); +} + +/*********************** struct1 ***********************/ + +static misc5_struct1_hndl * +create_struct1(void) +{ + misc5_struct1_hndl *str1hndl; /* New 'struct1' created */ + herr_t ret; /* For error checking */ + + str1hndl=malloc(sizeof(misc5_struct1_hndl)); + CHECK(str1hndl,NULL,"malloc"); + + str1hndl->st1h_base=H5Tcreate(H5T_COMPOUND, sizeof(misc5_struct1)); + CHECK(str1hndl->st1h_base,FAIL,"H5Tcreate"); + + ret=H5Tinsert(str1hndl->st1h_base, "st1_el1", HOFFSET(misc5_struct1, st1_el1), H5T_NATIVE_INT); + CHECK(ret,FAIL,"H5Tinsert"); + + str1hndl->st1h_st2hndl=create_struct2(); + CHECK(str1hndl->st1h_st2hndl,NULL,"create_struct2"); + + ret=H5Tinsert(str1hndl->st1h_base, "st1_el2", HOFFSET(misc5_struct1, st1_el2), str1hndl->st1h_st2hndl->st2h_id); + CHECK(ret,FAIL,"H5Tinsert"); + + str1hndl->st1h_id=H5Tvlen_create(str1hndl->st1h_base); + CHECK(str1hndl->st1h_id,FAIL,"H5Tvlen_create"); + + return(str1hndl); +} + +static void +delete_struct1(misc5_struct1_hndl *str1hndl) +{ + herr_t ret; /* For error checking */ + + ret=H5Tclose(str1hndl->st1h_id); + CHECK(ret,FAIL,"H5Tclose"); + + delete_struct2(str1hndl->st1h_st2hndl); + + ret=H5Tclose(str1hndl->st1h_base); + CHECK(ret,FAIL,"H5Tclose"); + + free(str1hndl); +} + +static void +set_struct1(misc5_struct1 *buf) +{ + unsigned i; /* Local index variable */ + + buf->st1_el1=MISC5_DBGELVAL1; + buf->st1_el2.len=MISC5_DBGNELM2; + + buf->st1_el2.p=malloc((buf->st1_el2.len)*sizeof(misc5_struct2)); + CHECK(buf->st1_el2.p,NULL,"malloc"); + + for(i=0; i<(buf->st1_el2.len); i++) + set_struct2(&(((misc5_struct2 *)(buf->st1_el2.p))[i])); +} + +static void +clear_struct1(misc5_struct1 *buf) +{ + unsigned i; + + for(i=0;i<buf->st1_el2.len;i++) + clear_struct2(&((( misc5_struct2 *)(buf->st1_el2.p))[i])); + free(buf->st1_el2.p); +} + +static void +test_misc5(void) +{ + hid_t loc_id, space_id, dataset_id; + hid_t mem_type_id; + misc5_struct1_hndl *str1hndl; + hsize_t dims[MISC5_DSETRANK]; + hvl_t buf; + unsigned i,j,k; + herr_t ret; + + /* Output message about test being performed */ + MESSAGE(5, ("Testing several level deep nested compound & VL datatypes \n")); + + /* Write the dataset out */ + loc_id=H5Fcreate(MISC5_FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + CHECK(loc_id,FAIL,"H5Fcreate"); + + /* Create the memory structure to write */ + str1hndl=create_struct1(); + CHECK(str1hndl,NULL,"create_struct1"); + + /* Create the dataspace */ + dims[0]=MISC5_NELMTOPLVL; + space_id=H5Screate_simple(MISC5_DSETRANK, dims, NULL); + CHECK(space_id,FAIL,"H5Screate_simple"); + + /* Create the dataset */ + dataset_id=H5Dcreate(loc_id, MISC5_DSETNAME, str1hndl->st1h_id, space_id, H5P_DEFAULT); + CHECK(dataset_id,FAIL,"H5Dcreate"); + + /* Create the variable-length buffer */ + buf.len=MISC5_DBGNELM1; + buf.p=malloc((buf.len)*sizeof(misc5_struct1)); + CHECK(buf.p,NULL,"malloc"); + + /* Create the top-level VL information */ + for(i=0; i<MISC5_DBGNELM1; i++) + set_struct1(&(((misc5_struct1 *) (buf.p))[i])); + + /* Write the data out */ + ret=H5Dwrite(dataset_id, str1hndl->st1h_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, &buf); + CHECK(ret,FAIL,"H5Dwrite"); + + /* Release the top-level VL information */ + for(j=0; j<MISC5_DBGNELM1; j++) + clear_struct1(&((( misc5_struct1 *)(buf.p))[j])); + + /* Free the variable-length buffer */ + free(buf.p); + + /* Close dataset */ + ret=H5Dclose(dataset_id); + CHECK(ret,FAIL,"H5Dclose"); + + /* Close dataspace */ + ret=H5Sclose(space_id); + CHECK(ret,FAIL,"H5Sclose"); + + /* Delete memory structures */ + delete_struct1(str1hndl); + + /* Close file */ + ret=H5Fclose(loc_id); + CHECK(ret,FAIL,"H5Fclose"); + + + /* Read the dataset back in & verify it */ + loc_id=H5Fopen(MISC5_FILE, H5F_ACC_RDONLY, H5P_DEFAULT); + CHECK(loc_id,FAIL,"H5Fopen"); + + /* Open dataset again */ + dataset_id=H5Dopen(loc_id, MISC5_DSETNAME); + CHECK(dataset_id,FAIL,"H5Dopen"); + + /* Get the dataset's datatype */ + mem_type_id=H5Dget_type(dataset_id); + CHECK(mem_type_id,FAIL,"H5Dget_type"); + + /* Get the dataset's dataspace */ + space_id=H5Dget_space(dataset_id); + CHECK(space_id,FAIL,"H5Dget_space"); + + /* Read the data back in */ + ret=H5Dread(dataset_id, mem_type_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, &buf); + CHECK(ret,FAIL,"H5Dread"); + + /* Verify the correct information was read in */ + for(i=0; i<(buf.len); i++) { + /* printf("[%d]=%d\n",i, ((misc5_struct1 *)(buf.p))[i].st1_el1); */ + VERIFY(((misc5_struct1 *)(buf.p))[i].st1_el1,MISC5_DBGELVAL1,"H5Dread"); + for(j=0; j<(((misc5_struct1 *)(buf.p)) [i].st1_el2.len); j++) { + /* printf(" [%d]=%d\n",j, ((misc5_struct2 *)(((misc5_struct1 *) (buf.p))[i].st1_el2.p))[j].st2_el1); */ + VERIFY(((misc5_struct2 *)(((misc5_struct1 *) (buf.p))[i].st1_el2.p))[j].st2_el1, MISC5_DBGELVAL2,"H5Dread"); + for(k=0; k<(((misc5_struct2 *) (((misc5_struct1 *)(buf.p))[i]. st1_el2.p))[j].st2_el2.len); k++) { + /* printf(" [%d]=%d\n",k, ((misc5_struct3 *)(((misc5_struct2 *) (((misc5_struct1 *)(buf.p))[i]. st1_el2.p))[j].st2_el2.p))[k].st3_el1); */ + VERIFY(((misc5_struct3 *)(((misc5_struct2 *) (((misc5_struct1 *)(buf.p))[i]. st1_el2.p))[j].st2_el2.p))[k].st3_el1, MISC5_DBGELVAL3,"H5Dread"); + } /* end for */ + } + } + + /* Reclaim the memory for the VL information */ + ret=H5Dvlen_reclaim(mem_type_id, space_id, H5P_DEFAULT, &buf); + CHECK(ret,FAIL,"H5Dvlen_reclaim"); + + /* Close dataspace */ + ret=H5Sclose(space_id); + CHECK(ret,FAIL,"H5Sclose"); + + /* Close dataset */ + ret=H5Tclose(mem_type_id); + CHECK(ret,FAIL,"H5Tclose"); + + /* Close dataset */ + ret=H5Dclose(dataset_id); + CHECK(ret,FAIL,"H5Dclose"); + + /* Close file */ + ret=H5Fclose(loc_id); + CHECK(ret,FAIL,"H5Fclose"); + +} /* end test_misc5() */ + +/**************************************************************** +** ** test_misc(): Main misc. test routine. ** ****************************************************************/ @@ -453,6 +810,7 @@ test_misc(void) test_misc2(); /* Test storing a VL-derived datatype in two different files */ test_misc3(); /* Test reading from chunked dataset with non-zero fill value */ test_misc4(); /* Test retrieving the fileno for various objects with H5Gget_objinfo() */ + test_misc5(); /* Test several level deep nested compound & VL datatypes */ } /* test_misc() */ @@ -480,4 +838,5 @@ cleanup_misc(void) remove(MISC3_FILE); remove(MISC4_FILE_1); remove(MISC4_FILE_2); + remove(MISC5_FILE); } |