mirror of
https://github.com/HDFGroup/hdf5.git
synced 2025-02-23 16:20:57 +08:00
[svn-r10951] Purpose:
Bug fix Description: Hyperslab selections that had a selection offset and were applied to a chunked dataset could get into an infinite loop or core dump if the same selection was used multiple times, with different selection offsets. Solution: "Normalize" the selection with the selection offset, generate the selections for the chunks overlapped and then "denormalize" the selection. Platforms tested: FreeBSD 4.11 (sleipnir) Too minor to require h5committest
This commit is contained in:
parent
04e424638a
commit
d641030436
@ -290,6 +290,11 @@ Bug Fixes since HDF5-1.6.0 release
|
||||
|
||||
Library
|
||||
-------
|
||||
- Fixed bug with hyperslab selections that use selection offsets and
|
||||
operate on chunked datasets going into infinite loop or dumping
|
||||
core. QAK - 2005/06/17
|
||||
- Corrected memory leak and possible corruption when opening a group.
|
||||
QAK - 2005/06/17
|
||||
- Added check for opaque datatype tags being too long (check against
|
||||
H5T_OPAQUE_TAG_MAX, currently set to 256). QAK - 2005/06/14
|
||||
- Fixed various errors in maintaining names for open objects in the
|
||||
|
22
src/H5Dio.c
22
src/H5Dio.c
@ -2358,6 +2358,8 @@ H5D_create_chunk_map(const H5D_t *dataset, const H5T_t *mem_type, const H5S_t *f
|
||||
H5S_t *tmp_mspace=NULL; /* Temporary memory dataspace */
|
||||
H5S_t *equiv_mspace=NULL; /* Equivalent memory dataspace */
|
||||
hbool_t equiv_mspace_init=0;/* Equivalent memory dataspace was created */
|
||||
hssize_t old_offset[H5O_LAYOUT_NDIMS]; /* Old selection offset */
|
||||
hbool_t file_space_normalized = FALSE; /* File dataspace was normalized */
|
||||
hid_t f_tid=(-1); /* Temporary copy of file datatype for iteration */
|
||||
hbool_t iter_init=0; /* Selection iteration info has been initialized */
|
||||
unsigned f_ndims; /* The number of dimensions of the file's dataspace */
|
||||
@ -2404,6 +2406,16 @@ H5D_create_chunk_map(const H5D_t *dataset, const H5T_t *mem_type, const H5S_t *f
|
||||
if(H5S_get_simple_extent_dims(file_space, fm->f_dims, NULL)<0)
|
||||
HGOTO_ERROR (H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimensionality")
|
||||
|
||||
/* Normalize hyperslab selections by adjusting them by the offset */
|
||||
/* (It might be worthwhile to normalize both the file and memory dataspaces
|
||||
* before any (contiguous, chunked, etc) file I/O operation, in order to
|
||||
* speed up hyperslab calculations by removing the extra checks and/or
|
||||
* additions involving the offset and the hyperslab selection -QAK)
|
||||
*/
|
||||
if(H5S_hyper_normalize_offset(file_space, old_offset)<0)
|
||||
HGOTO_ERROR (H5E_DATASET, H5E_BADSELECT, FAIL, "unable to normalize dataspace by offset")
|
||||
file_space_normalized = TRUE;
|
||||
|
||||
/* Decide the number of chunks in each dimension*/
|
||||
for(u=0; u<f_ndims; u++) {
|
||||
/* Keep the size of the chunk dimensions as hsize_t for various routines */
|
||||
@ -2564,6 +2576,10 @@ done:
|
||||
if(H5I_dec_ref(f_tid)<0)
|
||||
HDONE_ERROR (H5E_DATASET, H5E_CANTFREE, FAIL, "Can't decrement temporary datatype ID")
|
||||
} /* end if */
|
||||
if(file_space_normalized) {
|
||||
if(H5S_hyper_denormalize_offset(file_space, old_offset)<0)
|
||||
HGOTO_ERROR (H5E_DATASET, H5E_BADSELECT, FAIL, "unable to normalize dataspace by offset")
|
||||
} /* end if */
|
||||
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5D_create_chunk_map() */
|
||||
@ -2722,12 +2738,6 @@ H5D_create_chunk_file_map_hyper(const fm_map *fm)
|
||||
HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to convert selection to span trees")
|
||||
} /* end if */
|
||||
|
||||
/* Normalize hyperslab selections by adjusting them by the offset */
|
||||
if(H5S_hyper_normalize_offset(tmp_fchunk)<0) {
|
||||
(void)H5S_close(tmp_fchunk);
|
||||
HGOTO_ERROR (H5E_DATASET, H5E_BADSELECT, FAIL, "unable to normalize dataspace by offset")
|
||||
} /* end if */
|
||||
|
||||
/* "AND" temporary chunk and current chunk */
|
||||
if(H5S_select_hyperslab(tmp_fchunk,H5S_SELECT_AND,coords,NULL,fm->chunk_dim,NULL)<0) {
|
||||
(void)H5S_close(tmp_fchunk);
|
||||
|
@ -3671,7 +3671,7 @@ done:
|
||||
REVISION LOG
|
||||
--------------------------------------------------------------------------*/
|
||||
static htri_t
|
||||
H5S_hyper_intersect_block_helper (const H5S_hyper_span_info_t *spans, hssize_t *offset, hsize_t *start, hsize_t *end)
|
||||
H5S_hyper_intersect_block_helper (const H5S_hyper_span_info_t *spans, hsize_t *start, hsize_t *end)
|
||||
{
|
||||
H5S_hyper_span_t *curr; /* Pointer to current span in 1st span tree */
|
||||
htri_t status; /* Status from recursive call */
|
||||
@ -3681,7 +3681,6 @@ H5S_hyper_intersect_block_helper (const H5S_hyper_span_info_t *spans, hssize_t *
|
||||
|
||||
/* Sanity check */
|
||||
assert(spans);
|
||||
assert(offset);
|
||||
assert(start);
|
||||
assert(end);
|
||||
|
||||
@ -3691,11 +3690,11 @@ H5S_hyper_intersect_block_helper (const H5S_hyper_span_info_t *spans, hssize_t *
|
||||
/* Iterate over the spans in the tree */
|
||||
while(curr!=NULL) {
|
||||
/* Check for span entirely before block */
|
||||
if(((hssize_t)curr->high+*offset)<(hssize_t)*start)
|
||||
if(curr->high < *start)
|
||||
/* Advance to next span in this dimension */
|
||||
curr=curr->next;
|
||||
/* If this span is past the end of the block, then we're done in this dimension */
|
||||
else if(((hssize_t)curr->low+*offset)>(hssize_t)*end)
|
||||
else if(curr->low > *end)
|
||||
HGOTO_DONE(FALSE)
|
||||
/* block & span overlap */
|
||||
else {
|
||||
@ -3703,7 +3702,7 @@ H5S_hyper_intersect_block_helper (const H5S_hyper_span_info_t *spans, hssize_t *
|
||||
HGOTO_DONE(TRUE)
|
||||
else {
|
||||
/* Recursively check spans in next dimension down */
|
||||
if((status=H5S_hyper_intersect_block_helper(curr->down,offset+1,start+1,end+1))<0)
|
||||
if((status=H5S_hyper_intersect_block_helper(curr->down,start+1,end+1))<0)
|
||||
HGOTO_ERROR(H5E_DATASPACE, H5E_BADSELECT, FAIL, "can't perform hyperslab intersection check");
|
||||
|
||||
/* If there is a span intersection in the down dimensions, the span trees overlap */
|
||||
@ -3763,7 +3762,7 @@ H5S_hyper_intersect_block (H5S_t *space, hsize_t *start, hsize_t *end)
|
||||
HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "dataspace does not have span tree");
|
||||
|
||||
/* Perform the span-by-span intersection check */
|
||||
if((ret_value=H5S_hyper_intersect_block_helper(space->select.sel_info.hslab->span_lst,space->select.offset,start,end))<0)
|
||||
if((ret_value=H5S_hyper_intersect_block_helper(space->select.sel_info.hslab->span_lst,start,end))<0)
|
||||
HGOTO_ERROR(H5E_DATASPACE, H5E_BADSELECT, FAIL, "can't perform hyperslab intersection check");
|
||||
|
||||
done:
|
||||
@ -4106,20 +4105,22 @@ done:
|
||||
"Normalize" a hyperslab selection by adjusting it's coordinates by the
|
||||
amount of the selection offset.
|
||||
USAGE
|
||||
herr_t H5S_hyper_normalize_offset(space)
|
||||
herr_t H5S_hyper_normalize_offset(space, old_offset)
|
||||
H5S_t *space; IN/OUT: Pointer to dataspace to move
|
||||
hssize_t *old_offset; OUT: Pointer to space to store old offset
|
||||
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.
|
||||
Copies the current selection offset into the array provided, then
|
||||
inverts the selection offset, subtracts the offset from the hyperslab
|
||||
selection and resets the offset to zero.
|
||||
GLOBAL VARIABLES
|
||||
COMMENTS, BUGS, ASSUMPTIONS
|
||||
EXAMPLES
|
||||
REVISION LOG
|
||||
--------------------------------------------------------------------------*/
|
||||
herr_t
|
||||
H5S_hyper_normalize_offset(H5S_t *space)
|
||||
H5S_hyper_normalize_offset(H5S_t *space, hssize_t *old_offset)
|
||||
{
|
||||
unsigned u; /* Local index variable */
|
||||
herr_t ret_value=SUCCEED; /* Return value */
|
||||
@ -4131,23 +4132,70 @@ H5S_hyper_normalize_offset(H5S_t *space)
|
||||
/* Check for 'all' selection, instead of a hyperslab selection */
|
||||
/* (Technically, this check shouldn't be in the "hyperslab" routines...) */
|
||||
if(H5S_GET_SELECT_TYPE(space)!=H5S_SEL_ALL) {
|
||||
/* Invert the selection offset */
|
||||
for(u=0; u<space->extent.rank; u++)
|
||||
space->select.offset[u] =- space->select.offset[u];
|
||||
/* Copy & invert the selection offset */
|
||||
for(u=0; u<space->extent.rank; u++) {
|
||||
old_offset[u] = space->select.offset[u];
|
||||
space->select.offset[u] = -space->select.offset[u];
|
||||
} /* end for */
|
||||
|
||||
/* Call the existing 'adjust' routine */
|
||||
if(H5S_hyper_adjust_s(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.rank; u++)
|
||||
space->select.offset[u] = 0;
|
||||
HDmemset(space->select.offset, 0, sizeof(hssize_t) * space->extent.rank);
|
||||
} /* end if */
|
||||
|
||||
done:
|
||||
FUNC_LEAVE_NOAPI(ret_value);
|
||||
} /* H5S_hyper_normalize_offset() */
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
NAME
|
||||
H5S_hyper_denormalize_offset
|
||||
PURPOSE
|
||||
"Denormalize" a hyperslab selection by reverse adjusting it's coordinates
|
||||
by the amount of the former selection offset.
|
||||
USAGE
|
||||
herr_t H5S_hyper_normalize_offset(space, old_offset)
|
||||
H5S_t *space; IN/OUT: Pointer to dataspace to move
|
||||
hssize_t *old_offset; IN: Pointer to old offset array
|
||||
RETURNS
|
||||
Non-negative on success, negative on failure
|
||||
DESCRIPTION
|
||||
Subtracts the old offset from the current selection (canceling out the
|
||||
effect of the "normalize" routine), then restores the old offset into
|
||||
the dataspace.
|
||||
GLOBAL VARIABLES
|
||||
COMMENTS, BUGS, ASSUMPTIONS
|
||||
EXAMPLES
|
||||
REVISION LOG
|
||||
--------------------------------------------------------------------------*/
|
||||
herr_t
|
||||
H5S_hyper_denormalize_offset(H5S_t *space, const hssize_t *old_offset)
|
||||
{
|
||||
herr_t ret_value=SUCCEED; /* Return value */
|
||||
|
||||
FUNC_ENTER_NOAPI_NOINIT(H5S_hyper_denormalize_offset);
|
||||
|
||||
assert(space);
|
||||
|
||||
/* Check for 'all' selection, instead of a hyperslab selection */
|
||||
/* (Technically, this check shouldn't be in the "hyperslab" routines...) */
|
||||
if(H5S_GET_SELECT_TYPE(space)!=H5S_SEL_ALL) {
|
||||
/* Call the existing 'adjust' routine */
|
||||
if(H5S_hyper_adjust_s(space, old_offset)<0)
|
||||
HGOTO_ERROR(H5E_DATASPACE, H5E_BADSELECT, FAIL, "can't perform hyperslab normalization");
|
||||
|
||||
/* Copy the selection offset over */
|
||||
HDmemcpy(space->select.offset, old_offset, sizeof(hssize_t) * space->extent.rank);
|
||||
} /* end if */
|
||||
|
||||
done:
|
||||
FUNC_LEAVE_NOAPI(ret_value);
|
||||
} /* H5S_hyper_denormalize_offset() */
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
NAME
|
||||
|
@ -258,7 +258,8 @@ H5_DLL htri_t H5S_hyper_intersect_block (H5S_t *space, hsize_t *start, hsize_t *
|
||||
H5_DLL herr_t H5S_hyper_adjust_u(H5S_t *space, const hsize_t *offset);
|
||||
H5_DLL herr_t H5S_hyper_adjust_s(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);
|
||||
H5_DLL herr_t H5S_hyper_normalize_offset(H5S_t *space, hssize_t *old_offset);
|
||||
H5_DLL herr_t H5S_hyper_denormalize_offset(H5S_t *space, const hssize_t *old_offset);
|
||||
|
||||
/* 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);
|
||||
|
108
test/tselect.c
108
test/tselect.c
@ -133,6 +133,11 @@
|
||||
#define SPACE11_DIM2 100
|
||||
#define SPACE11_NPOINTS 4
|
||||
|
||||
/* Information for offsets w/chunks test #2 */
|
||||
#define SPACE12_RANK 1
|
||||
#define SPACE12_DIM0 25
|
||||
#define SPACE12_CHUNK_DIM0 5
|
||||
|
||||
/* Location comparison function */
|
||||
int compare_size_t(const void *s1, const void *s2);
|
||||
|
||||
@ -6739,6 +6744,108 @@ test_select_hyper_chunk_offset(void)
|
||||
HDfree(rbuf);
|
||||
} /* test_select_hyper_chunk_offset() */
|
||||
|
||||
/****************************************************************
|
||||
**
|
||||
** test_select_hyper_chunk_offset2(): Tests selections on dataspace,
|
||||
** another test to verify that offsets for hyperslab selections are
|
||||
** working in chunked datasets.
|
||||
**
|
||||
****************************************************************/
|
||||
static void
|
||||
test_select_hyper_chunk_offset2(void)
|
||||
{
|
||||
hid_t file, dataset; /* handles */
|
||||
hid_t dataspace;
|
||||
hid_t memspace;
|
||||
hid_t dcpl; /* Dataset creation property list */
|
||||
herr_t status;
|
||||
unsigned data_out[SPACE12_DIM0]; /* output buffer */
|
||||
unsigned data_in[SPACE12_CHUNK_DIM0]; /* input buffer */
|
||||
hsize_t dims[SPACE12_RANK]={SPACE12_DIM0}; /* Dimension size */
|
||||
hsize_t chunk_dims[SPACE12_RANK]={SPACE12_CHUNK_DIM0}; /* Chunk size */
|
||||
hsize_t start[SPACE12_RANK]; /* Start of hyperslab */
|
||||
hsize_t count[SPACE12_RANK]; /* Size of hyperslab */
|
||||
hssize_t offset[SPACE12_RANK]; /* hyperslab offset in the file */
|
||||
unsigned u, v; /* Local index variables */
|
||||
|
||||
/* Output message about test being performed */
|
||||
MESSAGE(6, ("Testing more hyperslab selections using offsets in chunked datasets\n"));
|
||||
|
||||
/* Initialize data to write out */
|
||||
for (u = 0; u < SPACE12_DIM0; u++)
|
||||
data_out[u] = u;
|
||||
|
||||
/* Create the file */
|
||||
file = H5Fcreate(FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
|
||||
CHECK(file, FAIL, "H5Fcreate");
|
||||
|
||||
/* Create dataspace */
|
||||
dataspace = H5Screate_simple(SPACE12_RANK, dims, NULL);
|
||||
CHECK(dataspace, FAIL, "H5Screate_simple");
|
||||
|
||||
/* Create dataset creation property list */
|
||||
dcpl = H5Pcreate(H5P_DATASET_CREATE);
|
||||
CHECK(dcpl, FAIL, "H5Pcreate");
|
||||
|
||||
/* Set chunk sizes */
|
||||
status = H5Pset_chunk(dcpl, SPACE12_RANK, chunk_dims);
|
||||
CHECK(status, FAIL, "H5Pset_chunk");
|
||||
|
||||
/* Create dataset */
|
||||
dataset = H5Dcreate(file, DATASETNAME, H5T_NATIVE_UINT, dataspace, dcpl);
|
||||
CHECK(dataset, FAIL, "H5Dcreate");
|
||||
|
||||
/* Close DCPL */
|
||||
status = H5Pclose(dcpl);
|
||||
CHECK(status, FAIL, "H5Pclose");
|
||||
|
||||
/* Write out entire dataset */
|
||||
status = H5Dwrite(dataset, H5T_NATIVE_UINT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data_out);
|
||||
CHECK(status, FAIL, "H5Dclose");
|
||||
|
||||
/* Create memory dataspace (same size as a chunk) */
|
||||
memspace = H5Screate_simple(SPACE12_RANK, chunk_dims, NULL);
|
||||
CHECK(dataspace, FAIL, "H5Screate_simple");
|
||||
|
||||
/*
|
||||
* Define hyperslab in the file dataspace.
|
||||
*/
|
||||
start[0] = 0;
|
||||
count[0] = SPACE12_CHUNK_DIM0;
|
||||
status = H5Sselect_hyperslab(dataspace, H5S_SELECT_SET, start, NULL, count, NULL);
|
||||
CHECK(status, FAIL, "H5Sselect_hyperslab");
|
||||
|
||||
/* Loop through retrieving data from file, checking it against data written */
|
||||
for(u = 0; u < SPACE12_DIM0; u += SPACE12_CHUNK_DIM0) {
|
||||
/* Set the offset of the file selection */
|
||||
offset[0] = u;
|
||||
status = H5Soffset_simple(dataspace, offset);
|
||||
CHECK(status, FAIL, "H5Soffset_simple");
|
||||
|
||||
/* Read in buffer of data */
|
||||
status = H5Dread(dataset, H5T_NATIVE_UINT, memspace, dataspace,
|
||||
H5P_DEFAULT, data_in);
|
||||
CHECK(status, FAIL, "H5Dread");
|
||||
|
||||
/* Check data read in */
|
||||
for(v = 0; v < SPACE12_CHUNK_DIM0; v++)
|
||||
if(data_out[u + v] != data_in[v])
|
||||
TestErrPrintf("Error! data_out[%u]=%u, data_in[%u]=%u\n",(unsigned)(u + v), data_out[u + v], v, data_in[v]);
|
||||
} /* end for */
|
||||
|
||||
status = H5Dclose(dataset);
|
||||
CHECK(status, FAIL, "H5Dclose");
|
||||
|
||||
status = H5Sclose(dataspace);
|
||||
CHECK(status, FAIL, "H5Sclose");
|
||||
|
||||
status = H5Sclose(memspace);
|
||||
CHECK(status, FAIL, "H5Sclose");
|
||||
|
||||
status = H5Fclose(file);
|
||||
CHECK(status, FAIL, "H5Fclose");
|
||||
} /* test_select_hyper_chunk_offset2() */
|
||||
|
||||
/****************************************************************
|
||||
**
|
||||
** test_select_bounds(): Tests selection bounds on dataspaces,
|
||||
@ -7083,6 +7190,7 @@ test_select(void)
|
||||
|
||||
/* Test using selection offset on hyperslab in chunked dataset */
|
||||
test_select_hyper_chunk_offset();
|
||||
test_select_hyper_chunk_offset2();
|
||||
|
||||
/* Test selection bounds with & without offsets */
|
||||
test_select_bounds();
|
||||
|
Loading…
Reference in New Issue
Block a user