summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2002-04-17 16:45:03 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2002-04-17 16:45:03 (GMT)
commit98c39db39136e96424d5ab2f846e62d4c71c30c5 (patch)
treec9968cd384c509dc8a5947fbb70f560bd398f7b2
parente69cdafdadbf43284e24c542a3458a68fa5df9c9 (diff)
downloadhdf5-98c39db39136e96424d5ab2f846e62d4c71c30c5.zip
hdf5-98c39db39136e96424d5ab2f846e62d4c71c30c5.tar.gz
hdf5-98c39db39136e96424d5ab2f846e62d4c71c30c5.tar.bz2
[svn-r5190] 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.txt3
-rw-r--r--src/H5D.c1
-rw-r--r--src/H5Tconv.c95
-rw-r--r--test/Makefile.in2
-rw-r--r--test/tarray.c39
-rw-r--r--test/tmisc.c360
6 files changed, 464 insertions, 36 deletions
diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt
index 9f874bf..3c619aa 100644
--- a/release_docs/RELEASE.txt
+++ b/release_docs/RELEASE.txt
@@ -70,6 +70,9 @@ New Features
Bug Fixes since HDF5-1.4.3 Release
==================================
+ * 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
* Fixed limitation in h5dumper with object names which reached over 1024
diff --git a/src/H5D.c b/src/H5D.c
index 764e135..7be70bd 100644
--- a/src/H5D.c
+++ b/src/H5D.c
@@ -2324,6 +2324,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 96e3dfa..b3c2e11 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_'
@@ -1177,10 +1180,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
*
@@ -1200,14 +1200,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);
@@ -2202,7 +2196,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)
{
const H5D_xfer_t *xfer_parms = NULL;
H5T_path_t *tpath; /* Type conversion path */
@@ -2211,15 +2205,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 */
- hsize_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);
@@ -2242,8 +2238,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;
@@ -2334,6 +2330,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;
@@ -2358,10 +2362,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");
@@ -2389,9 +2402,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);
@@ -2426,17 +2443,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);
@@ -2470,8 +2489,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;
@@ -2530,6 +2549,14 @@ 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 */
@@ -2537,7 +2564,7 @@ H5T_conv_array(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
/* 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)
+ dp, bkg_buf, dset_xfer_plist)<0)
HRETURN_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL,
"datatype conversion failed");
@@ -2546,6 +2573,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 0ebbdb8..bf5a37d 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -49,7 +49,7 @@ MOSTLYCLEAN=cmpd_dset.h5 dataset.h5 extend.h5 istore.h5 tfile1.h5 tfile2.h5 \
fillval_[0-9].h5 fillval.raw 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
+ tmisc2b.h5 tmisc3.h5 tmisc4a.h5 tmisc4b.h5 tmisc5.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 a45006c..b27d0bc 100644
--- a/test/tarray.c
+++ b/test/tarray.c
@@ -1772,6 +1772,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");
@@ -1783,15 +1784,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 549bde3..6423cfb 100644
--- a/test/tmisc.c
+++ b/test/tmisc.c
@@ -57,6 +57,56 @@ 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
@@ -441,6 +491,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.
**
****************************************************************/
@@ -454,6 +812,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() */
@@ -481,4 +840,5 @@ cleanup_misc(void)
remove(MISC3_FILE);
remove(MISC4_FILE_1);
remove(MISC4_FILE_2);
+ remove(MISC5_FILE);
}