summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2004-08-25 08:30:32 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2004-08-25 08:30:32 (GMT)
commit22d00ce23f0c39789d146e440d8b251b0c6b2268 (patch)
tree82a49a68d53bf1a3c1967c92fb5c9086e86b07bc
parent0a965d2236a811f66ff42df732031a150e1020ac (diff)
downloadhdf5-22d00ce23f0c39789d146e440d8b251b0c6b2268.zip
hdf5-22d00ce23f0c39789d146e440d8b251b0c6b2268.tar.gz
hdf5-22d00ce23f0c39789d146e440d8b251b0c6b2268.tar.bz2
[svn-r9155] Purpose:
Bug fix (sorta) Description: Change reading of "missing" chunks from datasets with undefined fill values to not overwrite the application buffer with random garbage from memory. Note that this is almost the same, since whatever garbage the application had in those locations will still be there... Platforms tested: FreeBSD 4.10 (sleipnir) IRIX64 6.5 (modi4) h5committested
-rw-r--r--release_docs/RELEASE.txt3
-rw-r--r--src/H5Distore.c82
-rw-r--r--test/dsets.c106
-rw-r--r--test/istore.c14
4 files changed, 196 insertions, 9 deletions
diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt
index 9f6ec10..888590c 100644
--- a/release_docs/RELEASE.txt
+++ b/release_docs/RELEASE.txt
@@ -174,6 +174,9 @@ Bug Fixes since HDF5-1.6.0 release
Library
-------
+ - Changed H5Dread() to not overwrite data in an application's buffer
+ with garbage when accessing a chunked dataset with an undefined
+ fill value and an unwritten chunk is uncountered. QAK - 2004/08/25
- Fixed error which could cause a core dump when a type conversion
routine was registered after a compound datatype had been
converted and then an equivalment compound datatype was converted
diff --git a/src/H5Distore.c b/src/H5Distore.c
index cbd7a0f..5182d29 100644
--- a/src/H5Distore.c
+++ b/src/H5Distore.c
@@ -1821,9 +1821,7 @@ H5D_istore_readvv(H5F_t *f, const struct H5D_dxpl_cache_t *dxpl_cache, hid_t dxp
{
H5D_istore_ud1_t udata; /*B-tree pass-through */
haddr_t chunk_addr; /* Chunk address on disk */
-#ifndef NDEBUG
size_t u; /* Local index variables */
-#endif
ssize_t ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5D_istore_readvv, FAIL);
@@ -1886,6 +1884,86 @@ HDfprintf(stderr,"%s: mem_offset_arr[%Zu]=%Hu\n",FUNC,*mem_curr_seq,mem_offset_a
unsigned idx_hint=0; /* Cache index hint */
ssize_t naccessed; /* Number of bytes accessed in chunk */
+ /* If the chunk address is not defined, check if the fill value is
+ * undefined also. If both situations hold, don't bother copying
+ * values to the destination buffer, since they will just be
+ * garbage.
+ *
+ * Ideally, this will eventually be checked at a higher level and
+ * the entire I/O operation on the chunk will be skipped. -QAK
+ */
+ if(!H5F_addr_defined(chunk_addr)) {
+ const H5O_fill_t *fill=&(dset->dcpl_cache.fill); /* Fill value info */
+ H5D_fill_time_t fill_time=dset->dcpl_cache.fill_time; /* Fill time */
+ H5D_fill_value_t fill_status;
+ H5D_rdcc_t *rdcc = &(dset->cache.chunk);/*raw data chunk cache*/
+ hbool_t found = FALSE; /*already in cache? */
+
+ /* Check if the chunk is in the cache (but hasn't been written to disk yet) */
+ if (rdcc->nslots>0) {
+ unsigned idx=H5D_HASH(dset,store->chunk.index); /* Cache entry index */
+ H5D_rdcc_ent_t *ent = rdcc->slot[idx]; /* Cache entry */
+
+ /* Potential match... */
+ if (ent) {
+ for (u=0, found=TRUE; u<dset->layout.u.chunk.ndims; u++) {
+ if (store->chunk.offset[u]!=ent->offset[u]) {
+ found = FALSE;
+ break;
+ } /* end if */
+ } /* end for */
+ } /* end if */
+ } /* end if */
+
+ /* If the chunk is in the cache, then it must have valid data */
+ if(!found) {
+ /* Check if the fill value is defined */
+ if (H5P_is_fill_value_defined(fill, &fill_status) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't tell if fill value defined");
+
+ /* If we are never to return fill values, or if we would return them
+ * but they aren't set, process the entire set of I/O vectors and
+ * get out now.
+ */
+ if(fill_time==H5D_FILL_TIME_NEVER ||
+ (fill_time==H5D_FILL_TIME_IFSET && fill_status!=H5D_FILL_VALUE_USER_DEFINED)) {
+ size_t size; /* Size of sequence in bytes */
+ size_t v; /* Local index variable */
+ ssize_t bytes_processed=0; /* Eventual return value */
+
+ /* Work through all the sequences */
+ for(u=*mem_curr_seq, v=*chunk_curr_seq; u<mem_max_nseq && v<chunk_max_nseq; ) {
+ /* Choose smallest buffer to write */
+ if(chunk_len_arr[v]<mem_len_arr[u])
+ size=chunk_len_arr[v];
+ else
+ size=mem_len_arr[u];
+
+ /* Update source information */
+ chunk_len_arr[v]-=size;
+ chunk_offset_arr[v]+=size;
+ if(chunk_len_arr[v]==0)
+ v++;
+
+ /* Update destination information */
+ mem_len_arr[u]-=size;
+ mem_offset_arr[u]+=size;
+ if(mem_len_arr[u]==0)
+ u++;
+
+ /* Increment number of bytes copied */
+ bytes_processed+=(ssize_t)size;
+ } /* end for */
+
+ /* Update current sequence vectors */
+ *mem_curr_seq=u;
+ *chunk_curr_seq=v;
+
+ HGOTO_DONE(bytes_processed);
+ } /* end if */
+ } /* end if */
+ } /* end if */
+
/*
* Lock the chunk, copy from application to chunk, then unlock the
* chunk.
diff --git a/test/dsets.c b/test/dsets.c
index cd3cbc5..6b29031 100644
--- a/test/dsets.c
+++ b/test/dsets.c
@@ -117,6 +117,10 @@ const char *FILENAME[] = {
/* Names for zero-dim test */
#define ZERODIM_DATASET "zerodim"
+/* Parameters for zero-dim test */
+#define MISSING_CHUNK_DATASET "missing_chunk"
+#define MISSING_CHUNK_DIM 100
+
/* Shared global arrays */
#define DSET_DIM1 100
#define DSET_DIM2 200
@@ -3677,6 +3681,107 @@ error:
/*-------------------------------------------------------------------------
+ * Function: test_missing_chunk
+ *
+ * Purpose: Tests that reads from chunked dataset with undefined fill value and
+ * not all chunks written don't overwrite data in user's buffer
+ * for missing chunks.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, August 25, 2004
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+test_missing_chunk(hid_t file)
+{
+ hid_t s=-1, d=-1, dcpl=-1;
+ hssize_t hs_start[1];
+ hsize_t hs_stride[1],
+ hs_count[1],
+ hs_block[1];
+ int wdata[MISSING_CHUNK_DIM],
+ rdata[MISSING_CHUNK_DIM];
+ hsize_t dsize=100, dmax=H5S_UNLIMITED, csize=5;
+ size_t u;
+
+ TESTING("Read dataset with unwritten chunk & undefined fill value");
+
+ /* Initialize data */
+ for(u=0; u<MISSING_CHUNK_DIM; u++) {
+ wdata[u]=u;
+ rdata[u]=911;
+ } /* end for */
+
+ /* Create dataspace */
+ if((s = H5Screate_simple(1, &dsize, &dmax))<0) TEST_ERROR;
+
+ /* Create dataset creation property list */
+ if((dcpl = H5Pcreate(H5P_DATASET_CREATE))<0) TEST_ERROR;
+
+ /* Set to chunked */
+ if(H5Pset_chunk(dcpl, 1, &csize)<0) TEST_ERROR;
+
+ /* Undefine fill value */
+ if(H5Pset_fill_value(dcpl, H5T_NATIVE_INT, NULL)<0) TEST_ERROR;
+
+ /* Create dataset */
+ if((d = H5Dcreate(file, MISSING_CHUNK_DATASET, H5T_NATIVE_INT, s, dcpl))<0) TEST_ERROR;
+
+ /* Select elements in every other chunk */
+ hs_start[0]=0;
+ hs_stride[0]=10;
+ hs_count[0]=10;
+ hs_block[0]=5;
+ if (H5Sselect_hyperslab(s, H5S_SELECT_SET, hs_start, hs_stride, hs_count,
+ hs_block)<0) TEST_ERROR;
+
+ /* Write selected data */
+ if(H5Dwrite(d, H5T_NATIVE_INT, s, s, H5P_DEFAULT, wdata)<0) TEST_ERROR;
+
+ /* Read all data */
+ if(H5Dread(d, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, rdata)<0) TEST_ERROR;
+
+ /* Validata values read */
+ for(u=0; u<MISSING_CHUNK_DIM; u++) {
+ if((u%10)>=5) {
+ if(rdata[u]!=911) {
+ printf(" Line %d: Incorrect value, rdata[%u]=%d\n",__LINE__,(unsigned)u,rdata[u]);
+ TEST_ERROR;
+ } /* end if */
+ } /* end if */
+ else {
+ if(rdata[u]!=wdata[u]) {
+ printf(" Line %d: Incorrect value, wdata[%u]=%d, rdata[%u]=%d\n",__LINE__,(unsigned)u,wdata[u],(unsigned)u,rdata[u]);
+ TEST_ERROR;
+ } /* end if */
+ } /* end else */
+ } /* end for */
+
+ /* Close everything */
+ if(H5Pclose(dcpl)<0) TEST_ERROR;
+ if(H5Sclose(s)<0) TEST_ERROR;
+ if(H5Dclose(d)<0) TEST_ERROR;
+
+ PASSED();
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Pclose(dcpl);
+ H5Dclose(d);
+ H5Sclose(s);
+ } H5E_END_TRY;
+ return -1;
+} /* end test_zero_dims() */
+
+
+/*-------------------------------------------------------------------------
* Function: main
*
* Purpose: Tests the dataset interface (H5D)
@@ -3745,6 +3850,7 @@ main(void)
nerrors += test_filter_delete(file)<0 ?1:0;
nerrors += test_filters_endianess()<0 ?1:0;
nerrors += test_zero_dims(file)<0 ?1:0;
+ nerrors += test_missing_chunk(file)<0 ?1:0;
if (H5Fclose(file)<0) goto error;
if (nerrors) goto error;
diff --git a/test/istore.c b/test/istore.c
index 0830ff4..f7baf31 100644
--- a/test/istore.c
+++ b/test/istore.c
@@ -298,17 +298,17 @@ test_extend(hid_t f, const char *prefix,
#if 0
if (0 == ctr)
fprintf(stderr,"\n");
- fprintf(stderr," Insert: ctr=%d, corner=(%d", ctr, offset[0]);
+ fprintf(stderr," Insert: ctr=%lu, corner=(%ld", (unsigned long)ctr, (long)offset[0]);
if (ndims > 1)
- fprintf(stderr,",%d", offset[1]);
+ fprintf(stderr,",%ld", (long)offset[1]);
if (ndims > 2)
- fprintf(stderr,",%d", offset[2]);
- fprintf(stderr,"), size=(%d", size[0]);
+ fprintf(stderr,",%ld", (long)offset[2]);
+ fprintf(stderr,"), size=(%lu", (unsigned long)size[0]);
if (ndims > 1)
- fprintf(stderr,",%d", size[1]);
+ fprintf(stderr,",%lu", (unsigned long)size[1]);
if (ndims > 2)
- fprintf(stderr,",%d", size[2]);
- fprintf(stderr,"), %d element%s", nelmts, 1 == nelmts ? "" : "s");
+ fprintf(stderr,",%lu", (unsigned long)size[2]);
+ fprintf(stderr,"), %lu element%s", (unsigned long)nelmts, 1 == nelmts ? "" : "s");
if (0 == nelmts)
fprintf(stderr," *SKIPPED*");
fprintf(stderr,"\n");