diff options
-rw-r--r-- | release_docs/RELEASE.txt | 3 | ||||
-rw-r--r-- | src/H5Dio.c | 12 | ||||
-rw-r--r-- | src/H5Shyper.c | 72 | ||||
-rw-r--r-- | src/H5Sprivate.h | 5 | ||||
-rw-r--r-- | test/tselect.c | 233 |
5 files changed, 312 insertions, 13 deletions
diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index 08e4edd..9338a31 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -93,6 +93,9 @@ Bug Fixes since HDF5-1.6.0 release Library ------- + - Fixed problem with selection offsets of hyperslab selections in + chunked datasets causing the library to go into an infinite loop. + QAK - 2003/12/06 - Fixed H5Giterate to avoid re-using index parameter after iteration callback has been called (allows iteration callback to modify the index parameter itself). QAK - 2003/12/06 diff --git a/src/H5Dio.c b/src/H5Dio.c index 1e6dcaf..562ee22 100644 --- a/src/H5Dio.c +++ b/src/H5Dio.c @@ -2293,6 +2293,10 @@ H5D_create_chunk_map(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *file_sp if(H5S_hyper_convert(fm->file_space)<0) HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to convert selection to span trees") + /* Normalize the hyperslab selections by adjusting them by the offset */ + if(H5S_hyper_normalize_offset(fm->file_space)<0) + HGOTO_ERROR (H5E_DATASET, H5E_BADSELECT, FAIL, "unable to normalize dataspace by offset") + #ifdef QAK { int mpi_rank; @@ -2339,6 +2343,10 @@ H5D_create_chunk_map(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *file_sp if(H5S_hyper_convert(fm->mem_space)<0) HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to convert selection to span trees") + /* Normalize the hyperslab selections by adjusting them by the offset */ + if(H5S_hyper_normalize_offset(fm->mem_space)<0) + HGOTO_ERROR (H5E_DATASET, H5E_BADSELECT, FAIL, "unable to normalize dataspace by offset") + /* If the selections are the same shape, use the file chunk information * to generate the memory chunk information quickly. */ @@ -2743,11 +2751,11 @@ H5D_create_chunk_mem_map_hyper(const fm_map *fm) assert(fm->f_ndims>0); /* Get offset of first block in file selection */ - if(H5S_get_select_hyper_blocklist(fm->file_space, (hsize_t)0, (hsize_t)1, file_off)<0) + if(H5S_get_select_hyper_blocklist(fm->file_space, 1, (hsize_t)0, (hsize_t)1, file_off)<0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection block info") /* Get offset of first block in memory selection */ - if(H5S_get_select_hyper_blocklist(fm->mem_space, (hsize_t)0, (hsize_t)1, mem_off)<0) + if(H5S_get_select_hyper_blocklist(fm->mem_space, 1, (hsize_t)0, (hsize_t)1, mem_off)<0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection block info") /* Calculate the adjustment for memory selection from file selection */ diff --git a/src/H5Shyper.c b/src/H5Shyper.c index 5ddf5a3..7422de2 100644 --- a/src/H5Shyper.c +++ b/src/H5Shyper.c @@ -2410,7 +2410,7 @@ done: REVISION LOG --------------------------------------------------------------------------*/ herr_t -H5S_get_select_hyper_blocklist(H5S_t *space, hsize_t startblock, hsize_t numblocks, hsize_t *buf) +H5S_get_select_hyper_blocklist(H5S_t *space, hbool_t internal, hsize_t startblock, hsize_t numblocks, hsize_t *buf) { H5S_hyper_dim_t *diminfo; /* Alias for dataspace's diminfo information */ hsize_t tmp_count[H5O_LAYOUT_NDIMS]; /* Temporary hyperslab counts */ @@ -2435,11 +2435,20 @@ H5S_get_select_hyper_blocklist(H5S_t *space, hsize_t startblock, hsize_t numbloc /* Set some convienence values */ ndims=space->extent.u.simple.rank; fast_dim=ndims-1; - /* - * Use the "application dimension information" to pass back to the user - * the blocks they set, not the optimized, internal information. - */ - diminfo=space->select.sel_info.hslab.app_diminfo; + + /* Check which set of dimension information to use */ + if(internal) + /* + * Use the "optimized dimension information" to pass back information + * on the blocks set, not the "application information". + */ + diminfo=space->select.sel_info.hslab.diminfo; + else + /* + * Use the "application dimension information" to pass back to the user + * the blocks they set, not the optimized, internal information. + */ + diminfo=space->select.sel_info.hslab.app_diminfo; /* Build the tables of count sizes as well as the initial offset */ for(i=0; i<ndims; i++) { @@ -2570,7 +2579,7 @@ H5Sget_select_hyper_blocklist(hid_t spaceid, hsize_t startblock, hsize_t numbloc /* Go get the correct number of blocks */ if(numblocks>0) - ret_value = H5S_get_select_hyper_blocklist(space,startblock,numblocks,buf); + ret_value = H5S_get_select_hyper_blocklist(space,0,startblock,numblocks,buf); else ret_value=SUCCEED; /* Successfully got 0 blocks... */ @@ -3919,6 +3928,55 @@ done: /*-------------------------------------------------------------------------- NAME + H5S_hyper_normalize_offset + PURPOSE + "Normalize" a hyperslab selection by adjusting it's coordinates by the + amount of the selection offset. + USAGE + herr_t H5S_hyper_normalize_offset(space) + H5S_t *space; IN/OUT: Pointer to dataspace to move + RETURNS + Non-negative on success, negative on failure + DESCRIPTION + Moves the hyperslab selection by the selection offset and then resets + the selection offset to zeros. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5S_hyper_normalize_offset(H5S_t *space) +{ + unsigned u; /* Local index variable */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5S_hyper_normalize_offset); + + assert(space); + + /* Check if there is an offset currently */ + if(space->select.offset) { + /* Invert the selection offset */ + for(u=0; u<space->extent.u.simple.rank; u++) + space->select.offset[u] =- space->select.offset[u]; + + /* Call the existing 'adjust' routine */ + if(H5S_hyper_adjust(space, space->select.offset)<0) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADSELECT, FAIL, "can't perform hyperslab normalization"); + + /* Zero out the selection offset */ + for(u=0; u<space->extent.u.simple.rank; u++) + space->select.offset[u] = 0; + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* H5S_hyper_normalize_offset() */ + + +/*-------------------------------------------------------------------------- + NAME H5S_hyper_append_span PURPOSE Create a new span and append to span list diff --git a/src/H5Sprivate.h b/src/H5Sprivate.h index c3089d6..a734993 100644 --- a/src/H5Sprivate.h +++ b/src/H5Sprivate.h @@ -233,8 +233,8 @@ H5_DLL herr_t H5S_select_elements (H5S_t *space, H5S_seloper_t op, /* Operations on hyperslab selections */ H5_DLL herr_t H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op, const hssize_t start[], const hsize_t *stride, const hsize_t count[], const hsize_t *block); -H5_DLL herr_t H5S_get_select_hyper_blocklist(H5S_t *space, hsize_t startblock, - hsize_t numblocks, hsize_t *buf); +H5_DLL herr_t H5S_get_select_hyper_blocklist(H5S_t *space, hbool_t internal, + hsize_t startblock, hsize_t numblocks, hsize_t *buf); H5_DLL herr_t H5S_hyper_add_span_element(H5S_t *space, unsigned rank, hssize_t *coords); H5_DLL herr_t H5S_hyper_reset_scratch(H5S_t *space); @@ -242,6 +242,7 @@ H5_DLL herr_t H5S_hyper_convert(H5S_t *space); H5_DLL htri_t H5S_hyper_intersect (H5S_t *space1, H5S_t *space2); H5_DLL herr_t H5S_hyper_adjust(H5S_t *space, const hssize_t *offset); H5_DLL herr_t H5S_hyper_move(H5S_t *space, const hssize_t *offset); +H5_DLL herr_t H5S_hyper_normalize_offset(H5S_t *space); /* Operations on selection iterators */ H5_DLL herr_t H5S_select_iter_init(H5S_sel_iter_t *iter, const H5S_t *space, size_t elmt_size); diff --git a/test/tselect.c b/test/tselect.c index c6c1a19..0d42dbb 100644 --- a/test/tselect.c +++ b/test/tselect.c @@ -12,8 +12,6 @@ * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* $Id$ */ - /*********************************************************** * * Test program: tselect @@ -125,6 +123,10 @@ #define CHUNK_Y 61 #define CHUNK_Z 181 +/* Basic chunk size */ +#define SPACE10_DIM1 180 +#define SPACE10_CHUNK_SIZE 12 + /* Location comparison function */ int compare_size_t(const void *s1, const void *s2); @@ -6542,6 +6544,230 @@ test_shape_same(void) /**************************************************************** ** +** test_select_hyper_chunk_offset(): Tests selections on dataspace, +** verify that offsets for hyperslab selections are working in +** chunked datasets. +** +****************************************************************/ +static void +test_select_hyper_chunk_offset(void) +{ + hid_t fid; /* File ID */ + hid_t sid; /* Dataspace ID */ + hid_t msid; /* Memory dataspace ID */ + hid_t did; /* Dataset ID */ + const hsize_t mem_dims[1] = { SPACE10_DIM1 }; /* Dataspace dimensions for memory */ + const hsize_t dims[1] = { 0 }; /* Dataspace initial dimensions */ + const hsize_t maxdims[1] = { H5S_UNLIMITED }; /* Dataspace mam dims */ + int *wbuf; /* Buffer for writing data */ + int *rbuf; /* Buffer for reading data */ + hid_t dcpl; /* Dataset creation property list ID */ + hsize_t chunks[1]={SPACE10_CHUNK_SIZE }; /* Chunk size */ + hssize_t start[1] = { 0 }; /* The start of the hyperslab */ + hsize_t count[1] = { SPACE10_CHUNK_SIZE }; /* The size of the hyperslab */ + int i,j; /* Local index */ + herr_t ret; /* Generic return value */ + + /* Output message about test being performed */ + MESSAGE(6, ("Testing hyperslab selections using offsets in chunked datasets\n")); + + /* Allocate buffers */ + wbuf= (int*)HDmalloc(sizeof(int)*SPACE10_DIM1); + CHECK(wbuf, NULL, "HDmalloc"); + rbuf= (int*)HDmalloc(sizeof(int)*SPACE10_DIM1); + CHECK(rbuf, NULL, "HDmalloc"); + + /* Initialize the write buffer */ + for(i=0; i<SPACE10_DIM1; i++) + wbuf[i]=i; + + /* Create file */ + fid = H5Fcreate (FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + CHECK(fid, FAIL, "H5Fcreate"); + + /* Create a dataset creation property list */ + dcpl = H5Pcreate (H5P_DATASET_CREATE); + CHECK(dcpl, FAIL, "H5Pcreate"); + + /* Set to chunked storage layout */ + ret=H5Pset_layout (dcpl, H5D_CHUNKED); + CHECK(ret, FAIL, "H5Pset_layout"); + + /* Set the chunk size */ + ret=H5Pset_chunk (dcpl, 1, chunks); + CHECK(ret, FAIL, "H5Pset_chunk"); + + /* Create dataspace for memory */ + msid = H5Screate_simple (1, mem_dims, NULL); + CHECK(msid, FAIL, "H5Screate_simple"); + + /* Select the correct chunk in the memory dataspace */ + ret=H5Sselect_hyperslab (msid, H5S_SELECT_SET, start, NULL, count, NULL); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + /* Create dataspace for dataset */ + sid = H5Screate_simple (1, dims, maxdims); + CHECK(sid, FAIL, "H5Screate_simple"); + + /* Create the dataset */ + did = H5Dcreate (fid, "fooData", H5T_NATIVE_INT, sid, dcpl); + CHECK(did, FAIL, "H5Dcreate"); + + /* Close the dataspace */ + ret=H5Sclose (sid); + CHECK(ret, FAIL, "H5Sclose"); + + /* Close the dataset creation property list */ + ret=H5Pclose (dcpl); + CHECK(ret, FAIL, "H5Pclose"); + + /* Loop over writing out each chunk */ + for(i=SPACE10_CHUNK_SIZE; i<=SPACE10_DIM1; i+=SPACE10_CHUNK_SIZE) { + hssize_t offset[1]; /* Offset of selection */ + hid_t fsid; /* File dataspace ID */ + hsize_t size[1]; /* The size to extend the dataset to */ + + /* Extend the dataset */ + size[0] = i; /* The size to extend the dataset to */ + ret=H5Dextend (did, size); + CHECK(ret, FAIL, "H5Dextend"); + + /* Get the (extended) dataspace from the dataset */ + fsid = H5Dget_space (did); + CHECK(fsid, FAIL, "H5Dget_space"); + + /* Select the correct chunk in the dataset */ + ret=H5Sselect_hyperslab (fsid, H5S_SELECT_SET, start, NULL, count, NULL); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + /* Set the selection offset for the file dataspace */ + offset[0] = i - SPACE10_CHUNK_SIZE; + ret=H5Soffset_simple (fsid, offset); + CHECK(ret, FAIL, "H5Soffset_simple"); + + /* Set the selection offset for the memory dataspace */ + offset[0] = SPACE10_DIM1-i; + ret=H5Soffset_simple (msid, offset); + CHECK(ret, FAIL, "H5Soffset_simple"); + + /* Write the data to the chunk */ + ret=H5Dwrite (did, H5T_NATIVE_INT, msid, fsid, H5P_DEFAULT, wbuf); + CHECK(ret, FAIL, "H5Soffset_simple"); + + /* Close the file dataspace copy */ + ret=H5Sclose (fsid); + CHECK(ret, FAIL, "H5Sclose"); + } + + /* Read the data back in */ + ret=H5Dread (did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, rbuf); + CHECK(ret, FAIL, "H5Soffset_simple"); + + /* Verify the information read in */ + for(i=0; i<SPACE10_DIM1; i+=SPACE10_CHUNK_SIZE) { + for(j=0; j<SPACE10_CHUNK_SIZE; j++) { + if(wbuf[i+j]!=rbuf[((SPACE10_DIM1-i)-SPACE10_CHUNK_SIZE)+j]) { + printf("Line: %d - Error! i=%d, j=%d, rbuf=%d, wbuf=%d\n",__LINE__,i,j,rbuf[((SPACE10_DIM1-i)-SPACE10_CHUNK_SIZE)+j],wbuf[i+j]); + num_errs++; + } /* end if */ + } /* end for */ + } /* end for */ + +/* Check with 'OR'ed set of hyperslab selections, which makes certain the + * hyperslab spanlist code gets tested. -QAK + */ + + /* Re-initialize the write buffer */ + for(i=0; i<SPACE10_DIM1; i++) + wbuf[i]=i*2; + + /* Change the selected the region in the memory dataspace */ + start[0] = 0; + count[0] = SPACE10_CHUNK_SIZE/3; + ret=H5Sselect_hyperslab (msid, H5S_SELECT_SET, start, NULL, count, NULL); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + start[0] = (2*SPACE10_CHUNK_SIZE)/3; + ret=H5Sselect_hyperslab (msid, H5S_SELECT_OR, start, NULL, count, NULL); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + /* Loop over writing out each chunk */ + for(i=SPACE10_CHUNK_SIZE; i<=SPACE10_DIM1; i+=SPACE10_CHUNK_SIZE) { + hssize_t offset[1]; /* Offset of selection */ + hid_t fsid; /* File dataspace ID */ + hsize_t size[1]; /* The size to extend the dataset to */ + + /* Extend the dataset */ + size[0] = i; /* The size to extend the dataset to */ + ret=H5Dextend (did, size); + CHECK(ret, FAIL, "H5Dextend"); + + /* Get the (extended) dataspace from the dataset */ + fsid = H5Dget_space (did); + CHECK(fsid, FAIL, "H5Dget_space"); + + /* Select the correct region in the dataset */ + start[0] = 0; + ret=H5Sselect_hyperslab (fsid, H5S_SELECT_SET, start, NULL, count, NULL); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + start[0] = (2*SPACE10_CHUNK_SIZE)/3; + ret=H5Sselect_hyperslab (fsid, H5S_SELECT_OR, start, NULL, count, NULL); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + /* Set the selection offset for the file dataspace */ + offset[0] = i - SPACE10_CHUNK_SIZE; + ret=H5Soffset_simple (fsid, offset); + CHECK(ret, FAIL, "H5Soffset_simple"); + + /* Set the selection offset for the memory dataspace */ + offset[0] = SPACE10_DIM1-i; + ret=H5Soffset_simple (msid, offset); + CHECK(ret, FAIL, "H5Soffset_simple"); + + /* Write the data to the chunk */ + ret=H5Dwrite (did, H5T_NATIVE_INT, msid, fsid, H5P_DEFAULT, wbuf); + CHECK(ret, FAIL, "H5Soffset_simple"); + + /* Close the file dataspace copy */ + ret=H5Sclose (fsid); + CHECK(ret, FAIL, "H5Sclose"); + } + + /* Read the data back in */ + ret=H5Dread (did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, rbuf); + CHECK(ret, FAIL, "H5Soffset_simple"); + + /* Verify the information read in */ + for(i=0; i<SPACE10_DIM1; i+=SPACE10_CHUNK_SIZE) { + for(j=0; j<SPACE10_CHUNK_SIZE; j++) { + /* We're not writing out the "middle" of each chunk, so don't check that */ + if(j<(SPACE10_CHUNK_SIZE/3) || j>=((2*SPACE10_CHUNK_SIZE)/3)) { + if(wbuf[i+j]!=rbuf[((SPACE10_DIM1-i)-SPACE10_CHUNK_SIZE)+j]) { + printf("Line: %d - Error! i=%d, j=%d, rbuf=%d, wbuf=%d\n",__LINE__,i,j,rbuf[((SPACE10_DIM1-i)-SPACE10_CHUNK_SIZE)+j],wbuf[i+j]); + num_errs++; + } /* end if */ + } /* end if */ + } /* end for */ + } /* end for */ + + /* Close the memory dataspace */ + ret=H5Sclose (msid); + CHECK(ret, FAIL, "H5Sclose"); + + /* Close the dataset */ + ret=H5Dclose (did); + CHECK(ret, FAIL, "H5Dclose"); + + /* Close the file */ + ret=H5Fclose (fid); + CHECK(ret, FAIL, "H5Fclose"); + + /* Free the buffers */ + HDfree(wbuf); + HDfree(rbuf); +} /* test_select_hyper_chunk_offset() */ + +/**************************************************************** +** ** test_select(): Main H5S selection testing routine. ** ****************************************************************/ @@ -6678,6 +6904,9 @@ test_select(void) /* Test scalar dataspaces in chunked datasets */ test_select_scalar_chunk(); + /* Test using selection offset on hyperslab in chunked dataset */ + test_select_hyper_chunk_offset(); + } /* test_select() */ |