summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2003-12-13 18:14:36 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2003-12-13 18:14:36 (GMT)
commita8161177b98fb2a85c92288294efe3fbace2fbeb (patch)
tree86cd881bd3f6294015588df4fa38d15101cc35d5
parent15830ae10ac760ee46777f7bba6c9e10ed0e5906 (diff)
downloadhdf5-a8161177b98fb2a85c92288294efe3fbace2fbeb.zip
hdf5-a8161177b98fb2a85c92288294efe3fbace2fbeb.tar.gz
hdf5-a8161177b98fb2a85c92288294efe3fbace2fbeb.tar.bz2
[svn-r7943] Purpose:
Bug fix. Description: Using a selection offset with hyperslab selections in chunked datasets was getting into an infinite loop and hanging the application. Solution: Apply the selection offset to the hyperslab selection properly. Platforms tested: FreeBSD 4.9 (sleipnir) w & w/o parallel h5committest
-rw-r--r--release_docs/RELEASE.txt3
-rw-r--r--src/H5Dio.c12
-rw-r--r--src/H5Shyper.c72
-rw-r--r--src/H5Sprivate.h5
-rw-r--r--test/tselect.c233
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() */