From a9b2e360653988b417f390e0a66d486fa775f3a2 Mon Sep 17 00:00:00 2001 From: Neil Fortner Date: Tue, 28 Apr 2015 22:22:55 -0500 Subject: [svn-r26962] Add support for unlimited selections to VDS code. Not tested (except for percival-unlim example) Fix percival-unlim example Other bug fixes/cleanup Tested: Fedora 64 --- examples/h5_vds-percival-unlim.c | 10 +- src/H5Dint.c | 7 + src/H5Dpkg.h | 2 +- src/H5Dprivate.h | 3 + src/H5Dvirtual.c | 271 ++++++++++++++++++++++++++++++++++++++- src/H5Olayout.c | 15 ++- src/H5Oprivate.h | 8 ++ src/H5Pdcpl.c | 29 ++++- src/H5S.c | 26 ++-- src/H5Sall.c | 27 ++++ src/H5Shyper.c | 248 +++++++++++++++++++++++++++++++---- src/H5Snone.c | 27 ++++ src/H5Spkg.h | 5 +- src/H5Spoint.c | 27 ++++ src/H5Sprivate.h | 5 + src/H5Sselect.c | 40 +++++- 16 files changed, 696 insertions(+), 54 deletions(-) diff --git a/examples/h5_vds-percival-unlim.c b/examples/h5_vds-percival-unlim.c index 1911e6d..eaa83b4 100644 --- a/examples/h5_vds-percival-unlim.c +++ b/examples/h5_vds-percival-unlim.c @@ -13,7 +13,7 @@ #include #include -#define FILE "vds-percival-unlim.h5" +#define VFILE "vds-percival-unlim.h5" #define DATASET "VDS-Percival-unlim" #define VDSDIM0 H5S_UNLIMITED #define VDSDIM1 10 @@ -100,7 +100,7 @@ main (void) status = H5Fclose (file); } - file = H5Fcreate (FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + vfile = H5Fcreate (VFILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); /* Create VDS dataspace. */ vspace = H5Screate_simple (RANK, vdsdims, vdsdims_max); @@ -147,6 +147,7 @@ main (void) dcpl, H5P_DEFAULT); status = H5Sclose (vspace); status = H5Sclose (src_space); + status = H5Pclose (dcpl); /* Let's get space of the VDS and its dimension; we should get 40x10x10 */ vspace = H5Dget_space (vdset); H5Sget_simple_extent_dims (vspace, vdsdims_out, vdsdims_max_out); @@ -188,13 +189,12 @@ main (void) status = H5Dwrite (dset, H5T_NATIVE_INT, mem_space, src_space, H5P_DEFAULT, wdata); status = H5Sclose (src_space); - status = H5Pclose (dcpl); status = H5Dclose (dset); status = H5Fclose (file); } /* Let's get space of the VDS and its dimension; we should get 80x10x10 */ - vspace = H5Dget_space (dset); + vspace = H5Dget_space (vdset); H5Sget_simple_extent_dims (vspace, vdsdims_out, vdsdims_max_out); printf ("VDS dimensions second time \n"); printf (" Current: "); @@ -212,7 +212,7 @@ main (void) /* * Open file and dataset using the default properties. */ - vfile = H5Fopen (FILE, H5F_ACC_RDONLY, H5P_DEFAULT); + vfile = H5Fopen (VFILE, H5F_ACC_RDONLY, H5P_DEFAULT); vdset = H5Dopen (vfile, DATASET, H5P_DEFAULT); /* diff --git a/src/H5Dint.c b/src/H5Dint.c index d7ef991..1757665 100644 --- a/src/H5Dint.c +++ b/src/H5Dint.c @@ -2346,6 +2346,8 @@ H5D__set_extent(H5D_t *dset, const hsize_t *size, hid_t dxpl_id) HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to mark dataspace as dirty") } /* end if */ + /* Make this function work with virtual layout VDSINC */ + done: FUNC_LEAVE_NOAPI_TAG(ret_value, FAIL) } /* end H5D__set_extent() */ @@ -2767,6 +2769,11 @@ H5D_get_space(H5D_t *dset) FUNC_ENTER_NOAPI_NOINIT + /* If the layout is virtual, update the extent */ + if(dset->shared->layout.type == H5D_VIRTUAL) + if(H5D__virtual_set_extent_unlim(dset, H5AC_ind_dxpl_id) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update virtual dataset extent") + /* Read the data space message and return a data space object */ if(NULL == (space = H5S_copy(dset->shared->space, FALSE, TRUE))) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to get data space") diff --git a/src/H5Dpkg.h b/src/H5Dpkg.h index 1e5038b..978936b 100644 --- a/src/H5Dpkg.h +++ b/src/H5Dpkg.h @@ -611,7 +611,6 @@ H5_DLL herr_t H5D__contig_copy(H5F_t *f_src, const H5O_storage_contig_t *storage H5_DLL herr_t H5D__contig_delete(H5F_t *f, hid_t dxpl_id, const H5O_storage_t *store); - /* Functions that operate on chunked dataset storage */ H5_DLL htri_t H5D__chunk_cacheable(const H5D_io_info_t *io_info, haddr_t caddr, hbool_t write_op); @@ -660,6 +659,7 @@ H5_DLL herr_t H5D__compact_copy(H5F_t *f_src, H5O_storage_compact_t *storage_src /* Functions that operate on virtual dataset storage */ H5_DLL herr_t H5D__virtual_copy_layout(H5O_layout_t *layout); +H5_DLL herr_t H5D__virtual_set_extent_unlim(const H5D_t *dset, hid_t dxpl_id); H5_DLL herr_t H5D__virtual_reset_layout(H5O_layout_t *layout); H5_DLL herr_t H5D__virtual_delete(H5F_t *f, hid_t dxpl_id, H5O_storage_t *storage); H5_DLL herr_t H5D__virtual_copy(H5F_t *f_src, diff --git a/src/H5Dprivate.h b/src/H5Dprivate.h index b2d88ee..5f588fd 100644 --- a/src/H5Dprivate.h +++ b/src/H5Dprivate.h @@ -177,6 +177,9 @@ H5_DLL herr_t H5D_vlen_reclaim(hid_t type_id, H5S_t *space, hid_t plist_id, /* Functions that operate on chunked storage */ H5_DLL herr_t H5D_chunk_idx_reset(H5O_storage_chunk_t *storage, hbool_t reset_addr); +/* Functions that operate on virtual storage */ +H5_DLL herr_t H5D_virtual_update_min_dims(H5O_layout_t *layout, size_t idx); + /* Functions that operate on indexed storage */ H5_DLL herr_t H5D_btree_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent, int fwidth, unsigned ndims); diff --git a/src/H5Dvirtual.c b/src/H5Dvirtual.c index 3643c53..67f405f 100644 --- a/src/H5Dvirtual.c +++ b/src/H5Dvirtual.c @@ -155,6 +155,12 @@ H5D__virtual_copy_layout(H5O_layout_t *layout) = H5S_copy(orig_list[i].virtual_select, FALSE, TRUE))) HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "unable to copy virtual selection") layout->storage.u.virt.list[i].source_dset = NULL; + layout->storage.u.virt.list[i].unlim_dim_source = orig_list[i].unlim_dim_source; + layout->storage.u.virt.list[i].unlim_dim_virtual = orig_list[i].unlim_dim_virtual; + layout->storage.u.virt.list[i].unlim_extent_source = orig_list[i].unlim_extent_source; + layout->storage.u.virt.list[i].unlim_extent_virtual = orig_list[i].unlim_extent_virtual; + layout->storage.u.virt.list[i].clip_size_source = orig_list[i].clip_size_source; + layout->storage.u.virt.list[i].clip_size_virtual = orig_list[i].clip_size_virtual; layout->storage.u.virt.list[i].source_space_status = orig_list[i].source_space_status; layout->storage.u.virt.list[i].virtual_space_status = orig_list[i].virtual_space_status; } /* end for */ @@ -178,13 +184,71 @@ done: /*------------------------------------------------------------------------- + * Function: H5D_virtual_update_min_dims + * + * Purpose: Updates the virtual layout's "min_dims" field to take into + * account the "idx"th entry in the mapping list. The entry + * must be complete, though top level fields list_nused does + * (and of course min_dims) do not need to take it into + * account. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Neil Fortner + * February 10, 2015 + * + *------------------------------------------------------------------------- + */ +herr_t +H5D_virtual_update_min_dims(H5O_layout_t *layout, size_t idx) +{ + H5S_sel_type sel_type; + int rank; + hsize_t bounds_start[H5S_MAX_RANK]; + hsize_t bounds_end[H5S_MAX_RANK]; + int i; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(FAIL) + + HDassert(layout); + HDassert(layout->type == H5D_VIRTUAL); + HDassert(idx < layout->storage.u.virt.list_nalloc); + + /* Get type of selection */ + if(H5S_SEL_ERROR == (sel_type = H5S_GET_SELECT_TYPE(layout->storage.u.virt.list[idx].virtual_select))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to get selection type") + + /* Do not update min_dims for "all" or "none" selections */ + if((sel_type == H5S_SEL_ALL) || (sel_type == H5S_SEL_NONE)) + HGOTO_DONE(SUCCEED) + + /* Get rank of vspace */ + if((rank = H5S_GET_EXTENT_NDIMS(layout->storage.u.virt.list[idx].virtual_select)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to get number of dimensions") + + /* Get selection bounds */ + if(H5S_SELECT_BOUNDS(layout->storage.u.virt.list[idx].virtual_select, bounds_start, bounds_end) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to get selection bounds") + + /* Update min_dims */ + for(i = 0; i < rank; i++) + /* Don't check unlimited dimensions in the selection */ + if((i != layout->storage.u.virt.list[idx].unlim_dim_virtual) + && (bounds_end[i] > layout->storage.u.virt.min_dims[i])) + layout->storage.u.virt.min_dims[i] = bounds_end[i]; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D_virtual_update_min_dims() */ + + +/*------------------------------------------------------------------------- * Function: H5D__virtual_open_source_dset * * Purpose: Attempts to open a source dataset. * - * Return: TRUE: Source dataset opened - * FALSE: Source dataset not opened - * Negative: Error + * Return: Non-negative on success/Negative on failure * * Programmer: Neil Fortner * March 6, 2015 @@ -234,7 +298,7 @@ H5D__virtual_open_source_dset(const H5D_t *vdset, /* Patch the source selection if necessary */ if(virtual_ent->source_space_status != H5O_VIRTUAL_STATUS_CORRECT) { if(H5S_extent_copy(virtual_ent->source_select, virtual_ent->source_dset->shared->space) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "can't copy virtual dataspace extent") + HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "can't copy source dataspace extent") virtual_ent->source_space_status = H5O_VIRTUAL_STATUS_CORRECT; } /* end if */ @@ -249,6 +313,193 @@ done: /*------------------------------------------------------------------------- + * Function: H5D__virtual_set_extent_unlim + * + * Purpose: Sets the extent of the virtual dataset by checking the + * extents of source datasets where an unlimited selection + * matching. Dimensions that are not unlimited in any + * virtual mapping selections are not affected. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Neil Fortner + * April 22, 2015 + * + *------------------------------------------------------------------------- + */ +herr_t +H5D__virtual_set_extent_unlim(const H5D_t *dset, hid_t dxpl_id) +{ + H5O_storage_virtual_t *storage; + hsize_t new_dims[H5S_MAX_RANK]; + hsize_t curr_dims[H5S_MAX_RANK]; + hsize_t clip_size; + int rank; + hbool_t changed = FALSE; /* Whether the VDS extent changed */ + size_t i; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE + + /* Sanity check */ + HDassert(dset); + storage = &dset->shared->layout.storage.u.virt; + HDassert(dset->shared->layout.storage.type == H5D_VIRTUAL); + + /* Get rank of VDS */ + if((rank = H5S_GET_EXTENT_NDIMS(dset->shared->space)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to get number of dimensions") + + /* Initialize new_dims to HSIZE_UNDEF */ + for(i = 0; i < (size_t)rank; i++) + new_dims[i] = HSIZE_UNDEF; + + /* Iterate over mappings */ + for(i = 0; i < storage->list_nalloc; i++) + /* Check for unlimited dimension */ + if(storage->list[i].unlim_dim_virtual >= 0) { + HDassert(storage->list[i].unlim_dim_source >= 0); + + /* Open source dataset */ + if(!storage->list[i].source_dset) + if(H5D__virtual_open_source_dset(dset, &storage->list[i], dxpl_id) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "unable to open source dataset") + + /* Check if source dataset is open */ + if(storage->list[i].source_dset) { + /* Retrieve current source dataset extent and patch mapping. + * Note this will clip the source selection to the extent. */ + if(H5S_extent_copy(storage->list[i].source_select, storage->list[i].source_dset->shared->space) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "can't copy source dataspace extent") + + /* Get source space dimenstions */ + if(H5S_get_simple_extent_dims(storage->list[i].source_select, curr_dims, NULL) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get source space dimensions") + + /* Check if the source extent in the unlimited dimension + * changed since the last time the VDS extent/mapping + * was updated */ + if(curr_dims[storage->list[i].unlim_dim_source] + == storage->list[i].unlim_extent_source) + /* Use cached result for clip size */ + clip_size = storage->list[i].clip_size_virtual; + else { + /* Get size that virtual selection would be clipped + * to to match size of source selection */ + if(H5S_hyper_get_clip_extent(storage->list[i].virtual_select, storage->list[i].source_select, &clip_size) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get hyperslab clip size") + + /* If we are setting the extent by the maximum of all + * mappings, clip virtual_select. Note that if we used the + * cached clip_size above, the selection will already be + * clipped to the correct size. */ + if(storage->set_extent_max) + if(H5S_hyper_clip_unlim(storage->list[i].virtual_select, clip_size)) + HGOTO_ERROR(H5E_DATASET, H5E_CANTCLIP, FAIL, "failed to clip unlimited selection") + + /* Update cached values unlim_extent_source and + * clip_size_virtual */ + storage->list[i].unlim_extent_source = curr_dims[storage->list[i].unlim_dim_source]; + storage->list[i].clip_size_virtual = clip_size; + } /* end else */ + + /* Update new_dims */ + if((new_dims[storage->list[i].unlim_dim_virtual] == HSIZE_UNDEF) + || (storage->set_extent_max ? (clip_size + > (hsize_t)new_dims[storage->list[i].unlim_dim_virtual]) + : (clip_size + < (hsize_t)new_dims[storage->list[i].unlim_dim_virtual]))) + new_dims[storage->list[i].unlim_dim_virtual] = clip_size; + } /* end if */ + } /* end if */ + + /* Get current VDS dimensions */ + if(H5S_get_simple_extent_dims(dset->shared->space, curr_dims, NULL) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get VDS dimensions") + + /* Calculate new extent */ + for(i = 0; i < (size_t)rank; i++) { + if((new_dims[i] != HSIZE_UNDEF) && (new_dims[i] != curr_dims[i])) { + changed = TRUE; + curr_dims[i] = new_dims[i]; + } /* end if */ + if(storage->min_dims[i] > curr_dims[i]) { + HDassert(0 && "Checking code coverage..."); //VDSINC + changed = TRUE; + curr_dims[i] = storage->min_dims[i]; + } /* end if */ + } /* end for */ + + /* If we did not change the VDS dimensions and we are setting the extent by + * maximum, there is nothing more to update */ + if(changed || !storage->set_extent_max) { + /* Update VDS extent */ + if(changed) + if(H5S_set_extent(dset->shared->space, curr_dims) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to modify size of data space") + + /* Iterate over mappings again to update source selections and virtual + * mapping extents */ + for(i = 0; i < storage->list_nalloc; i++) + /* Check for unlimited dimension */ + if((storage->list[i].unlim_dim_source >= 0) + && (storage->list[i].source_dset)) { + HDassert(storage->list[i].unlim_dim_virtual >= 0); + + /* Update virtual mapping extent. Note this function does not + * clip the selection. */ + if(changed) + if(H5S_set_extent(storage->list[i].virtual_select, curr_dims) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to modify size of data space") + + /* Check if we are setting extent by the minimum of mappings */ + if(!storage->set_extent_max) { + /* Clip virtual selection to extent (only necessary if the + * extent changed, otherwise it will already be clipped to + * the extent) */ + if(changed) { + HDassert(0 && "Checking code coverage..."); //VDSINC + if(H5S_hyper_clip_to_extent(storage->list[i].virtual_select)) + HGOTO_ERROR(H5E_DATASET, H5E_CANTCLIP, FAIL, "failed to clip unlimited selection") + } //VDSINC + + /* Check if the virtual extent in the unlimited dimension + * changed since the last time the VDS extent/mapping was + * updated */ + if(curr_dims[storage->list[i].unlim_dim_virtual] + == storage->list[i].unlim_extent_virtual) { + HDassert(0 && "Checking code coverage..."); //VDSINC + /* Use cached result for clip size */ + clip_size = storage->list[i].clip_size_source; + } //VDSINC + else { + HDassert(0 && "Checking code coverage..."); //VDSINC + /* Get size that source selection will be clipped to to + * match size of virtual selection */ + if(H5S_hyper_get_clip_extent(storage->list[i].source_select, storage->list[i].virtual_select, &clip_size) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get hyperslab clip size") + + /* Update cached values unlim_extent_virtual and + * clip_size_source */ + storage->list[i].unlim_extent_virtual = curr_dims[storage->list[i].unlim_dim_virtual]; + storage->list[i].clip_size_source = clip_size; + } /* end else */ + + /* Clip source_select */ + if(H5S_hyper_clip_unlim(storage->list[i].source_select, clip_size)) + HGOTO_ERROR(H5E_DATASET, H5E_CANTCLIP, FAIL, "failed to clip unlimited selection") + } /* end if */ + } /* end if */ + } /* end if */ + + /* Call H5D__mark so dataspace is updated on disk? VDSINC */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D__virtual_set_extent_unlim() */ + + +/*------------------------------------------------------------------------- * Function: H5D__virtual_reset_layout * * Purpose: Frees internal structures in a virtual storage layout @@ -462,6 +713,11 @@ H5D__virtual_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, storage = &io_info->dset->shared->layout.storage.u.virt; + /* Update VDS extent due to unlimited selections */ + /* Don't call if there is no unlimited selection? VDSINC */ + if(H5D__virtual_set_extent_unlim(io_info->dset, io_info->dxpl_id) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update virtual dataset extent") + /* Iterate over mappings */ for(i = 0; i < storage->list_nused; i++) { /* Sanity check that the virtual space has been patched by now */ @@ -515,7 +771,7 @@ H5D__virtual_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, } /* end for */ /* Fill unmapped part of buffer with fill value. Keep track of total number - * elements written to memory buffer and assert that it == nelmts */ + * elements written to memory buffer and assert that it == nelmts VDSINC */ done: /* Release allocated resources on failure */ @@ -569,6 +825,11 @@ H5D__virtual_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, storage = &io_info->dset->shared->layout.storage.u.virt; + /* Update VDS extent due to unlimited selections */ + /* Don't call if there is no unlimited selection? VDSINC */ + if(H5D__virtual_set_extent_unlim(io_info->dset, io_info->dxpl_id) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update virtual dataset extent") + /* Iterate over mappings */ for(i = 0; i < storage->list_nused; i++) { /* Sanity check that virtual space has been patched by now */ diff --git a/src/H5Olayout.c b/src/H5Olayout.c index a20b6d4..fb9bb9c 100644 --- a/src/H5Olayout.c +++ b/src/H5Olayout.c @@ -191,7 +191,7 @@ H5O_layout_decode(H5F_t *f, hid_t dxpl_id, H5O_t UNUSED *open_oh, } /* end if */ else { /* Layout class */ - mesg->type = (H5D_layout_t)*p++; + mesg->type = mesg->storage.type = (H5D_layout_t)*p++; /* Interpret the rest of the message according to the layout class */ switch(mesg->type) { @@ -251,6 +251,7 @@ H5O_layout_decode(H5F_t *f, hid_t dxpl_id, H5O_t UNUSED *open_oh, mesg->storage.u.virt.list_nused = 0; mesg->storage.u.virt.list = NULL; mesg->storage.u.virt.list_nalloc = 0; + mesg->storage.u.virt.set_extent_max = TRUE; /* Decode heap block if it exists */ if(mesg->storage.u.virt.serial_list_hobjid.addr != HADDR_UNDEF) { @@ -300,6 +301,18 @@ H5O_layout_decode(H5F_t *f, hid_t dxpl_id, H5O_t UNUSED *open_oh, /* Virtual selection */ if(H5S_SELECT_DESERIALIZE(f, &(mesg->storage.u.virt.list[i].virtual_select), &heap_block_p) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, NULL, "can't decode virtual space selection") + + /* unlim_dim fields */ + mesg->storage.u.virt.list[i].unlim_dim_source = H5S_get_select_unlim_dim(mesg->storage.u.virt.list[i].source_select); + mesg->storage.u.virt.list[i].unlim_dim_virtual = H5S_get_select_unlim_dim(mesg->storage.u.virt.list[i].virtual_select); + mesg->storage.u.virt.list[i].unlim_extent_source = HSIZE_UNDEF; + mesg->storage.u.virt.list[i].unlim_extent_virtual = HSIZE_UNDEF; + mesg->storage.u.virt.list[i].clip_size_source = HSIZE_UNDEF; + mesg->storage.u.virt.list[i].clip_size_virtual = HSIZE_UNDEF; + + /* Update min_dims */ + if(H5D_virtual_update_min_dims(mesg, i) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to update virtual dataset minimum dimensions") } /* end for */ /* Read stored checksum */ diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h index 7c69a01..74cc9a4 100644 --- a/src/H5Oprivate.h +++ b/src/H5Oprivate.h @@ -428,6 +428,12 @@ typedef struct H5O_storage_virtual_ent_t { /* Not stored */ struct H5D_t *source_dset; /* Source dataset */ + int unlim_dim_source; /* Unlimited dimension in source_select */ + int unlim_dim_virtual; /* Unlimited dimension in virtual_select */ + hsize_t unlim_extent_source; /* Extent of unlimited dimension in source dset last time virtual_select was patched to match selection */ + hsize_t unlim_extent_virtual; /* Extent of unlimited dimension in virtual dset last time source_select was patched to match selection */ + hsize_t clip_size_virtual; /* Size selection would be clipped to in virtual selection, ignoring other mappings, when source extent == unlim_extent_source */ + hsize_t clip_size_source; /* Size selection would be clipped to in source selection when virtual extent == unlim_extent_virtual */ H5O_virtual_space_status_t source_space_status; /* Extent patching status of source_select */ H5O_virtual_space_status_t virtual_space_status; /* Extent patching status of virtual_select */ } H5O_storage_virtual_ent_t; @@ -442,6 +448,8 @@ typedef struct H5O_storage_virtual_t { /* Not stored */ size_t list_nalloc; /* Number of slots allocated */ + hsize_t min_dims[H5S_MAX_RANK]; /* Minimum extent of VDS (maximum of all non-unlimited selection bounds) */ + hbool_t set_extent_max; /* Whether we set the extent by the maximum (TRUE) or minimum (FALSE) of unlimited selections */ } H5O_storage_virtual_t; typedef struct H5O_storage_t { diff --git a/src/H5Pdcpl.c b/src/H5Pdcpl.c index 60241a0..575de9c 100644 --- a/src/H5Pdcpl.c +++ b/src/H5Pdcpl.c @@ -43,6 +43,7 @@ #include "H5MMprivate.h" /* Memory management */ #include "H5Oprivate.h" /* Object headers */ #include "H5Ppkg.h" /* Property lists */ +#include "H5Sprivate.h" /* Dataspaces */ #include "H5Tprivate.h" /* Datatypes */ #include "H5Zpkg.h" /* Data filters */ @@ -56,12 +57,12 @@ #define H5D_DEF_STORAGE_CONTIG_INIT {HADDR_UNDEF, (hsize_t)0} #define H5D_DEF_STORAGE_CHUNK_INIT {H5D_CHUNK_IDX_BTREE, HADDR_UNDEF, NULL, {{HADDR_UNDEF, NULL}}} #define H5D_DEF_LAYOUT_CHUNK_INIT {(unsigned)0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, (uint32_t)0, (hsize_t)0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}} -#define H5D_DEF_STORAGE_VIRTUAL_INIT {{HADDR_UNDEF, 0}, 0, NULL, 0} +#define H5D_DEF_STORAGE_VIRTUAL_INIT {{HADDR_UNDEF, 0}, 0, NULL, 0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, TRUE} #ifdef H5_HAVE_C99_DESIGNATED_INITIALIZER #define H5D_DEF_STORAGE_COMPACT {H5D_COMPACT, { .compact = H5D_DEF_STORAGE_COMPACT_INIT }} #define H5D_DEF_STORAGE_CONTIG {H5D_CONTIGUOUS, { .contig = H5D_DEF_STORAGE_CONTIG_INIT }} #define H5D_DEF_STORAGE_CHUNK {H5D_CHUNKED, { .chunk = H5D_DEF_STORAGE_CHUNK_INIT }} -#define H5D_DEF_STORAGE_VIRTUAL {H5D_CHUNKED, { .virt = H5D_DEF_STORAGE_VIRTUAL_INIT }} +#define H5D_DEF_STORAGE_VIRTUAL {H5D_VIRTUAL, { .virt = H5D_DEF_STORAGE_VIRTUAL_INIT }} #define H5D_DEF_LAYOUT_COMPACT {H5D_COMPACT, H5O_LAYOUT_VERSION_3, NULL, {H5D_DEF_LAYOUT_CHUNK_INIT}, H5D_DEF_STORAGE_COMPACT} #define H5D_DEF_LAYOUT_CONTIG {H5D_CONTIGUOUS, H5O_LAYOUT_VERSION_3, NULL, {H5D_DEF_LAYOUT_CHUNK_INIT}, H5D_DEF_STORAGE_CONTIG} #define H5D_DEF_LAYOUT_CHUNK {H5D_CHUNKED, H5O_LAYOUT_VERSION_3, NULL, {H5D_DEF_LAYOUT_CHUNK_INIT}, H5D_DEF_STORAGE_CHUNK} @@ -75,7 +76,7 @@ #define H5D_DEF_LAYOUT_COMPACT {H5D_COMPACT, H5O_LAYOUT_VERSION_3, NULL, {H5D_DEF_LAYOUT_CHUNK_INIT}, {H5D_CONTIGUOUS, H5D_DEF_STORAGE_CONTIG_INIT}} #define H5D_DEF_LAYOUT_CONTIG {H5D_CONTIGUOUS, H5O_LAYOUT_VERSION_3, NULL, {H5D_DEF_LAYOUT_CHUNK_INIT}, {H5D_CONTIGUOUS, H5D_DEF_STORAGE_CONTIG_INIT}} #define H5D_DEF_LAYOUT_CHUNK {H5D_CHUNKED, H5O_LAYOUT_VERSION_3, NULL, {H5D_DEF_LAYOUT_CHUNK_INIT}, {H5D_CONTIGUOUS, H5D_DEF_STORAGE_CONTIG_INIT}} -#define H5D_DEF_LAYOUT_VIRTUAL {H5D_CHUNKED, H5O_LAYOUT_VERSION_3, NULL, {H5D_DEF_LAYOUT_CHUNK_INIT}, {H5D_CONTIGUOUS, H5D_DEF_STORAGE_CONTIG_INIT}} +#define H5D_DEF_LAYOUT_VIRTUAL {H5D_VIRTUAL, H5O_LAYOUT_VERSION_3, NULL, {H5D_DEF_LAYOUT_CHUNK_INIT}, {H5D_CONTIGUOUS, H5D_DEF_STORAGE_CONTIG_INIT}} #endif /* H5_HAVE_C99_DESIGNATED_INITIALIZER */ /* ======== Dataset creation properties ======== */ @@ -1669,8 +1670,20 @@ H5Pset_virtual(hid_t dcpl_id, hid_t vspace_id, const char *src_file_name, HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "unable to copy source selection") if(NULL == (layout.storage.u.virt.list[layout.storage.u.virt.list_nused].virtual_select = H5S_copy(vspace, FALSE, TRUE))) HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "unable to copy virtual selection") + layout.storage.u.virt.list[layout.storage.u.virt.list_nused].unlim_dim_source = H5S_get_select_unlim_dim(src_space); + layout.storage.u.virt.list[layout.storage.u.virt.list_nused].unlim_dim_virtual = H5S_get_select_unlim_dim(vspace); + layout.storage.u.virt.list[layout.storage.u.virt.list_nused].unlim_extent_source = HSIZE_UNDEF; + layout.storage.u.virt.list[layout.storage.u.virt.list_nused].unlim_extent_virtual = HSIZE_UNDEF; + layout.storage.u.virt.list[layout.storage.u.virt.list_nused].clip_size_source = HSIZE_UNDEF; + layout.storage.u.virt.list[layout.storage.u.virt.list_nused].clip_size_virtual = HSIZE_UNDEF; layout.storage.u.virt.list[layout.storage.u.virt.list_nused].source_space_status = H5O_VIRTUAL_STATUS_USER; layout.storage.u.virt.list[layout.storage.u.virt.list_nused].virtual_space_status = H5O_VIRTUAL_STATUS_USER; + + /* 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") + + /* Finish adding entry */ layout.storage.u.virt.list_nused++; adding_entry = FALSE; @@ -1786,6 +1799,11 @@ H5Pget_virtual_vspace(hid_t dcpl_id, size_t index) if(NULL == (space = H5S_copy(layout.storage.u.virt.list[index].virtual_select, FALSE, TRUE))) HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "unable to copy virtual selection") + /* Clip selection to extent */ + if(H5S_get_select_unlim_dim(space) >= 0) + if(H5S_hyper_clip_to_extent(space) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTCLIP, FAIL, "failed to clip unlimited selection") + /* Register ID */ if((ret_value = H5I_register(H5I_DATASPACE, space, TRUE)) < 0) HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register data space") @@ -1844,6 +1862,11 @@ H5Pget_virtual_srcspace(hid_t dcpl_id, size_t index) 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") + /* Clip selection to extent */ + if(H5S_get_select_unlim_dim(space) >= 0) + if(H5S_hyper_clip_to_extent(space) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTCLIP, FAIL, "failed to clip unlimited selection") + /* Register ID */ if((ret_value = H5I_register(H5I_DATASPACE, space, TRUE)) < 0) HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register data space") diff --git a/src/H5S.c b/src/H5S.c index e24879c..045ab51 100644 --- a/src/H5S.c +++ b/src/H5S.c @@ -522,7 +522,7 @@ H5S_extent_copy(H5S_t *dst, const H5S_t *src) /* If the selection is 'hyper', update the selection due to changed extent */ if(H5S_GET_SELECT_TYPE(dst) == H5S_SEL_HYPERSLABS) - if(H5S__hyper_update_extent_offset(dst) < 0) + if(H5S_hyper_clip_to_extent(dst) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't update hyperslab") done: @@ -1363,7 +1363,7 @@ H5S__set_extent_simple(H5S_t *space, unsigned rank, const hsize_t *dims, /* If the selection is 'hyper', update the selection due to changed * extent */ if(H5S_GET_SELECT_TYPE(space) == H5S_SEL_HYPERSLABS) - if(H5S__hyper_update_extent_offset(space) < 0) + if(H5S_hyper_clip_to_extent(space) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't update hyperslab") done: @@ -1883,7 +1883,14 @@ done: /*------------------------------------------------------------------------- * Function: H5S_set_extent * - * Purpose: Modify the dimensions of a dataspace. Based on H5S_extend + * Purpose: Modify the dimensions of a dataspace. Based on H5S_extend. + * + * Note that this function does *not* clip unlimited + * selections, because it is not currently necessary to do + * that anywhere this function is called. If this becomes + * necessary (if the selection could be unlimited and the + * clip size is not being handled separately), this function + * must be updated to (optionally) clip the selection. * * Return: Success: Non-negative * Failure: Negative @@ -1966,6 +1973,13 @@ H5S_has_extent(const H5S_t *ds) * * Purpose: Modify the dimensions of a dataspace. Based on H5S_extend * + * Note that this function does *not* clip unlimited + * selections, because it is not currently necessary to do + * that anywhere this function is called. If this becomes + * necessary (if the selection could be unlimited and the + * clip size is not being handled separately), this function + * must be updated to (optionally) clip the selection. + * * Return: Success: Non-negative * Failure: Negative * @@ -1999,12 +2013,6 @@ H5S_set_extent_real(H5S_t *space, const hsize_t *size) if(H5S_select_all(space, FALSE) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection") - /* If the selection is 'hyper', update the selection due to changed - * extent */ - if(H5S_GET_SELECT_TYPE(space) == H5S_SEL_HYPERSLABS) - if(H5S__hyper_update_extent_offset(space) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't update hyperslab") - /* Mark the dataspace as no longer shared if it was before */ if(H5O_msg_reset_share(H5O_SDSPACE_ID, space) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRESET, FAIL, "can't stop sharing dataspace") diff --git a/src/H5Sall.c b/src/H5Sall.c index cb7e6f2..94eb5f5 100644 --- a/src/H5Sall.c +++ b/src/H5Sall.c @@ -45,6 +45,7 @@ static herr_t H5S_all_deserialize(const H5F_t *f, H5S_t *space, uint32_t version, uint8_t flags, const uint8_t **p); static herr_t H5S_all_bounds(const H5S_t *space, hsize_t *start, hsize_t *end); static herr_t H5S_all_offset(const H5S_t *space, hsize_t *off); +static int H5S_all_unlim_dim(const H5S_t *space); static htri_t H5S_all_is_contiguous(const H5S_t *space); static htri_t H5S_all_is_single(const H5S_t *space); static htri_t H5S_all_is_regular(const H5S_t *space); @@ -76,6 +77,7 @@ const H5S_select_class_t H5S_sel_all[1] = {{ H5S_all_deserialize, H5S_all_bounds, H5S_all_offset, + H5S_all_unlim_dim, H5S_all_is_contiguous, H5S_all_is_single, H5S_all_is_regular, @@ -662,6 +664,31 @@ H5S_all_offset(const H5S_t UNUSED *space, hsize_t *offset) /*-------------------------------------------------------------------------- NAME + H5S_all_unlim_dim + PURPOSE + Return unlimited dimension of selection, or -1 if none + USAGE + VDSINC + RETURNS + Unlimited dimension of selection, or -1 if none (never fails). + DESCRIPTION + VDSINC + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static int +H5S_all_unlim_dim(const H5S_t UNUSED *space) +{ + FUNC_ENTER_NOAPI_NOERR + + FUNC_LEAVE_NOAPI(-1) +} /* end H5S_all_unlim_dim() */ + + +/*-------------------------------------------------------------------------- + NAME H5S_all_is_contiguous PURPOSE Check if a "all" selection is contiguous within the dataspace extent. diff --git a/src/H5Shyper.c b/src/H5Shyper.c index d9bde55..81306c9 100644 --- a/src/H5Shyper.c +++ b/src/H5Shyper.c @@ -60,6 +60,7 @@ static herr_t H5S_hyper_deserialize(const H5F_t *f, H5S_t *space, uint32_t version, uint8_t flags, const uint8_t **p); 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 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); @@ -96,6 +97,7 @@ const H5S_select_class_t H5S_sel_hyper[1] = {{ H5S_hyper_deserialize, H5S_hyper_bounds, H5S_hyper_offset, + H5S_hyper_unlim_dim, H5S_hyper_is_contiguous, H5S_hyper_is_single, H5S_hyper_is_regular, @@ -1655,6 +1657,7 @@ H5S_hyper_copy (H5S_t *dst, const H5S_t *src, hbool_t share_selection) dst_hslab->app_diminfo[u] = src_hslab->app_diminfo[u]; } /* end for */ } /* end for */ + dst_hslab->unlim_dim_clip_size = src_hslab->unlim_dim_clip_size; dst_hslab->num_elem_non_unlim = src_hslab->num_elem_non_unlim; dst->select.sel_info.hslab->span_lst=src->select.sel_info.hslab->span_lst; @@ -1681,7 +1684,7 @@ H5S_hyper_copy (H5S_t *dst, const H5S_t *src, hbool_t share_selection) if(!extent_equal) /* Update selection due to changed extent */ - if(H5S__hyper_update_extent_offset(dst) < 0) + if(H5S_hyper_clip_to_extent(dst) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't update hyperslab") } /* end if */ @@ -1906,7 +1909,7 @@ H5S_get_select_hyper_nblocks(H5S_t *space) for(ret_value = 1, u = 0; u < space->extent.rank; u++) { if(diminfo[u].block == (hsize_t)0) HGOTO_DONE((hsize_t)0) - ret_value *= diminfo[u].count;; + ret_value *= diminfo[u].count; } /* end for */ } /* end if */ else @@ -2980,6 +2983,31 @@ done: /*-------------------------------------------------------------------------- NAME + H5S_hyper_unlim_dim + PURPOSE + Return unlimited dimension of selection, or -1 if none + USAGE + VDSINC + RETURNS + Unlimited dimension of selection, or -1 if none (never fails). + DESCRIPTION + VDSINC + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static int +H5S_hyper_unlim_dim(const H5S_t *space) +{ + FUNC_ENTER_NOAPI_NOERR + + FUNC_LEAVE_NOAPI(space->select.sel_info.hslab->unlim_dim) +} /* end H5S_hyper_get_unlim_dim() */ + + +/*-------------------------------------------------------------------------- + NAME H5S_hyper_is_contiguous PURPOSE Check if a hyperslab selection is contiguous within the dataspace extent. @@ -6683,6 +6711,10 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op, /* Save unlim_dim */ space->select.sel_info.hslab->unlim_dim = unlim_dim; + /* Initialize unlim_dim_clip_size to H5S_UNLIMITED so the selection is + * clipped by H5S__hyper_clip_unlim() no matter what the extent is */ + space->select.sel_info.hslab->unlim_dim_clip_size = H5S_UNLIMITED; + /* Indicate that the dimension information is valid */ space->select.sel_info.hslab->diminfo_valid = TRUE; @@ -6693,17 +6725,24 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op, if(unlim_dim >= 0) { space->select.sel_info.hslab->num_elem_non_unlim = (hsize_t)1; for(u = 0; u < space->extent.rank; u++) { + /* Save start/stride/count/block */ space->select.sel_info.hslab->opt_unlim_diminfo[u].start = start[u]; space->select.sel_info.hslab->opt_unlim_diminfo[u].stride = opt_stride[u]; space->select.sel_info.hslab->opt_unlim_diminfo[u].count = opt_count[u]; space->select.sel_info.hslab->opt_unlim_diminfo[u].block = opt_block[u]; + /* Calculate num_elem_non_unlim */ if((int)u != unlim_dim) space->select.sel_info.hslab->num_elem_non_unlim *= (opt_count[u] * opt_block[u]); } /* end for */ + /* Initialize unlim_dim_clip_size to H5S_UNLIMITED so the selection + * is clipped by H5S__hyper_clip_to_extent() no matter what the + * extent is */ + space->select.sel_info.hslab->unlim_dim_clip_size = H5S_UNLIMITED; + /* Set opt_diminfo or span tree based on extent */ - if(H5S__hyper_update_extent_offset(space) < 0) + if(H5S_hyper_clip_to_extent(space) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't set selection based on extent") } /* end if */ } /* end if */ @@ -7133,13 +7172,19 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op, /* Check for unlimited dimension */ for(u = 0; uextent.rank; u++) if((count[u] == H5S_UNLIMITED) || (block[u] == H5S_UNLIMITED)) { - if(unlim_dim >= 0) + if(unlim_dim >= 0) { + HDassert(0 && "Checking code coverage..."); //VDSINC HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "cannot have more than one unlimited dimension in selection") + } //VDSINC else { - if(op != H5S_SELECT_SET) + if(op != H5S_SELECT_SET) { + HDassert(0 && "Checking code coverage..."); //VDSINC HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "cannot use unlimited selection to modify existing selection") - if(count[u] == block[u] /* == H5S_UNLIMITED */) + } //VDSINC + if(count[u] == block[u] /* == H5S_UNLIMITED */) { + HDassert(0 && "Checking code coverage..."); //VDSINC HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "count and block cannot both be unlimited") + } //VDSINC unlim_dim = (int)u; } /* end else */ } /* end if */ @@ -7336,6 +7381,11 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op, /* Save unlim_dim */ space->select.sel_info.hslab->unlim_dim = unlim_dim; + /* Initialize unlim_dim_clip_size to H5S_UNLIMITED so the selection is + * clipped by H5S__hyper_clip_to_extent() no matter what the extent is + */ + space->unlim_dim_clip_size = H5S_UNLIMITED; + /* Indicate that the dimension information is valid */ space->select.sel_info.hslab->diminfo_valid=TRUE; @@ -7356,7 +7406,7 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op, } /* end for */ /* Set opt_diminfo or span tree based on extent */ - if(H5S__hyper_update_extent_offset(space) < 0) + if(H5S__hyper_clip_to_extent(space) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't set selection based on extent") } /* end if */ } /* end if */ @@ -7365,8 +7415,10 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op, HDassert(H5S_GET_SELECT_TYPE(space) == H5S_SEL_HYPERSLABS); /* Cannot modify unlimited selections */ - if(space->select.sel_info.hslab->unlim_dim >= 0) + if(space->select.sel_info.hslab->unlim_dim >= 0) { + HDassert(0 && "Checking code coverage..."); //VDSINC HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "cannot modify unlimited selection") + } //VDSINC /* Check if there's no hyperslab span information currently */ if(space->select.sel_info.hslab->span_lst==NULL) @@ -9502,40 +9554,39 @@ done: /*-------------------------------------------------------------------------- NAME - H5S__hyper_update_extent_offset + H5S_hyper_clip_unlim PURPOSE - Updates the hyperslab selection after a change to the dataspace extent - or offset + Clips the unlimited dimension of the hyperslab selection to the + specified size USAGE VDSINC RETURNS Non-negative on success/Negative on failure. DESCRIPTION - since unlimited selections are internally described as limited - selections with maximal size, these internal selections need to be - updated whenever the maximum size changes. This function - recaluculates the unlimited dimension (if any) of the hyperslab - selection when the extent or offset is changed. + This function recalculates the internal description of the hyperslab + to make the unlimited dimension extend to the specified extent. GLOBAL VARIABLES COMMENTS, BUGS, ASSUMPTIONS + Note this function takes the offset into account. EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ herr_t -H5S__hyper_update_extent_offset(H5S_t *space) +H5S_hyper_clip_unlim(H5S_t *space, hsize_t clip_size) { H5S_hyper_sel_t *hslab; /* Convenience pointer to hyperslab info */ herr_t ret_value = SUCCEED; - FUNC_ENTER_PACKAGE + FUNC_ENTER_NOAPI(FAIL) /* Check parameters */ HDassert(space); hslab = space->select.sel_info.hslab; HDassert(hslab); + HDassert(hslab->unlim_dim >= 0); - /* Check for unlimited dimension */ - if(hslab->unlim_dim < 0) + /* Check for no need to change size */ + if(clip_size == hslab->unlim_dim_clip_size) HGOTO_DONE(SUCCEED) /* Free previous spans, if any */ @@ -9548,10 +9599,10 @@ H5S__hyper_update_extent_offset(H5S_t *space) /* Initialize opt_diminfo with opt_unlim_diminfo */ hslab->opt_diminfo[hslab->unlim_dim] = hslab->opt_unlim_diminfo[hslab->unlim_dim]; - /* Check for selection outside extent */ + /* Check for selection outside clip size */ if((hsize_t)((hssize_t)hslab->opt_diminfo[hslab->unlim_dim].start + space->select.offset[hslab->unlim_dim]) - >= space->extent.size[hslab->unlim_dim]) { + >= clip_size) { if(hslab->opt_diminfo[hslab->unlim_dim].block == H5S_UNLIMITED) hslab->opt_diminfo[hslab->unlim_dim].block = 0; else @@ -9569,11 +9620,11 @@ H5S__hyper_update_extent_offset(H5S_t *space) if(hslab->opt_diminfo[hslab->unlim_dim].count == (hsize_t)1) { HDassert(hslab->opt_diminfo[hslab->unlim_dim].block == H5S_UNLIMITED); - /* Calculate actual block size for this extent */ + /* Calculate actual block size for this clip size */ hslab->opt_diminfo[hslab->unlim_dim].block = (hsize_t)((hssize_t)space->extent.size[hslab->unlim_dim] - - ((hssize_t)hslab->opt_diminfo[hslab->unlim_dim].start - + space->select.offset[hslab->unlim_dim])); + - ((hssize_t)hslab->opt_diminfo[hslab->unlim_dim].start) + + space->select.offset[hslab->unlim_dim]); /* Calculate number of elements */ space->select.num_elem = hslab->opt_diminfo[hslab->unlim_dim].block @@ -9588,7 +9639,7 @@ H5S__hyper_update_extent_offset(H5S_t *space) /* Calculate initial count (last block may be partial) */ hslab->opt_diminfo[hslab->unlim_dim].count = - ((hsize_t)((hssize_t)space->extent.size[hslab->unlim_dim] + ((hsize_t)((hssize_t)clip_size - ((hssize_t)hslab->opt_diminfo[hslab->unlim_dim].start + space->select.offset[hslab->unlim_dim]) + (hssize_t)hslab->opt_diminfo[hslab->unlim_dim].stride @@ -9605,7 +9656,7 @@ H5S__hyper_update_extent_offset(H5S_t *space) if(((hslab->opt_diminfo[hslab->unlim_dim].stride * (hslab->opt_diminfo[hslab->unlim_dim].count - (hsize_t)1)) + hslab->opt_diminfo[hslab->unlim_dim].block - (hsize_t)1) - > ((hsize_t)((hssize_t)space->extent.size[hslab->unlim_dim] + > ((hsize_t)((hssize_t)clip_size - (hssize_t)hslab->opt_diminfo[hslab->unlim_dim].start + space->select.offset[hslab->unlim_dim]))) { /* Last block is partial, need to construct compound selection */ @@ -9616,9 +9667,150 @@ H5S__hyper_update_extent_offset(H5S_t *space) hslab->diminfo_valid = TRUE; } /* end else */ + /* Save clip size */ + hslab->unlim_dim_clip_size = clip_size; + done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5S__hyper_update_extent_offset() */ +} /* end H5S_hyper_clip_unlim() */ + + +/*-------------------------------------------------------------------------- + NAME + H5S_hyper_clip_to_extent + PURPOSE + Updates the hyperslab selection after a change to the dataspace extent + or offset + USAGE + VDSINC + RETURNS + Non-negative on success/Negative on failure. + DESCRIPTION + Since unlimited selections are internally described as limited + selections with maximal size, these internal selections need to be + updated whenever the maximum size changes. This function + recaluculates the unlimited dimension (if any) of the hyperslab + selection when the extent or offset is changed. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + Note this function takes the offset into account. + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5S_hyper_clip_to_extent(H5S_t *space) +{ + H5S_hyper_sel_t *hslab; /* Convenience pointer to hyperslab info */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(FAIL) + + /* Check parameters */ + HDassert(space); + hslab = space->select.sel_info.hslab; + HDassert(hslab); + + /* Check for unlimited dimension */ + if(hslab->unlim_dim < 0) + HGOTO_DONE(SUCCEED) + + /* Clip unlimited selection to extent */ + if(H5S_hyper_clip_unlim(space, space->extent.size[hslab->unlim_dim]) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL, "failed to clip unlimited selection") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5S_hyper_clip_to_extent() */ + + +/*-------------------------------------------------------------------------- + NAME + H5S_hyper_get_clip_extent + PURPOSE + VDSINC + USAGE + VDSINC + RETURNS + Non-negative on success/Negative on failure. + DESCRIPTION + VDSINC + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + Note this assumes the offset has been normalized. + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5S_hyper_get_clip_extent(const H5S_t *clip_space, + const H5S_t *match_space, hsize_t *clip_space_unlim_extent) +{ + const H5S_hyper_sel_t *clip_hslab; /* Convenience pointer to hyperslab info */ + const H5S_hyper_sel_t *match_hslab; /* Convenience pointer to hyperslab info */ + hsize_t num_slices; + hsize_t count; + hsize_t rem_slices; + + FUNC_ENTER_NOAPI_NOERR + + /* Check parameters */ + HDassert(clip_space); + clip_hslab = clip_space->select.sel_info.hslab; + HDassert(clip_hslab); + HDassert(match_space); + match_hslab = match_space->select.sel_info.hslab; + HDassert(match_space); + HDassert(clip_space_unlim_extent); + HDassert(clip_hslab->unlim_dim >= 0); + HDassert(match_hslab->unlim_dim >= 0); + HDassert(clip_hslab->num_elem_non_unlim == match_hslab->num_elem_non_unlim); + + /* Calculate number of slices */ + num_slices = match_space->select.num_elem / match_hslab->num_elem_non_unlim; + + if(num_slices == 0) + *clip_space_unlim_extent = 0; + else if(clip_hslab->opt_unlim_diminfo[clip_hslab->unlim_dim].block == H5S_UNLIMITED) { + HDassert(0 && "Checking code coverage..."); //VDSINC + /* Unlimited block, just set the extent large enough for the block size + * to match num_slices */ + HDassert(clip_hslab->opt_unlim_diminfo[clip_hslab->unlim_dim].count == (hsize_t)1); + + *clip_space_unlim_extent = + clip_hslab->opt_unlim_diminfo[clip_hslab->unlim_dim].start + + num_slices; + } /* end if */ + else { + /* Unlimited count, need to match extent so a block (possibly) gets cut + * off so the number of slices matches num_slices */ + HDassert(clip_hslab->opt_unlim_diminfo[clip_hslab->unlim_dim].count == H5S_UNLIMITED); + + /* Calculate number of complete blocks in clip_space */ + count = num_slices / clip_hslab->opt_unlim_diminfo[clip_hslab->unlim_dim].block; + + /* Calculate slices remaining */ + rem_slices = num_slices - (count + * clip_hslab->opt_unlim_diminfo[clip_hslab->unlim_dim].block); + + if(rem_slices > 0) { + HDassert(0 && "Checking code coverage..."); //VDSINC + /* Must end extent in middle of partial block */ + *clip_space_unlim_extent = + clip_hslab->opt_unlim_diminfo[clip_hslab->unlim_dim].start + + (count + * clip_hslab->opt_unlim_diminfo[clip_hslab->unlim_dim].stride) + + rem_slices; + } //VDSINC + else + /* End extent at end of last block */ + *clip_space_unlim_extent = + clip_hslab->opt_unlim_diminfo[clip_hslab->unlim_dim].start + + ((count - (hsize_t)1) + * clip_hslab->opt_unlim_diminfo[clip_hslab->unlim_dim].stride) + + clip_hslab->opt_unlim_diminfo[clip_hslab->unlim_dim].block; + } /* end else */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5S_hyper_get_clip_extent() */ /*-------------------------------------------------------------------------- diff --git a/src/H5Snone.c b/src/H5Snone.c index 11c4912..e9ea5e1 100644 --- a/src/H5Snone.c +++ b/src/H5Snone.c @@ -46,6 +46,7 @@ static herr_t H5S_none_deserialize(const H5F_t *f, H5S_t *space, uint32_t version, uint8_t flags, const uint8_t **p); static herr_t H5S_none_bounds(const H5S_t *space, hsize_t *start, hsize_t *end); static herr_t H5S_none_offset(const H5S_t *space, hsize_t *off); +static int H5S_none_unlim_dim(const H5S_t *space); static htri_t H5S_none_is_contiguous(const H5S_t *space); static htri_t H5S_none_is_single(const H5S_t *space); static htri_t H5S_none_is_regular(const H5S_t *space); @@ -77,6 +78,7 @@ const H5S_select_class_t H5S_sel_none[1] = {{ H5S_none_deserialize, H5S_none_bounds, H5S_none_offset, + H5S_none_unlim_dim, H5S_none_is_contiguous, H5S_none_is_single, H5S_none_is_regular, @@ -613,6 +615,31 @@ H5S_none_offset(const H5S_t UNUSED *space, hsize_t UNUSED *offset) /*-------------------------------------------------------------------------- NAME + H5S_none_unlim_dim + PURPOSE + Return unlimited dimension of selection, or -1 if none + USAGE + VDSINC + RETURNS + Unlimited dimension of selection, or -1 if none (never fails). + DESCRIPTION + VDSINC + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static int +H5S_none_unlim_dim(const H5S_t UNUSED *space) +{ + FUNC_ENTER_NOAPI_NOERR + + FUNC_LEAVE_NOAPI(-1) +} /* end H5S_none_unlim_dim() */ + + +/*-------------------------------------------------------------------------- + NAME H5S_none_is_contiguous PURPOSE Check if a "none" selection is contiguous within the dataspace extent. diff --git a/src/H5Spkg.h b/src/H5Spkg.h index e28c118..226edf1 100644 --- a/src/H5Spkg.h +++ b/src/H5Spkg.h @@ -124,6 +124,7 @@ typedef struct { * contains H5S_UNLIMITED in the count or block of the unlimited * dimension (if any). */ int unlim_dim; /* Dimension where selection is unlimited, or -1 if none */ + hsize_t unlim_dim_clip_size; /* Size to which the selection is clipped in unlimited dimension */ hsize_t num_elem_non_unlim; /* # of elements in a "slice" excluding the unlimited dimension */ H5S_hyper_span_info_t *span_lst; /* List of hyperslab span information */ } H5S_hyper_sel_t; @@ -151,6 +152,8 @@ typedef herr_t (*H5S_sel_deserialize_func_t)(const H5F_t *f, H5S_t *space, typedef herr_t (*H5S_sel_bounds_func_t)(const H5S_t *space, hsize_t *start, hsize_t *end); /* Method to determine linear offset of initial element in selection within dataspace */ 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 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 */ @@ -180,6 +183,7 @@ typedef struct { H5S_sel_deserialize_func_t deserialize; /* Method to store create selection from "serialized" form (a byte sequence suitable for storing on disk) */ 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_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" */ @@ -268,7 +272,6 @@ H5_DLL herr_t H5S_extent_copy_real(H5S_extent_t *dst, const H5S_extent_t *src, H5_DLL herr_t H5S__hyper_project_intersection(const H5S_t *src_space, const H5S_t *dst_space, const H5S_t *src_intersect_space, H5S_t *proj_space); -H5_DLL herr_t H5S__hyper_update_extent_offset(H5S_t *space); /* Testing functions */ #ifdef H5S_TESTING diff --git a/src/H5Spoint.c b/src/H5Spoint.c index a7421de..50b8550 100644 --- a/src/H5Spoint.c +++ b/src/H5Spoint.c @@ -47,6 +47,7 @@ static herr_t H5S_point_deserialize(const H5F_t *f, H5S_t *space, uint32_t version, uint8_t flags, const uint8_t **p); static herr_t H5S_point_bounds(const H5S_t *space, hsize_t *start, hsize_t *end); static herr_t H5S_point_offset(const H5S_t *space, hsize_t *off); +static int H5S_point_unlim_dim(const H5S_t *space); static htri_t H5S_point_is_contiguous(const H5S_t *space); static htri_t H5S_point_is_single(const H5S_t *space); static htri_t H5S_point_is_regular(const H5S_t *space); @@ -78,6 +79,7 @@ const H5S_select_class_t H5S_sel_point[1] = {{ H5S_point_deserialize, H5S_point_bounds, H5S_point_offset, + H5S_point_unlim_dim, H5S_point_is_contiguous, H5S_point_is_single, H5S_point_is_regular, @@ -1189,6 +1191,31 @@ done: /*-------------------------------------------------------------------------- NAME + H5S_point_unlim_dim + PURPOSE + Return unlimited dimension of selection, or -1 if none + USAGE + VDSINC + RETURNS + Unlimited dimension of selection, or -1 if none (never fails). + DESCRIPTION + VDSINC + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static int +H5S_point_unlim_dim(const H5S_t UNUSED *space) +{ + FUNC_ENTER_NOAPI_NOERR + + FUNC_LEAVE_NOAPI(-1) +} /* end H5S_point_unlim_dim() */ + + +/*-------------------------------------------------------------------------- + NAME H5S_point_is_contiguous PURPOSE Check if a point selection is contiguous within the dataspace extent. diff --git a/src/H5Sprivate.h b/src/H5Sprivate.h index 8f9b530..ebfa88e 100644 --- a/src/H5Sprivate.h +++ b/src/H5Sprivate.h @@ -218,6 +218,7 @@ H5_DLL htri_t H5S_select_valid(const H5S_t *space); 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_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); @@ -265,6 +266,10 @@ H5_DLL htri_t H5S_hyper_intersect_block (H5S_t *space, hsize_t *start, hsize_t * H5_DLL herr_t H5S_hyper_adjust_s(H5S_t *space, const hssize_t *offset); H5_DLL htri_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); +H5_DLL herr_t H5S_hyper_clip_unlim(H5S_t *space, hsize_t clip_size); +H5_DLL herr_t H5S_hyper_clip_to_extent(H5S_t *space); +H5_DLL herr_t H5S_hyper_get_clip_extent(const H5S_t *clip_space, + const H5S_t *match_space, hsize_t *clip_space_unlim_extent); /* 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/src/H5Sselect.c b/src/H5Sselect.c index 52273c7..b22ea64 100644 --- a/src/H5Sselect.c +++ b/src/H5Sselect.c @@ -81,7 +81,7 @@ H5S_select_offset(H5S_t *space, const hssize_t *offset) /* If the selection is 'hyper', update the selection due to changed offset */ if(H5S_GET_SELECT_TYPE(space) == H5S_SEL_HYPERSLABS) - if(H5S__hyper_update_extent_offset(space) < 0) + if(H5S_hyper_clip_to_extent(space) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't update hyperslab") done: @@ -699,6 +699,44 @@ H5S_get_select_offset(const H5S_t *space, hsize_t *offset) /*-------------------------------------------------------------------------- NAME + H5S_get_select_unlim_dim + PURPOSE + Gets the unlimited dimension in the selection, or -1 if there is no + unlimited dimension. + USAGE + int H5S_get_select_unlim_dim(space) + const H5S_t *space; IN: Dataspace pointer of selection to query + RETURNS + Unlimited dimension in the selection, or -1 if there is no unlimited + dimension (never fails) + DESCRIPTION + Gets the unlimited dimension in the selection, or -1 if there is no + unlimited dimension. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + Currently only implemented for hyperslab selections, all others + simply return -1. + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +int +H5S_get_select_unlim_dim(const H5S_t *space) +{ + herr_t ret_value; /* return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + /* Check args */ + HDassert(space); + + ret_value = (*space->select.type->unlim_dim)(space); + + 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 -- cgit v0.12