From 98f947ceaedbae472efbebad505680d2ca62b403 Mon Sep 17 00:00:00 2001 From: Neil Fortner Date: Fri, 7 Aug 2015 11:15:39 -0500 Subject: [svn-r27479] Add checking for invalid inputs to H5Dset_virtual: point selections, incorrect numbers of elements selected, incorrect "slice" through limited dimensions, incorrect number of printf substitutions. Patch source selection space extent with bounds of selection if extent is unknown before returning via H5Pget_virtual_srcspace. Write updated VDS dataspace to file when it changes due to unlimited selections. Other minor fixes/cleanup. Tested: ummon --- src/H5Dvirtual.c | 44 ++++++++++++------- src/H5Pdcpl.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++++------- src/H5S.c | 12 +++--- src/H5Sall.c | 1 + src/H5Shyper.c | 45 +++++++++++++++++++ src/H5Snone.c | 1 + src/H5Spkg.h | 6 ++- src/H5Spoint.c | 1 + src/H5Sprivate.h | 4 ++ src/H5Sselect.c | 53 +++++++++++++++++++++-- test/vds.c | 53 +++++++++++++++++++++++ 11 files changed, 306 insertions(+), 42 deletions(-) diff --git a/src/H5Dvirtual.c b/src/H5Dvirtual.c index 09519bf..db45ceb 100644 --- a/src/H5Dvirtual.c +++ b/src/H5Dvirtual.c @@ -574,7 +574,7 @@ H5D__virtual_open_source_dset(const H5D_t *vdset, if(HDstrcmp(source_dset->file_name, ".")) { /* Open the source file */ if(NULL == (src_file = H5F_open(source_dset->file_name, H5F_INTENT(vdset->oloc.file) & H5F_ACC_RDWR, H5P_FILE_CREATE_DEFAULT, vdset->shared->layout.storage.u.virt.source_fapl, dxpl_id))) - H5E_clear_stack(NULL); //Quick hack until proper support for H5Fopen with missing file is implemented VDSINC HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENFILE, FAIL, "unable to open source file") + H5E_clear_stack(NULL); /* Quick hack until proper support for H5Fopen with missing file is implemented */ else src_file_open = TRUE; } /* end if */ @@ -591,7 +591,7 @@ H5D__virtual_open_source_dset(const H5D_t *vdset, /* Open the source dataset */ if(NULL == (source_dset->dset = H5D__open_name(&src_root_loc, source_dset->dset_name, vdset->shared->layout.storage.u.virt.source_dapl, dxpl_id))) - H5E_clear_stack(NULL); //Quick hack until proper support for H5Fopen with missing file is implemented VDSINC HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "unable to open dataset") + H5E_clear_stack(NULL); /* Quick hack until proper support for H5Dopen with missing file is implemented */ else /* Patch the source selection if necessary */ if(virtual_ent->source_space_status != H5O_VIRTUAL_STATUS_CORRECT) { @@ -1352,13 +1352,21 @@ H5D__virtual_set_extent_unlim(const H5D_t *dset, hid_t dxpl_id) changed = TRUE; } /* end for */ - /* If we did not change the VDS dimensions, there is nothing more to update - */ - if(changed || (!storage->init && (storage->view == H5D_VDS_FIRST_MISSING))) { + /* Update extent if it changed */ + if(changed) { /* Update VDS extent */ if(H5S_set_extent(dset->shared->space, new_dims) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to modify size of data space") + /* Mark the space as dirty, for later writing to the file */ + if(H5F_INTENT(dset->oloc.file) & H5F_ACC_RDWR) + if(H5D__mark(dset, dxpl_id, H5D_MARK_SPACE) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to mark dataspace as dirty") + } /* end if */ + + /* If we did not change the VDS dimensions, there is nothing more to update + */ + if(changed || (!storage->init && (storage->view == H5D_VDS_FIRST_MISSING))) { /* Iterate over mappings again to update source selections and virtual * mapping extents */ for(i = 0; i < storage->list_nalloc; i++) { @@ -1516,7 +1524,6 @@ H5D__virtual_set_extent_unlim(const H5D_t *dset, hid_t dxpl_id) } /* end for */ } /* end if */ - /* Call H5D__mark so dataspace is updated on disk? VDSINC */ /* Mark layout as fully initialized */ storage->init = TRUE; @@ -1555,14 +1562,16 @@ H5D__virtual_init(H5F_t *f, hid_t H5_ATTR_UNUSED dxpl_id, const H5D_t *dset, storage = &dset->shared->layout.storage.u.virt; HDassert(storage->list || (storage->list_nused == 0)); - /* Patch the virtual selection dataspaces */ + /* Patch the virtual selection dataspaces. Note we always patch the space + * status because this layout could be from an old version held in the + * object header message code. We cannot update that held message because + * the layout message is constant, so just overwrite the values here (and + * invalidate other fields by setting storage->init to FALSE below). */ for(i = 0; i < storage->list_nused; i++) { - if(storage->list[i].virtual_space_status != H5O_VIRTUAL_STATUS_CORRECT) { - if(H5S_extent_copy(storage->list[i].source_dset.virtual_select, dset->shared->space) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "can't copy virtual dataspace extent") - storage->list[i].virtual_space_status = H5O_VIRTUAL_STATUS_CORRECT; - HDassert(storage->list[i].sub_dset_nalloc == 0); - } /* end if */ + if(H5S_extent_copy(storage->list[i].source_dset.virtual_select, dset->shared->space) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "can't copy virtual dataspace extent") + storage->list[i].virtual_space_status = H5O_VIRTUAL_STATUS_CORRECT; + HDassert(storage->list[i].sub_dset_nalloc == 0); } /* end for */ /* Get dataset access property list */ @@ -1589,6 +1598,10 @@ H5D__virtual_init(H5F_t *f, hid_t H5_ATTR_UNUSED dxpl_id, const H5D_t *dset, if((storage->source_dapl = H5P_copy_plist(dapl, FALSE)) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "can't copy dapl") + /* Mark layout as not fully initialized (must be done prior to I/O for + * unlimited/printf selections) */ + storage->init = FALSE; + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5D__virtual_init() */ @@ -2069,8 +2082,9 @@ H5D__virtual_write_one(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, HDassert(source_dset->dset); HDassert(source_dset->clipped_source_select); - /* Extend source dataset if necessary and there is an unlimited - * dimension VDSINC */ + /* In the future we may wish to extent this implementation to extend + * source datasets if a write to a virtual dataset goes past the current + * extent in the unlimited dimension. -NAF */ /* Project intersection of file space and mapping virtual space onto * mapping source space */ if(H5S_select_project_intersection(source_dset->virtual_select, source_dset->clipped_source_select, file_space, &projected_src_space) < 0) diff --git a/src/H5Pdcpl.c b/src/H5Pdcpl.c index f687104..0c6184b 100644 --- a/src/H5Pdcpl.c +++ b/src/H5Pdcpl.c @@ -1805,7 +1805,10 @@ H5Pset_virtual(hid_t dcpl_id, hid_t vspace_id, const char *src_file_name, H5O_layout_t layout; /* Layout information for setting chunk info */ H5S_t *vspace; /* Virtual dataset space selection */ H5S_t *src_space; /* Source dataset space selection */ - hssize_t nelmts; /* Number of elements */ + H5S_sel_type select_type; /* Selection type */ + hsize_t nelmts_vs; /* Number of elements in virtual selection */ + hsize_t nelmts_ss; /* Number of elements in source selection */ + H5S_t *tmp_space = NULL; /* Temporary dataspace */ hbool_t new_layout = FALSE; /* Whether we are adding a new virtual layout message to plist */ H5O_storage_virtual_ent_t *ent = NULL; /* Convenience pointer to new VDS entry */ hbool_t adding_entry = FALSE; /* Whether we are in the middle of adding an entry */ @@ -1825,14 +1828,43 @@ H5Pset_virtual(hid_t dcpl_id, hid_t vspace_id, const char *src_file_name, HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace") if(NULL == (src_space = (H5S_t *)H5I_object_verify(src_space_id, H5I_DATASPACE))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace") - nelmts = H5S_GET_SELECT_NPOINTS(vspace); - if((nelmts != H5S_UNLIMITED) - && (nelmts != H5S_GET_SELECT_NPOINTS(src_space))) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "virtual and source space selections have different numbers of elements") - /* Check for unlimited selections having the same number of elements in the - * non-unlimited dimensions, and check for printf selections having the - * correct numbers of elements and unlimited/non-unlimited dimensions VDSINC - */ + + /* Check for point selections (currently unsupported) */ + if(H5S_SEL_ERROR == (select_type = H5S_GET_SELECT_TYPE(vspace))) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get selection type") + if(select_type == H5S_SEL_POINTS) + HGOTO_ERROR(H5E_PLIST, H5E_UNSUPPORTED, FAIL, "point selections not currently supported with virtual datasets") + if(H5S_SEL_ERROR == (select_type = H5S_GET_SELECT_TYPE(src_space))) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get selection type") + if(select_type == H5S_SEL_POINTS) + HGOTO_ERROR(H5E_PLIST, H5E_UNSUPPORTED, FAIL, "point selections not currently supported with virtual datasets") + + /* Get number of elements in spaces */ + nelmts_vs = (hsize_t)H5S_GET_SELECT_NPOINTS(vspace); + nelmts_ss = (hsize_t)H5S_GET_SELECT_NPOINTS(src_space); + + /* Check for unlimited vspace */ + if(nelmts_vs == H5S_UNLIMITED) { + /* Check for unlimited src_space */ + if(nelmts_ss == H5S_UNLIMITED) { + hsize_t nenu_vs; /* Number of elements in the non-unlimited dimensions of vspace */ + hsize_t nenu_ss; /* Number of elements in the non-unlimited dimensions of src_space */ + + /* Non-printf unlimited selection. Make sure both selections have + * the same number of elements in the non-unlimited dimension */ + if(H5S_get_select_num_elem_non_unlim(vspace, &nenu_vs) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTCOUNT, FAIL, "can't get number of elements in non-unlimited dimension") + if(H5S_get_select_num_elem_non_unlim(src_space, &nenu_ss) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTCOUNT, FAIL, "can't get number of elements in non-unlimited dimension") + if(nenu_vs != nenu_ss) + HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "numbers of elemnts in the non-unlimited dimensions is different for source and virtual spaces") + } /* end if */ + /* We will handle the printf case after parsing the source names */ + } /* end if */ + else + /* Limited selections. Check number of points is the same. */ + if(nelmts_vs != nelmts_ss) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "virtual and source space selections have different numbers of elements") #ifndef H5_HAVE_C99_DESIGNATED_INITIALIZER /* If the compiler doesn't support C99 designated initializers, check if @@ -1913,7 +1945,6 @@ H5Pset_virtual(hid_t dcpl_id, hid_t vspace_id, const char *src_file_name, ent->source_dset.clipped_source_select = ent->source_select; ent->source_dset.clipped_virtual_select = ent->source_dset.virtual_select; } /* end if */ - ent->unlim_extent_source = HSIZE_UNDEF; ent->unlim_extent_virtual = HSIZE_UNDEF; ent->clip_size_source = HSIZE_UNDEF; @@ -1921,6 +1952,38 @@ H5Pset_virtual(hid_t dcpl_id, hid_t vspace_id, const char *src_file_name, ent->source_space_status = H5O_VIRTUAL_STATUS_USER; ent->virtual_space_status = H5O_VIRTUAL_STATUS_USER; + /* Check for printf selection */ + if((nelmts_vs == H5S_UNLIMITED) && (nelmts_ss != H5S_UNLIMITED)) { + /* Make sure there at least one %b substitution in the source file or + * dataset name */ + if((ent->psfn_nsubs == 0) && (ent->psdn_nsubs == 0)) + HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "unlimited virtual selection, limited source selection, and no printf specifiers in source names") + + /* Make sure virtual space uses hyperslab selection */ + if(H5S_GET_SELECT_TYPE(vspace) != H5S_SEL_HYPERSLABS) + HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "virtual selection with printf mapping must be hyperslab") + + /* Get first block in virtual selection */ + if(NULL == (tmp_space = H5S_hyper_get_unlim_block(vspace, (hsize_t)0))) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get first block in virtual selection") + + /* Check that the number of elements in one block in the virtual + * selection matches the total number of elements in the source + * selection */ + nelmts_vs = (hsize_t)H5S_GET_SELECT_NPOINTS(tmp_space); + if(nelmts_vs != nelmts_ss) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "virtual (single block) and source space selections have different numbers of elements") + + /* Close tmp_space */ + if(H5S_close(tmp_space) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CLOSEERROR, FAIL, "can't close dataspace") + tmp_space = NULL; + } /* end if */ + else + /* Make sure there are no printf substitutions */ + if((ent->psfn_nsubs > 0) || (ent->psdn_nsubs > 0)) + HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "printf specifier(s) in source name(s) without an unlimited virtual selection and limited source selection") + /* Update min_dims */ if(H5D_virtual_update_min_dims(&layout, layout.storage.u.virt.list_nused) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "unable to update virtual dataset minimum dimensions") @@ -1972,6 +2035,11 @@ done: /* Free list if necessary */ if(free_list) layout.storage.u.virt.list = (H5O_storage_virtual_ent_t *)H5MM_xfree(layout.storage.u.virt.list); + + /* Free temporary space */ + if(tmp_space) + if(H5S_close(tmp_space) < 0) + HDONE_ERROR(H5E_PLIST, H5E_CLOSEERROR, FAIL, "can't close dataspace") } /* end if */ } /* end if */ @@ -2108,14 +2176,44 @@ H5Pget_virtual_srcspace(hid_t dcpl_id, size_t index) if(H5D_VIRTUAL != layout.type) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a virtual storage layout") - /* Attempt to open source dataset and patch extent if extent status is not - * H5O_VIRTUAL_STATUS_CORRECT, otherwise if status is - * H5O_VIRTUAL_STATUS_INVALID, patch with bounds of selection VDSINC */ - - /* Get the source space */ + /* Check index */ if(index >= layout.storage.u.virt.list_nused) HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid index (out of range)") HDassert(layout.storage.u.virt.list_nused <= layout.storage.u.virt.list_nalloc); + + /* Attempt to open source dataset and patch extent if extent status is not + * H5O_VIRTUAL_STATUS_CORRECT? -NAF */ + /* If source space status is H5O_VIRTUAL_STATUS_INVALID, patch with bounds + * of selection */ + if((layout.storage.u.virt.list[index].source_space_status + == H5O_VIRTUAL_STATUS_INVALID) + && (layout.storage.u.virt.list[index].unlim_dim_source < 0)) { + hsize_t bounds_start[H5S_MAX_RANK]; + hsize_t bounds_end[H5S_MAX_RANK]; + int rank; + int i; + + /* Get rank of source space */ + if((rank = H5S_GET_EXTENT_NDIMS(layout.storage.u.virt.list[index].source_select)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get source space rank") + + /* Get bounds of selection */ + if(H5S_SELECT_BOUNDS(layout.storage.u.virt.list[index].source_select, bounds_start, bounds_end) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get selection bounds") + + /* Adjust bounds to extent */ + for(i = 0; i < rank; i++) + bounds_end[i]++; + + /* Set extent */ + if(H5S_set_extent_simple(layout.storage.u.virt.list[index].source_select, (unsigned)rank, bounds_end, NULL) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set source space extent") + + /* Update source space status */ + layout.storage.u.virt.list[index].source_space_status = H5O_VIRTUAL_STATUS_SEL_BOUNDS; + } /* end if */ + + /* Get the source space */ if(NULL == (space = H5S_copy(layout.storage.u.virt.list[index].source_select, FALSE, TRUE))) HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "unable to copy source selection") diff --git a/src/H5S.c b/src/H5S.c index 6a6f45a..d8ab37c 100644 --- a/src/H5S.c +++ b/src/H5S.c @@ -1268,7 +1268,7 @@ H5Sset_extent_simple(hid_t space_id, int rank, const hsize_t dims[/*rank*/], } /* Do it */ - if (H5S__set_extent_simple(space, (unsigned)rank, dims, max)<0) + if (H5S_set_extent_simple(space, (unsigned)rank, dims, max)<0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to set simple extent") done: @@ -1277,7 +1277,7 @@ done: /*------------------------------------------------------------------------- - * Function: H5S__set_extent_simple + * Function: H5S_set_extent_simple * * Purpose: This is where the real work happens for * H5Sset_extent_simple(). @@ -1292,13 +1292,13 @@ done: *------------------------------------------------------------------------- */ herr_t -H5S__set_extent_simple(H5S_t *space, unsigned rank, const hsize_t *dims, +H5S_set_extent_simple(H5S_t *space, unsigned rank, const hsize_t *dims, const hsize_t *max) { unsigned u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_PACKAGE + FUNC_ENTER_NOAPI(FAIL) /* Check args */ HDassert(rank <= H5S_MAX_RANK); @@ -1354,7 +1354,7 @@ H5S__set_extent_simple(H5S_t *space, unsigned rank, const hsize_t *dims, done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5S__set_extent_simple() */ +} /* H5S_set_extent_simple() */ /*------------------------------------------------------------------------- @@ -1465,7 +1465,7 @@ H5S_create_simple(unsigned rank, const hsize_t dims[/*rank*/], /* Create the space and set the extent */ if(NULL==(ret_value=H5S_create(H5S_SIMPLE))) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, NULL, "can't create simple dataspace") - if(H5S__set_extent_simple(ret_value,rank,dims,maxdims)<0) + if(H5S_set_extent_simple(ret_value,rank,dims,maxdims)<0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, NULL, "can't set dimensions") done: diff --git a/src/H5Sall.c b/src/H5Sall.c index 1b9ceec..7e33980 100644 --- a/src/H5Sall.c +++ b/src/H5Sall.c @@ -78,6 +78,7 @@ const H5S_select_class_t H5S_sel_all[1] = {{ H5S_all_bounds, H5S_all_offset, H5S_all_unlim_dim, + NULL, H5S_all_is_contiguous, H5S_all_is_single, H5S_all_is_regular, diff --git a/src/H5Shyper.c b/src/H5Shyper.c index 8736b69..898c3df 100644 --- a/src/H5Shyper.c +++ b/src/H5Shyper.c @@ -65,6 +65,8 @@ static herr_t H5S_hyper_deserialize(const H5F_t *f, H5S_t *space, static herr_t H5S_hyper_bounds(const H5S_t *space, hsize_t *start, hsize_t *end); static herr_t H5S_hyper_offset(const H5S_t *space, hsize_t *offset); static int H5S_hyper_unlim_dim(const H5S_t *space); +static herr_t H5S_hyper_num_elem_non_unlim(const H5S_t *space, + hsize_t *num_elem_non_unlim); static htri_t H5S_hyper_is_contiguous(const H5S_t *space); static htri_t H5S_hyper_is_single(const H5S_t *space); static htri_t H5S_hyper_is_regular(const H5S_t *space); @@ -102,6 +104,7 @@ const H5S_select_class_t H5S_sel_hyper[1] = {{ H5S_hyper_bounds, H5S_hyper_offset, H5S_hyper_unlim_dim, + H5S_hyper_num_elem_non_unlim, H5S_hyper_is_contiguous, H5S_hyper_is_single, H5S_hyper_is_regular, @@ -3007,6 +3010,48 @@ H5S_hyper_unlim_dim(const H5S_t *space) /*-------------------------------------------------------------------------- NAME + H5S_hyper_num_elem_non_unlim + PURPOSE + Return number of elements in the non-unlimited dimensions + USAGE + herr_t H5S_hyper_num_elem_non_unlim(space,num_elem_non_unlim) + H5S_t *space; IN: Dataspace pointer to check + hsize_t *num_elem_non_unlim; OUT: Number of elements in the non-unlimited dimensions + RETURNS + Non-negative on success/Negative on failure + DESCRIPTION + Returns the number of elements in a slice through the non-unlimited + dimensions of the selection. Fails if the selection has no unlimited + dimension. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static herr_t +H5S_hyper_num_elem_non_unlim(const H5S_t *space, hsize_t *num_elem_non_unlim) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity check */ + HDassert(space); + HDassert(num_elem_non_unlim); + + /* Get number of elements in the non-unlimited dimensions */ + if(space->select.sel_info.hslab->unlim_dim >= 0) + *num_elem_non_unlim = space->select.sel_info.hslab->num_elem_non_unlim; + else + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "selection has no unlimited dimension") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5S_hyper_num_elem_non_unlim() */ + + +/*-------------------------------------------------------------------------- + NAME H5S_hyper_is_contiguous PURPOSE Check if a hyperslab selection is contiguous within the dataspace extent. diff --git a/src/H5Snone.c b/src/H5Snone.c index b4e2f0e..23433a1 100644 --- a/src/H5Snone.c +++ b/src/H5Snone.c @@ -79,6 +79,7 @@ const H5S_select_class_t H5S_sel_none[1] = {{ H5S_none_bounds, H5S_none_offset, H5S_none_unlim_dim, + NULL, H5S_none_is_contiguous, H5S_none_is_single, H5S_none_is_regular, diff --git a/src/H5Spkg.h b/src/H5Spkg.h index 7805777..f719201 100644 --- a/src/H5Spkg.h +++ b/src/H5Spkg.h @@ -154,6 +154,9 @@ typedef herr_t (*H5S_sel_bounds_func_t)(const H5S_t *space, hsize_t *start, hsiz typedef herr_t (*H5S_sel_offset_func_t)(const H5S_t *space, hsize_t *offset); /* Method to get unlimited dimension of selection (or -1 for none) */ typedef int (*H5S_sel_unlim_dim_func_t)(const H5S_t *space); +/* Method to get the number of elements in a slice through the unlimited dimension */ +typedef herr_t (*H5S_sel_num_elem_non_unlim_func_t)(const H5S_t *space, + hsize_t *num_elem_non_unlim); /* Method to determine if current selection is contiguous */ typedef htri_t (*H5S_sel_is_contiguous_func_t)(const H5S_t *space); /* Method to determine if current selection is a single block */ @@ -184,6 +187,7 @@ typedef struct { H5S_sel_bounds_func_t bounds; /* Method to determine to smallest n-D bounding box containing the current selection */ H5S_sel_offset_func_t offset; /* Method to determine linear offset of initial element in selection within dataspace */ H5S_sel_unlim_dim_func_t unlim_dim; /* Method to get unlimited dimension of selection (or -1 for none) */ + H5S_sel_num_elem_non_unlim_func_t num_elem_non_unlim; /* Method to get the number of elements in a slice through the unlimited dimension */ H5S_sel_is_contiguous_func_t is_contiguous; /* Method to determine if current selection is contiguous */ H5S_sel_is_single_func_t is_single; /* Method to determine if current selection is a single block */ H5S_sel_is_regular_func_t is_regular; /* Method to determine if current selection is "regular" */ @@ -262,8 +266,6 @@ H5_DLLVAR const H5S_select_class_t H5S_sel_none[1]; H5_DLLVAR const H5S_select_class_t H5S_sel_point[1]; /* Extent functions */ -H5_DLL herr_t H5S__set_extent_simple(H5S_t *space, unsigned rank, - const hsize_t *dims, const hsize_t *max); H5_DLL herr_t H5S_extent_release(H5S_extent_t *extent); H5_DLL herr_t H5S_extent_copy_real(H5S_extent_t *dst, const H5S_extent_t *src, hbool_t copy_max); diff --git a/src/H5Spoint.c b/src/H5Spoint.c index 1ea4a23..d10b600 100644 --- a/src/H5Spoint.c +++ b/src/H5Spoint.c @@ -80,6 +80,7 @@ const H5S_select_class_t H5S_sel_point[1] = {{ H5S_point_bounds, H5S_point_offset, H5S_point_unlim_dim, + NULL, H5S_point_is_contiguous, H5S_point_is_single, H5S_point_is_regular, diff --git a/src/H5Sprivate.h b/src/H5Sprivate.h index 91e4513..8918a4f 100644 --- a/src/H5Sprivate.h +++ b/src/H5Sprivate.h @@ -190,6 +190,8 @@ H5_DLL herr_t H5S_append(H5F_t *f, hid_t dxpl_id, struct H5O_t *oh, H5S_t *ds); H5_DLL H5S_t *H5S_read(const struct H5O_loc_t *loc, hid_t dxpl_id); H5_DLL htri_t H5S_set_extent(H5S_t *space, const hsize_t *size); H5_DLL herr_t H5S_set_extent_real(H5S_t *space, const hsize_t *size); +H5_DLL herr_t H5S_set_extent_simple(H5S_t *space, unsigned rank, + const hsize_t *dims, const hsize_t *max); H5_DLL H5S_t *H5S_create(H5S_class_t type); H5_DLL H5S_t *H5S_create_simple(unsigned rank, const hsize_t dims[/*rank*/], const hsize_t maxdims[/*rank*/]); @@ -221,6 +223,8 @@ H5_DLL hssize_t H5S_get_select_npoints(const H5S_t *space); H5_DLL herr_t H5S_get_select_bounds(const H5S_t *space, hsize_t *start, hsize_t *end); H5_DLL herr_t H5S_get_select_offset(const H5S_t *space, hsize_t *offset); H5_DLL int H5S_get_select_unlim_dim(const H5S_t *space); +H5_DLL herr_t H5S_get_select_num_elem_non_unlim(const H5S_t *space, + hsize_t *num_elem_non_unlim); H5_DLL herr_t H5S_select_offset(H5S_t *space, const hssize_t *offset); H5_DLL herr_t H5S_select_copy(H5S_t *dst, const H5S_t *src, hbool_t share_selection); H5_DLL htri_t H5S_select_shape_same(const H5S_t *space1, const H5S_t *space2); diff --git a/src/H5Sselect.c b/src/H5Sselect.c index bb74b14..86a8c43 100644 --- a/src/H5Sselect.c +++ b/src/H5Sselect.c @@ -507,7 +507,7 @@ H5S_select_deserialize(const H5F_t *f, H5S_t **space, const uint8_t **p) /* Patch the rank of the allocated dataspace */ (void)HDmemset(dims, 0, (size_t)rank * sizeof(dims[0])); - if(H5S__set_extent_simple(tmp_space, rank, dims, NULL) < 0) + if(H5S_set_extent_simple(tmp_space, rank, dims, NULL) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't set dimensions") } /* end if */ else @@ -731,6 +731,51 @@ H5S_get_select_unlim_dim(const H5S_t *space) /*-------------------------------------------------------------------------- NAME + H5S_get_select_num_elem_non_unlim + PURPOSE + Gets the number of elements in the non-unlimited dimensions + USAGE + herr_t H5S_get_select_num_elem_non_unlim(space,num_elem_non_unlim) + H5S_t *space; IN: Dataspace pointer to check + hsize_t *num_elem_non_unlim; OUT: Number of elements in the non-unlimited dimensions + RETURNS + Non-negative on success/Negative on failure + DESCRIPTION + Returns the number of elements in a slice through the non-unlimited + dimensions of the selection. Fails if the selection has no unlimited + dimension. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5S_get_select_num_elem_non_unlim(const H5S_t *space, + hsize_t *num_elem_non_unlim) +{ + herr_t ret_value = SUCCEED; /* return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Check args */ + HDassert(space); + HDassert(num_elem_non_unlim); + + /* Check for selection callback */ + if(!space->select.type->num_elem_non_unlim) + HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "selection type has no num_elem_non_unlim callback") + + /* Make selection callback */ + if((*space->select.type->num_elem_non_unlim)(space, num_elem_non_unlim) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOUNT, FAIL, "can't get number of elements in non-unlimited dimension") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5S_get_select_unlim_dim() */ + + +/*-------------------------------------------------------------------------- + NAME H5S_select_is_contiguous PURPOSE Determines if a selection is contiguous in the dataspace @@ -2240,7 +2285,7 @@ H5S_select_project_intersection(const H5S_t *src_space, const H5S_t *dst_space, else if((src_intersect_space->select.type->type == H5S_SEL_POINTS) || (src_space->select.type->type == H5S_SEL_POINTS) || (dst_space->select.type->type == H5S_SEL_POINTS)) - HDassert(0 && "Not yet implemented...");//VDSINC + HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "point selections not currently supported") else { HDassert(src_intersect_space->select.type->type == H5S_SEL_HYPERSLABS); /* Intersecting space is hyperslab selection. Call the hyperslab @@ -2314,7 +2359,7 @@ H5S_select_subtract(H5S_t *space, H5S_t *subtract_space) /* Check for point selection in subtract_space, convert to * hyperslab */ if(subtract_space->select.type->type == H5S_SEL_POINTS) - HDassert(0 && "Not yet implemented...");//VDSINC + HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "point selections not currently supported") /* Check for point or all selection in space, convert to hyperslab */ @@ -2340,7 +2385,7 @@ H5S_select_subtract(H5S_t *space, H5S_t *subtract_space) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't convert selection") } /* end if */ else if(space->select.type->type == H5S_SEL_POINTS) - HDassert(0 && "Not yet implemented...");//VDSINC + HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "point selections not currently supported") HDassert(space->select.type->type == H5S_SEL_HYPERSLABS); HDassert(subtract_space->select.type->type == H5S_SEL_HYPERSLABS); diff --git a/test/vds.c b/test/vds.c index 04c0e5f..547f775 100644 --- a/test/vds.c +++ b/test/vds.c @@ -461,6 +461,7 @@ test_api(test_api_config_t config, hid_t fapl) hsize_t block[2]; /* Hyperslab block */ hsize_t coord[10]; /* Point selection array */ size_t size_out; + herr_t ret; unsigned i; /* Initialize vspace */ @@ -616,6 +617,7 @@ test_api(test_api_config_t config, hid_t fapl) ex_dcpl = -1; +#ifdef VDS_POINT_SELECTIONS /* VDS does not currently support point selections */ /* * Test 3: Point - point selection */ @@ -892,6 +894,57 @@ test_api(test_api_config_t config, hid_t fapl) if(H5Pclose(ex_dcpl) < 0) TEST_ERROR ex_dcpl = -1; +#else /* VDS_POINT_SELECTIONS */ + /* + * Test 3: Verify point selections fail + */ + /* Clear virtual layout in DCPL */ + if(H5Pset_layout(dcpl, H5D_VIRTUAL) < 0) + TEST_ERROR + + /* Create source dataspace */ + if((srcspace[0] = H5Screate_simple(2, dims, NULL)) < 0) + TEST_ERROR + + /* Create virtual dataspace */ + if((vspace[0] = H5Screate_simple(2, dims, NULL)) < 0) + TEST_ERROR + + /* Select points in source space */ + coord[0] = 5; + coord[1] = 15; + coord[2] = 7; + coord[3] = 19; + coord[4] = 8; + coord[5] = 0; + coord[6] = 2; + coord[7] = 14; + coord[8] = 8; + coord[9] = 18; + if(H5Sselect_elements(srcspace[0], H5S_SELECT_SET, (size_t)5, coord) < 0) + TEST_ERROR + + /* Select points in virtual space */ + coord[0] = 3; + coord[1] = 12; + coord[2] = 7; + coord[3] = 11; + coord[4] = 4; + coord[5] = 9; + coord[6] = 7; + coord[7] = 11; + coord[8] = 5; + coord[9] = 5; + if(H5Sselect_elements(vspace[0], H5S_SELECT_SET, (size_t)5, coord) < 0) + TEST_ERROR + + /* Attempt to add virtual layout mapping */ + H5E_BEGIN_TRY { + ret = H5Pset_virtual(dcpl, vspace[0], src_file[0], src_dset[0], srcspace[0]); + } H5E_END_TRY + if(ret >= 0) + TEST_ERROR +#endif /* VDS_POINT_SELECTIONS */ /* -- cgit v0.12