summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2005-06-18 05:10:22 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2005-06-18 05:10:22 (GMT)
commitd6410304369bea0644da9ab594f22af6201fa16e (patch)
treedbbc72537715fa4c4fb53e153970735dc3003a66 /src
parent04e424638ad15f4663f77468f70ec58b7ac8df22 (diff)
downloadhdf5-d6410304369bea0644da9ab594f22af6201fa16e.zip
hdf5-d6410304369bea0644da9ab594f22af6201fa16e.tar.gz
hdf5-d6410304369bea0644da9ab594f22af6201fa16e.tar.bz2
[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
Diffstat (limited to 'src')
-rw-r--r--src/H5Dio.c22
-rw-r--r--src/H5Shyper.c78
-rw-r--r--src/H5Sprivate.h3
3 files changed, 81 insertions, 22 deletions
diff --git a/src/H5Dio.c b/src/H5Dio.c
index b5259a3..f1d12f8 100644
--- a/src/H5Dio.c
+++ b/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);
diff --git a/src/H5Shyper.c b/src/H5Shyper.c
index 6f8c1d1..b9f22fb 100644
--- a/src/H5Shyper.c
+++ b/src/H5Shyper.c
@@ -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,17 +4132,18 @@ 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:
@@ -4151,6 +4153,52 @@ done:
/*--------------------------------------------------------------------------
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
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 06c9f02..ac6a297 100644
--- a/src/H5Sprivate.h
+++ b/src/H5Sprivate.h
@@ -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);