diff options
-rw-r--r-- | release_docs/RELEASE.txt | 3 | ||||
-rw-r--r-- | src/H5Distore.c | 82 | ||||
-rw-r--r-- | test/dsets.c | 106 | ||||
-rw-r--r-- | test/istore.c | 14 |
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"); |