summaryrefslogtreecommitdiffstats
path: root/src/H5Shyper.c
diff options
context:
space:
mode:
authorAllen Byrne <byrn@hdfgroup.org>2019-06-18 17:12:24 (GMT)
committerAllen Byrne <byrn@hdfgroup.org>2019-06-18 17:12:24 (GMT)
commitd118a47a921fb8c545805dbd9ceea93bb487d9b6 (patch)
tree8749afede87172160e616346992c1607e26a26ca /src/H5Shyper.c
parente7f16c6f2c7b031d7e9b4ba22a9fcdad4d258360 (diff)
parent712a2a13d8add828d053135a172abb2e819d59ad (diff)
downloadhdf5-d118a47a921fb8c545805dbd9ceea93bb487d9b6.zip
hdf5-d118a47a921fb8c545805dbd9ceea93bb487d9b6.tar.gz
hdf5-d118a47a921fb8c545805dbd9ceea93bb487d9b6.tar.bz2
Merging in latest from upstream (HDFFV/hdf5:refs/heads/develop)
* commit '712a2a13d8add828d053135a172abb2e819d59ad': Fixed a warning in H5CX.c concerning incorrect use of freeing VOL connector info. Add H5S_SEL_ITER_SHARE_WITH_DATASPACE selection iterator creation flag, to share dataspace's selection with iterator (and with caution about not modifying or closing the dataspace while the iterator is open). Fix misc. typos, etc. from code review New hyperslab selection routines and new public selection iterator routines.
Diffstat (limited to 'src/H5Shyper.c')
-rw-r--r--src/H5Shyper.c316
1 files changed, 311 insertions, 5 deletions
diff --git a/src/H5Shyper.c b/src/H5Shyper.c
index 63f457b..6df368d 100644
--- a/src/H5Shyper.c
+++ b/src/H5Shyper.c
@@ -726,10 +726,27 @@ H5S__hyper_iter_init(const H5S_t *space, H5S_sel_iter_t *iter)
else { /* Initialize the information needed for non-regular hyperslab I/O */
H5S_hyper_span_info_t *spans; /* Pointer to hyperslab span info node */
- /* Share the source dataspace's span tree by incrementing the reference count on it */
- HDassert(space->select.sel_info.hslab->span_lst);
- iter->u.hyp.spans = space->select.sel_info.hslab->span_lst;
- iter->u.hyp.spans->count++;
+ /* If this iterator is created from an API call, by default we clone the
+ * selection now, as the dataspace could be modified or go out of scope.
+ *
+ * However, if the H5S_SEL_ITER_SHARE_WITH_DATASPACE flag is given,
+ * the selection is shared between the selection iterator and the
+ * dataspace. In this case, the application _must_not_ modify or
+ * close the dataspace that the iterator is operating on, or undefined
+ * behavior will occur.
+ */
+ if((iter->flags & H5S_SEL_ITER_API_CALL) &&
+ !(iter->flags & H5S_SEL_ITER_SHARE_WITH_DATASPACE)) {
+ /* Copy the span tree */
+ if(NULL == (iter->u.hyp.spans = H5S__hyper_copy_span(space->select.sel_info.hslab->span_lst, space->extent.rank)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy span tree")
+ } /* end if */
+ else {
+ /* Share the source dataspace's span tree by incrementing the reference count on it */
+ HDassert(space->select.sel_info.hslab->span_lst);
+ iter->u.hyp.spans = space->select.sel_info.hslab->span_lst;
+ iter->u.hyp.spans->count++;
+ } /* end else */
/* Initialize the starting span_info's and spans */
spans = iter->u.hyp.spans;
@@ -3431,7 +3448,7 @@ H5S__get_select_hyper_nblocks(const H5S_t *space, hbool_t app_ref)
/* Check each dimension */
for(ret_value = 1, u = 0; u < space->extent.rank; u++)
ret_value *= (app_ref ? space->select.sel_info.hslab->diminfo.app[u].count :
- space->select.sel_info.hslab->diminfo.opt[u].count);
+ space->select.sel_info.hslab->diminfo.opt[u].count);
} /* end if */
else
ret_value = H5S__hyper_span_nblocks(space->select.sel_info.hslab->span_lst);
@@ -10408,6 +10425,213 @@ done:
} /* end H5S__fill_in_select() */
+/*--------------------------------------------------------------------------
+ NAME
+ H5Scombine_hyperslab
+ PURPOSE
+ Specify a hyperslab to combine with the current hyperslab selection and
+ return a new dataspace with the combined selection as the selection in the
+ new dataspace.
+ USAGE
+ hid_t H5Scombine_hyperslab(dsid, op, start, stride, count, block)
+ hid_t dsid; IN: Dataspace ID of selection to use
+ H5S_seloper_t op; IN: Operation to perform on current selection
+ const hsize_t *start; IN: Offset of start of hyperslab
+ const hsize_t *stride; IN: Hyperslab stride
+ const hsize_t *count; IN: Number of blocks included in hyperslab
+ const hsize_t *block; IN: Size of block in hyperslab
+ RETURNS
+ Dataspace ID on success / H5I_INVALID_HID on failure
+ DESCRIPTION
+ Combines a hyperslab selection with the current selection for a dataspace,
+ creating a new dataspace to return the generated selection.
+ If the current selection is not a hyperslab, it is freed and the hyperslab
+ parameters passed in are combined with the H5S_SEL_ALL hyperslab (ie. a
+ selection composing the entire current extent). If STRIDE or BLOCK is
+ NULL, they are assumed to be set to all '1'.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+hid_t
+H5Scombine_hyperslab(hid_t space_id, H5S_seloper_t op, const hsize_t start[],
+ const hsize_t stride[], const hsize_t count[], const hsize_t block[])
+{
+ H5S_t *space; /* Dataspace to modify selection of */
+ H5S_t *new_space = NULL; /* New dataspace created */
+ hid_t ret_value; /* Return value */
+
+ FUNC_ENTER_API(H5I_INVALID_HID)
+ H5TRACE6("i", "iSs*h*h*h*h", space_id, op, start, stride, count, block);
+
+ /* Check args */
+ if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a dataspace")
+ if(start == NULL || count == NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "hyperslab not specified")
+ if(!(op >= H5S_SELECT_SET && op <= H5S_SELECT_NOTA))
+ HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, H5I_INVALID_HID, "invalid selection operation")
+
+ /* Generate new space, with combination of selections */
+ if(H5S_combine_hyperslab(space, op, start, stride, count, block, &new_space) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, H5I_INVALID_HID, "unable to set hyperslab selection")
+
+ /* Atomize */
+ if((ret_value = H5I_register(H5I_DATASPACE, new_space, TRUE)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register dataspace atom")
+
+done:
+ if(ret_value < 0 && new_space)
+ H5S_close(new_space);
+
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Scombine_hyperslab() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5S__combine_select
+ *
+ * Purpose: Internal version of H5Scombine_select().
+ *
+ * Return: New dataspace on success/NULL on failure
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, October 30, 2001
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5S_t *
+H5S__combine_select(H5S_t *space1, H5S_seloper_t op, H5S_t *space2)
+{
+ H5S_t *new_space = NULL; /* New dataspace generated */
+ H5S_t *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check args */
+ HDassert(space1);
+ HDassert(space2);
+ HDassert(op >= H5S_SELECT_OR && op <= H5S_SELECT_NOTA);
+
+ /* Check if space1 selections has span trees */
+ if(NULL == space1->select.sel_info.hslab->span_lst)
+ if(H5S__hyper_generate_spans(space1) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, NULL, "dataspace does not have span tree")
+
+ if(NULL == space2->select.sel_info.hslab->span_lst) {
+ hsize_t tmp_start[H5S_MAX_RANK];
+ hsize_t tmp_stride[H5S_MAX_RANK];
+ hsize_t tmp_count[H5S_MAX_RANK];
+ hsize_t tmp_block[H5S_MAX_RANK];
+ unsigned u;
+
+ for(u = 0; u < space2->extent.rank; u++) {
+ tmp_start[u] = space2->select.sel_info.hslab->diminfo.opt[u].start;
+ tmp_stride[u] = space2->select.sel_info.hslab->diminfo.opt[u].stride;
+ tmp_count[u] = space2->select.sel_info.hslab->diminfo.opt[u].count;
+ tmp_block[u] = space2->select.sel_info.hslab->diminfo.opt[u].block;
+ } /* end for */
+
+ /* Combine hyperslab selection with regular selection directly */
+ if(H5S_combine_hyperslab(space1, op, tmp_start, tmp_stride, tmp_count, tmp_block, &new_space) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, NULL, "unable to set hyperslab selection")
+ } /* end if */
+ else{
+ /* Combine new_space (a copy of space 1) & space2, with the result in new_space */
+ if(H5S__fill_in_select(space1, op, space2, &new_space) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, NULL, "can't clip hyperslab information")
+ } /* end else */
+
+ /* Set unlim_dim */
+ new_space->select.sel_info.hslab->unlim_dim = -1;
+
+ /* Set return value */
+ ret_value = new_space;
+
+done:
+ if(ret_value == NULL && new_space)
+ H5S_close(new_space);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S__combine_select() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Scombine_select
+ PURPOSE
+ Combine two hyperslab selections with an operation, returning a dataspace
+ with the resulting selection.
+ USAGE
+ hid_t H5Scombine_select(space1, op, space2)
+ hid_t space1; IN: First Dataspace ID
+ H5S_seloper_t op; IN: Selection operation
+ hid_t space2; IN: Second Dataspace ID
+ RETURNS
+ Dataspace ID on success / H5I_INVALID_HID on failure
+ DESCRIPTION
+ Combine two existing hyperslab selections with an operation, returning
+ a new dataspace with the resulting selection. The dataspace extent from
+ space1 is copied for the dataspace extent of the newly created dataspace.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+hid_t
+H5Scombine_select(hid_t space1_id, H5S_seloper_t op, hid_t space2_id)
+{
+ H5S_t *space1; /* First Dataspace */
+ H5S_t *space2; /* Second Dataspace */
+ H5S_t *new_space = NULL; /* New Dataspace */
+ hid_t ret_value; /* Return value */
+
+ FUNC_ENTER_API(H5I_INVALID_HID)
+ H5TRACE3("i", "iSsi", space1_id, op, space2_id);
+
+ /* Check args */
+ if(NULL == (space1 = (H5S_t *)H5I_object_verify(space1_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a dataspace")
+ if(NULL == (space2 = (H5S_t *)H5I_object_verify(space2_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a dataspace")
+ if(!(op >= H5S_SELECT_OR && op <= H5S_SELECT_NOTA))
+ HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, H5I_INVALID_HID, "invalid selection operation")
+
+ /* Check that both dataspaces have the same rank */
+ if(space1->extent.rank != space2->extent.rank)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "dataspaces not same rank")
+
+ /* Note: currently, the offset of each dataspace is ignored */
+#if 0
+ /* Check that both dataspaces have the same offset */
+ /* Same note as in H5Smodify_select */
+ for(u=0; u<space1->extent.rank; u++) {
+ if(space1->select.offset[u] != space2->select.offset[u])
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "dataspaces not same offset")
+ } /* end for */
+#endif
+
+ /* Check that both dataspaces have hyperslab selections */
+ if(H5S_GET_SELECT_TYPE(space1) != H5S_SEL_HYPERSLABS || H5S_GET_SELECT_TYPE(space2) != H5S_SEL_HYPERSLABS)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "dataspaces don't have hyperslab selections")
+
+ /* Go combine the dataspaces */
+ if(NULL == (new_space = H5S__combine_select(space1, op, space2)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, H5I_INVALID_HID, "unable to create hyperslab selection")
+
+ /* Atomize */
+ if((ret_value = H5I_register(H5I_DATASPACE, new_space, TRUE)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register dataspace atom")
+
+done:
+ if(ret_value < 0 && new_space)
+ H5S_close(new_space);
+
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Scombine_select() */
+
+
/*-------------------------------------------------------------------------
* Function: H5S__modify_select
*
@@ -10470,6 +10694,88 @@ done:
/*--------------------------------------------------------------------------
NAME
+ H5Smodify_select
+ PURPOSE
+ Refine a hyperslab selection with an operation using a second hyperslab
+ to modify it
+ USAGE
+ herr_t H5Smodify_select(space1, op, space2)
+ hid_t space1; IN/OUT: First Dataspace ID
+ H5S_seloper_t op; IN: Selection operation
+ hid_t space2; IN: Second Dataspace ID
+ RETURNS
+ Non-negative on success/Negative on failure
+ DESCRIPTION
+ Refine an existing hyperslab selection with an operation, using a second
+ hyperslab. The first selection is modified to contain the result of
+ space1 operated on by space2.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5Smodify_select(hid_t space1_id, H5S_seloper_t op, hid_t space2_id)
+{
+ H5S_t *space1; /* First Dataspace */
+ H5S_t *space2; /* Second Dataspace */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE3("e", "iSsi", space1_id, op, space2_id);
+
+ /* Check args */
+ if(NULL == (space1 = (H5S_t *)H5I_object_verify(space1_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
+ if(NULL == (space2 = (H5S_t *)H5I_object_verify(space2_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
+ if(!(op >= H5S_SELECT_OR && op <= H5S_SELECT_NOTA))
+ HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation")
+
+ /* Check that both dataspaces have the same rank */
+ if(space1->extent.rank != space2->extent.rank)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dataspaces not same rank")
+
+ /* Check that both dataspaces have the same offset */
+ /** Note that this is a tricky part of this function. It's
+ * possible that two dataspaces have different "offset". If the
+ * space2 has smaller offset value than that of space1 in a
+ * dimension, then the span elements of this dimension in
+ * space2 could have negative "low" and "high" values relative
+ * to the offset in space1. In other words, if the bounds of
+ * span elements in space2 are adjusted relative to the offset
+ * in space1, then every span element's bound is computed as
+ * "origin_bound+offset2-offset1". Therefore, if offset2 (the
+ * offset of space2) is smaller, then
+ * "origin_bound+offset2-offset1" could be negative which is
+ * not allowed by the bound type declaration as hsize_t!
+ * As a result, if the op is an OR selection, then the final
+ * result may contain span elements that have negative bound!
+ * So right now, the difference in the offset is totally
+ * ignored!!
+ */
+#if 0
+ for(u=0; u<space1->extent.rank; u++) {
+ if(space1->select.offset[u] != space2->select.offset[u])
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dataspaces not same offset")
+ } /* end for */
+#endif
+
+ /* Check that both dataspaces have hyperslab selections */
+ if(H5S_GET_SELECT_TYPE(space1) != H5S_SEL_HYPERSLABS || H5S_GET_SELECT_TYPE(space2) != H5S_SEL_HYPERSLABS)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dataspaces don't have hyperslab selections")
+
+ /* Go refine the first selection */
+ if(H5S__modify_select(space1, op, space2) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to modify hyperslab selection")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Smodify_select() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
H5S__hyper_proj_int_build_proj
PURPOSE
Secondary iteration routine for H5S__hyper_project_intersection