summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeil Fortner <nfortne2@hdfgroup.org>2015-04-29 03:22:55 (GMT)
committerNeil Fortner <nfortne2@hdfgroup.org>2015-04-29 03:22:55 (GMT)
commita9b2e360653988b417f390e0a66d486fa775f3a2 (patch)
treea80cb2c83dab88061999f05911ae6b98ea3f4cdc
parentf3f74731619798b8e802987b01266348f1fbc027 (diff)
downloadhdf5-a9b2e360653988b417f390e0a66d486fa775f3a2.zip
hdf5-a9b2e360653988b417f390e0a66d486fa775f3a2.tar.gz
hdf5-a9b2e360653988b417f390e0a66d486fa775f3a2.tar.bz2
[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
-rw-r--r--examples/h5_vds-percival-unlim.c10
-rw-r--r--src/H5Dint.c7
-rw-r--r--src/H5Dpkg.h2
-rw-r--r--src/H5Dprivate.h3
-rw-r--r--src/H5Dvirtual.c271
-rw-r--r--src/H5Olayout.c15
-rw-r--r--src/H5Oprivate.h8
-rw-r--r--src/H5Pdcpl.c29
-rw-r--r--src/H5S.c26
-rw-r--r--src/H5Sall.c27
-rw-r--r--src/H5Shyper.c248
-rw-r--r--src/H5Snone.c27
-rw-r--r--src/H5Spkg.h5
-rw-r--r--src/H5Spoint.c27
-rw-r--r--src/H5Sprivate.h5
-rw-r--r--src/H5Sselect.c40
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 <stdio.h>
#include <stdlib.h>
-#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; u<space->extent.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