From a8161177b98fb2a85c92288294efe3fbace2fbeb Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Sat, 13 Dec 2003 13:14:36 -0500 Subject: [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 --- release_docs/RELEASE.txt | 3 + src/H5Dio.c | 12 ++- src/H5Shyper.c | 72 +++++++++++++-- src/H5Sprivate.h | 5 +- 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; i0) - 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; uextent.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; uextent.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=((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() */ -- cgit v0.12