diff options
Diffstat (limited to 'src/H5Dvirtual.c')
-rw-r--r-- | src/H5Dvirtual.c | 271 |
1 files changed, 266 insertions, 5 deletions
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 */ |