From bfc69905acab1727260af74efa0b119a119ddc6b Mon Sep 17 00:00:00 2001 From: Neil Fortner Date: Mon, 9 Mar 2015 16:59:50 -0500 Subject: [svn-r26411] Add support for I/O in very simple cases (virtual mapping and file space are both H5S_ALL). Note make check fails in h5dump test (unrelated to this checkin). Tested: ummon --- src/H5D.c | 44 ++--------- src/H5Dint.c | 80 ++++++++++++++++++- src/H5Dio.c | 5 +- src/H5Dpkg.h | 5 ++ src/H5Dvirtual.c | 235 +++++++++++++++++++++++++++++++++++++++++++++++++++---- src/H5Pdcpl.c | 2 + src/H5Sprivate.h | 3 + src/H5Sselect.c | 93 ++++++++++++++++++++++ test/Makefile.am | 2 +- test/vds.c | 215 +++++++++++++++++++++++++++++++++++++++++++++++++- 10 files changed, 626 insertions(+), 58 deletions(-) diff --git a/src/H5D.c b/src/H5D.c index a81fb8b..d19e3a6 100644 --- a/src/H5D.c +++ b/src/H5D.c @@ -323,14 +323,9 @@ hid_t H5Dopen2(hid_t loc_id, const char *name, hid_t dapl_id) { H5D_t *dset = NULL; - H5G_loc_t loc; /* Object location of group */ - H5G_loc_t dset_loc; /* Object location of dataset */ - H5G_name_t path; /* Dataset group hier. path */ - H5O_loc_t oloc; /* Dataset object location */ - H5O_type_t obj_type; /* Type of object at location */ - hbool_t loc_found = FALSE; /* Location at 'name' found */ - hid_t dxpl_id = H5AC_dxpl_id; /* dxpl to use to open datset */ - hid_t ret_value; + H5G_loc_t loc; /* Object location of group */ + hid_t dxpl_id = H5AC_dxpl_id; /* dxpl to use to open datset */ + hid_t ret_value; FUNC_ENTER_API(FAIL) H5TRACE3("i", "i*si", loc_id, name, dapl_id); @@ -348,41 +343,18 @@ H5Dopen2(hid_t loc_id, const char *name, hid_t dapl_id) if(TRUE != H5P_isa_class(dapl_id, H5P_DATASET_ACCESS)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not dataset access property list") - /* Set up dataset location to fill in */ - dset_loc.oloc = &oloc; - dset_loc.path = &path; - H5G_loc_reset(&dset_loc); - - /* Find the dataset object */ - if(H5G_loc_find(&loc, name, &dset_loc, dapl_id, dxpl_id) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_NOTFOUND, FAIL, "not found") - loc_found = TRUE; - - /* Check that the object found is the correct type */ - if(H5O_obj_type(&oloc, &obj_type, dxpl_id) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get object type") - if(obj_type != H5O_TYPE_DATASET) - HGOTO_ERROR(H5E_DATASET, H5E_BADTYPE, FAIL, "not a dataset") - /* Open the dataset */ - if(NULL == (dset = H5D_open(&dset_loc, dapl_id, dxpl_id))) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't open dataset") + if(NULL == (dset = H5D__open_name(&loc, name, dapl_id, dxpl_id))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "unable to open dataset") /* Register an atom for the dataset */ if((ret_value = H5I_register(H5I_DATASET, dset, TRUE)) < 0) HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "can't register dataset atom") done: - if(ret_value < 0) { - if(dset) { - if(H5D_close(dset) < 0) - HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release dataset") - } /* end if */ - else { - if(loc_found && H5G_loc_free(&dset_loc) < 0) - HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "can't free location") - } /* end else */ - } /* end if */ + if(ret_value < 0) + if(dset && H5D_close(dset) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release dataset") FUNC_LEAVE_API(ret_value) } /* end H5Dopen2() */ diff --git a/src/H5Dint.c b/src/H5Dint.c index 5035a67..a36b8b3 100644 --- a/src/H5Dint.c +++ b/src/H5Dint.c @@ -1105,6 +1105,69 @@ done: } /* end H5D__create() */ +/*------------------------------------------------------------------------- + * Function: H5D__open_name + * + * Purpose: Opens an existing dataset by name. + * + * Return: Success: Ptr to a new dataset. + * Failure: NULL + * + * Programmer: Neil Fortner + * Friday, March 6, 2015 + * + *------------------------------------------------------------------------- + */ +H5D_t * +H5D__open_name(const H5G_loc_t *loc, const char *name, hid_t dapl_id, + hid_t dxpl_id) +{ + H5D_t *dset = NULL; + H5G_loc_t dset_loc; /* Object location of dataset */ + H5G_name_t path; /* Dataset group hier. path */ + H5O_loc_t oloc; /* Dataset object location */ + H5O_type_t obj_type; /* Type of object at location */ + hbool_t loc_found = FALSE; /* Location at 'name' found */ + H5D_t *ret_value; /* Return value */ + + FUNC_ENTER_PACKAGE + + /* Check args */ + HDassert(loc); + HDassert(name); + + /* Set up dataset location to fill in */ + dset_loc.oloc = &oloc; + dset_loc.path = &path; + H5G_loc_reset(&dset_loc); + + /* Find the dataset object */ + if(H5G_loc_find(loc, name, &dset_loc, dapl_id, dxpl_id) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_NOTFOUND, NULL, "not found") + loc_found = TRUE; + + /* Check that the object found is the correct type */ + if(H5O_obj_type(&oloc, &obj_type, dxpl_id) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, NULL, "can't get object type") + if(obj_type != H5O_TYPE_DATASET) + HGOTO_ERROR(H5E_DATASET, H5E_BADTYPE, NULL, "not a dataset") + + /* Open the dataset */ + if(NULL == (dset = H5D_open(&dset_loc, dapl_id, dxpl_id))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "can't open dataset") + + /* Set return value */ + ret_value = dset; + +done: + if(!ret_value) + if(loc_found && H5G_loc_free(&dset_loc) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, NULL, "can't free location") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D__open_name() */ + + /* *------------------------------------------------------------------------- * Function: H5D_open @@ -1449,8 +1512,21 @@ H5D_close(H5D_t *dataset) break; case H5D_VIRTUAL: - /* Close datasets here? VDSINC */ - break; + { + size_t i; + + HDassert(dataset->shared->layout.storage.u.virt.list || (dataset->shared->layout.storage.u.virt.list_nused == 0)); + + /* Close source datasets */ + for(i = 0; i < dataset->shared->layout.storage.u.virt.list_nused; i++) + if(dataset->shared->layout.storage.u.virt.list[i].source_dset) { + HDassert(dataset->shared->layout.storage.u.virt.list[i].source_dset != dataset); + if(H5D_close(dataset->shared->layout.storage.u.virt.list[i].source_dset) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to close source dataset") + dataset->shared->layout.storage.u.virt.list[i].source_dset = NULL; + } /* end if */ + } /* end block */ + break; case H5D_LAYOUT_ERROR: case H5D_NLAYOUTS: diff --git a/src/H5Dio.c b/src/H5Dio.c index 88f75b1..296e529 100644 --- a/src/H5Dio.c +++ b/src/H5Dio.c @@ -52,9 +52,6 @@ /********************/ /* Internal I/O routines */ -static herr_t H5D__write(H5D_t *dataset, hid_t mem_type_id, - const H5S_t *mem_space, const H5S_t *file_space, hid_t dset_xfer_plist, - const void *buf); static herr_t H5D__pre_write(H5D_t *dset, hbool_t direct_write, hid_t mem_type_id, const H5S_t *mem_space, const H5S_t *file_space, hid_t dxpl_id, const void *buf); @@ -586,7 +583,7 @@ done: * *------------------------------------------------------------------------- */ -static herr_t +herr_t H5D__write(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space, const H5S_t *file_space, hid_t dxpl_id, const void *buf) { diff --git a/src/H5Dpkg.h b/src/H5Dpkg.h index 82c4d2f..d448406 100644 --- a/src/H5Dpkg.h +++ b/src/H5Dpkg.h @@ -536,6 +536,8 @@ H5_DLL H5D_t *H5D__create(H5F_t *file, hid_t type_id, const H5S_t *space, H5_DLL H5D_t *H5D__create_named(const H5G_loc_t *loc, const char *name, hid_t type_id, const H5S_t *space, hid_t lcpl_id, hid_t dcpl_id, hid_t dapl_id, hid_t dxpl_id); +H5_DLL H5D_t *H5D__open_name(const H5G_loc_t *loc, const char *name, + hid_t dapl_id, hid_t dxpl_id); H5_DLL herr_t H5D__get_space_status(H5D_t *dset, H5D_space_status_t *allocation, hid_t dxpl_id); H5_DLL herr_t H5D__alloc_storage(const H5D_t *dset, hid_t dxpl_id, H5D_time_alloc_t time_alloc, @@ -558,6 +560,9 @@ H5_DLL herr_t H5D__flush_real(H5D_t *dataset, hid_t dxpl_id); H5_DLL herr_t H5D__read(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space, const H5S_t *file_space, hid_t dset_xfer_plist, void *buf/*out*/); +H5_DLL herr_t H5D__write(H5D_t *dataset, hid_t mem_type_id, + const H5S_t *mem_space, const H5S_t *file_space, hid_t dset_xfer_plist, + const void *buf); /* Functions that perform direct serial I/O operations */ H5_DLL herr_t H5D__select_read(const H5D_io_info_t *io_info, diff --git a/src/H5Dvirtual.c b/src/H5Dvirtual.c index 1bc4b75..ac7af54 100644 --- a/src/H5Dvirtual.c +++ b/src/H5Dvirtual.c @@ -35,6 +35,7 @@ #include "H5Dpkg.h" /* Dataset functions */ #include "H5Eprivate.h" /* Error handling */ #include "H5Fprivate.h" /* Files */ +#include "H5Gprivate.h" /* Groups */ #include "H5HGprivate.h" /* Global Heaps */ #include "H5MMprivate.h" /* Memory management */ #include "H5Oprivate.h" /* Object headers */ @@ -68,6 +69,10 @@ static herr_t H5D__virtual_write(H5D_io_info_t *io_info, const H5S_t *mem_space, H5D_chunk_map_t *fm); static herr_t H5D__virtual_flush(H5D_t *dset, hid_t dxpl_id); +/* Other functions */ +static htri_t H5D__virtual_open_source_dset(const H5D_t *vdset, + H5O_storage_virtual_ent_t *virtual_ent, hid_t dxpl_id); + /*********************/ /* Package Variables */ @@ -171,6 +176,68 @@ done: /*------------------------------------------------------------------------- + * 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 + * + * Programmer: Neil Fortner + * March 6, 2015 + * + *------------------------------------------------------------------------- + */ +static htri_t +H5D__virtual_open_source_dset(const H5D_t *vdset, + H5O_storage_virtual_ent_t *virtual_ent, hid_t dxpl_id) +{ + H5F_t *src_file = NULL; /* Source file */ + hbool_t src_file_open = FALSE; /* Whether we have opened and need to close src_file */ + H5G_loc_t src_root_loc; /* Object location of source file root group */ + htri_t ret_value = TRUE; /* Return value */ + + FUNC_ENTER_STATIC + + /* Sanity check */ + HDassert(virtual_ent); + HDassert(!virtual_ent->source_dset); + + /* Get dapl and fapl from current (virtual dataset) location? VDSINC */ + /* Write code to check if these exist and return FALSE otherwise VDSINC */ + + /* Check if we need to open the source file */ + if(HDstrcmp(virtual_ent->source_file_name, ".")) { + /* Open the source file */ + if(NULL == (src_file = H5F_open(virtual_ent->source_file_name, H5F_ACC_RDONLY, H5P_FILE_CREATE_DEFAULT, H5P_FILE_ACCESS_DEFAULT, dxpl_id))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENFILE, FAIL, "unable to open source file") + src_file_open = TRUE; + } /* end if */ + else + /* Source file is ".", use the virtual dataset's file */ + src_file = vdset->oloc.file; + + /* Set up the root group in the destination file */ + if(NULL == (src_root_loc.oloc = H5G_oloc(H5G_rootof(src_file)))) + HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "unable to get object location for root group") + if(NULL == (src_root_loc.path = H5G_nameof(H5G_rootof(src_file)))) + HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "unable to get path for root group") + + /* Open the source dataset */ + if(NULL == (virtual_ent->source_dset = H5D__open_name(&src_root_loc, virtual_ent->source_dset_name, H5P_DATASET_ACCESS_DEFAULT, dxpl_id))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "unable to open dataset") + +done: + if(src_file_open) + if(H5F_try_close(src_file) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEFILE, FAIL, "can't close source file") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D__virtual_open_source_dset() */ + + +/*------------------------------------------------------------------------- * Function: H5D__virtual_reset_layout * * Purpose: Frees internal structures in a virtual storage layout @@ -307,7 +374,7 @@ H5D__virtual_is_space_alloc(const H5O_storage_t *storage) /* Need to decide what to do here. For now just return TRUE if the global * heap block has been allocated. VDSINC */ - ret_value = storage->u.virt.serial_list_hobjid.addr != HADDR_UNDEF; + ret_value = TRUE;//storage->u.virt.serial_list_hobjid.addr != HADDR_UNDEF; FUNC_LEAVE_NOAPI(ret_value) } /* end H5D__virtual_is_space_alloc() */ @@ -332,7 +399,7 @@ H5D__virtual_io_init(const H5D_io_info_t UNUSED *io_info, const H5D_type_info_t { FUNC_ENTER_STATIC_NOERR - HDassert(0 && "Not yet implemented...");//VDSINC + /* No-op for now. Delete if we never add anything here. VDSINC */ FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5D__virtual_io_init() */ @@ -350,16 +417,86 @@ H5D__virtual_io_init(const H5D_io_info_t UNUSED *io_info, const H5D_type_info_t * *------------------------------------------------------------------------- */ -herr_t -H5D__virtual_read(H5D_io_info_t UNUSED *io_info, const H5D_type_info_t UNUSED *type_info, - hsize_t UNUSED nelmts, const H5S_t UNUSED *file_space, const H5S_t UNUSED *mem_space, +static herr_t +H5D__virtual_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, + hsize_t UNUSED nelmts, const H5S_t *file_space, const H5S_t *mem_space, H5D_chunk_map_t UNUSED *fm) { - FUNC_ENTER_PACKAGE_NOERR + H5O_storage_virtual_t *storage; /* Convenient pointer into layout struct */ + H5S_t *projected_mem_space = NULL; /* Memory space for selection in a single mapping */ + H5S_t *projected_src_space = NULL; /* File space for selection in a single source dataset */ + hssize_t select_nelmts; /* Number of elements in selection */ + htri_t opened_dset; /* Whether we opened the source dataset */ + size_t i; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + /* Sanity check */ + HDassert(io_info); + HDassert(io_info->u.rbuf); + HDassert(type_info); + HDassert(mem_space); + HDassert(file_space); + + storage = &io_info->dset->shared->layout.storage.u.virt; + + /* Iterate over mappings */ + for(i = 0; i < storage->list_nused; i++) { + /* Project intersection of file space and mapping virtual space onto + * memory space */ + if(H5S_select_project_intersection(file_space, mem_space, storage->list[i].virtual_select, &projected_mem_space) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTCLIP, FAIL, "can't project virtual intersection onto memory space") + + /* Get number of elements in projected dataspace */ + if((select_nelmts = (hssize_t)H5S_GET_SELECT_NPOINTS(projected_mem_space)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTCOUNT, FAIL, "unable to get number of elements in selection") + + /* Only perform I/O if there are any elements */ + if(nelmts > 0) { + /* Open source dataset, fail if cannot open */ + if(!storage->list[i].source_dset) { + if((opened_dset = H5D__virtual_open_source_dset(io_info->dset, &storage->list[i], io_info->dxpl_id)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "unable to open source dataset") + if(!opened_dset) + HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "did not open source dataset") + } /* end if */ + + /* Project intersection of file space and mapping virtual space onto + * mapping source space */ + if(H5S_select_project_intersection(storage->list[i].virtual_select, storage->list[i].source_select, file_space, &projected_src_space) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTCLIP, FAIL, "can't project virtual intersection onto source space") + + /* Perform read on source dataset */ + if(H5D__read(storage->list[i].source_dset, type_info->dst_type_id, projected_mem_space, projected_src_space, io_info->dxpl_id, io_info->u.rbuf) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read source dataset") + + /* Close projected_src_space */ + if(H5S_close(projected_src_space) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "can't close projected source space") + projected_src_space = NULL; + } /* end if */ + + /* Close projected_mem_space */ + if(H5S_close(projected_mem_space) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "can't close projected memory space") + projected_mem_space = NULL; + } /* end for */ - HDassert(0 && "Not yet implemented...");//VDSINC +done: + /* Release allocated resources on failure */ + if(projected_src_space) { + HDassert(ret_value < 0); + if(H5S_close(projected_src_space) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "can't close projected source space") + } /* end if */ + if(projected_mem_space) { + HDassert(ret_value < 0); + if(H5S_close(projected_mem_space) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "can't close projected memory space") + } /* end if */ - FUNC_LEAVE_NOAPI(SUCCEED) + FUNC_LEAVE_NOAPI(ret_value) } /* end H5D__virtual_read() */ @@ -375,16 +512,86 @@ H5D__virtual_read(H5D_io_info_t UNUSED *io_info, const H5D_type_info_t UNUSED *t * *------------------------------------------------------------------------- */ -herr_t -H5D__virtual_write(H5D_io_info_t UNUSED *io_info, const H5D_type_info_t UNUSED *type_info, - hsize_t UNUSED nelmts, const H5S_t UNUSED *file_space, const H5S_t UNUSED *mem_space, +static herr_t +H5D__virtual_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, + hsize_t UNUSED nelmts, const H5S_t *file_space, const H5S_t *mem_space, H5D_chunk_map_t UNUSED *fm) { - FUNC_ENTER_PACKAGE_NOERR + H5O_storage_virtual_t *storage; /* Convenient pointer into layout struct */ + H5S_t *projected_mem_space = NULL; /* Memory space for selection in a single mapping */ + H5S_t *projected_src_space = NULL; /* File space for selection in a single source dataset */ + hssize_t select_nelmts; /* Number of elements in selection */ + htri_t opened_dset; /* Whether we opened the source dataset */ + size_t i; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + /* Sanity check */ + HDassert(io_info); + HDassert(io_info->u.rbuf); + HDassert(type_info); + HDassert(mem_space); + HDassert(file_space); + + storage = &io_info->dset->shared->layout.storage.u.virt; + + /* Iterate over mappings */ + for(i = 0; i < storage->list_nused; i++) { + /* Project intersection of file space and mapping virtual space onto + * memory space */ + if(H5S_select_project_intersection(file_space, mem_space, storage->list[i].virtual_select, &projected_mem_space) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTCLIP, FAIL, "can't project virtual intersection onto memory space") + + /* Get number of elements in projected dataspace */ + if((select_nelmts = (hssize_t)H5S_GET_SELECT_NPOINTS(projected_mem_space)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTCOUNT, FAIL, "unable to get number of elements in selection") + + /* Only perform I/O if there are any elements */ + if(nelmts > 0) { + /* Open source dataset, fail if cannot open */ + if(!storage->list[i].source_dset) { + if((opened_dset = H5D__virtual_open_source_dset(io_info->dset, &storage->list[i], io_info->dxpl_id)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "unable to open source dataset") + if(!opened_dset) + HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "did not open source dataset") + } /* end if */ + + /* Project intersection of file space and mapping virtual space onto + * mapping source space */ + if(H5S_select_project_intersection(storage->list[i].virtual_select, storage->list[i].source_select, file_space, &projected_src_space) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTCLIP, FAIL, "can't project virtual intersection onto source space") + + /* Perform read on source dataset */ + if(H5D__write(storage->list[i].source_dset, type_info->dst_type_id, projected_mem_space, projected_src_space, io_info->dxpl_id, io_info->u.wbuf) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write to source dataset") + + /* Close projected_src_space */ + if(H5S_close(projected_src_space) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "can't close projected source space") + projected_src_space = NULL; + } /* end if */ + + /* Close projected_mem_space */ + if(H5S_close(projected_mem_space) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "can't close projected memory space") + projected_mem_space = NULL; + } /* end for */ - HDassert(0 && "Not yet implemented...");//VDSINC +done: + /* Release allocated resources on failure */ + if(projected_src_space) { + HDassert(ret_value < 0); + if(H5S_close(projected_src_space) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "can't close projected source space") + } /* end if */ + if(projected_mem_space) { + HDassert(ret_value < 0); + if(H5S_close(projected_mem_space) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "can't close projected memory space") + } /* end if */ - FUNC_LEAVE_NOAPI(SUCCEED) + FUNC_LEAVE_NOAPI(ret_value) } /* end H5D__virtual_write() */ diff --git a/src/H5Pdcpl.c b/src/H5Pdcpl.c index de3ab86..9c5833d 100644 --- a/src/H5Pdcpl.c +++ b/src/H5Pdcpl.c @@ -1615,6 +1615,8 @@ H5Pset_virtual(hid_t dcpl_id, hid_t vspace_id, const char *src_file_name, if(NULL == (src_space = (H5S_t *)H5I_object_verify(src_space_id, H5I_DATASPACE))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace") + //VDSINC add check for overlaping virtual spaces + #ifndef H5_HAVE_C99_DESIGNATED_INITIALIZER /* If the compiler doesn't support C99 designated initializers, check if * the default layout structs have been initialized yet or not. *ick* -QAK diff --git a/src/H5Sprivate.h b/src/H5Sprivate.h index 7cb5285..6ce2821 100644 --- a/src/H5Sprivate.h +++ b/src/H5Sprivate.h @@ -235,6 +235,9 @@ H5_DLL htri_t H5S_select_is_regular(const H5S_t *space); H5_DLL herr_t H5S_select_adjust_u(H5S_t *space, const hsize_t *offset); H5_DLL herr_t H5S_select_project_scalar(const H5S_t *space, hsize_t *offset); H5_DLL herr_t H5S_select_project_simple(const H5S_t *space, H5S_t *new_space, hsize_t *offset); +H5_DLL herr_t H5S_select_project_intersection(const H5S_t *src_space, + const H5S_t *dst_space, const H5S_t *src_intersect_space, + H5S_t **new_space_ptr); /* Operations on all selections */ H5_DLL herr_t H5S_select_all(H5S_t *space, hbool_t rel_prev); diff --git a/src/H5Sselect.c b/src/H5Sselect.c index a4f13d7..4085e7f 100644 --- a/src/H5Sselect.c +++ b/src/H5Sselect.c @@ -2101,3 +2101,96 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* H5S_select_fill() */ + +/*-------------------------------------------------------------------------- + NAME + H5S_select_project_intersection + + PURPOSE + VDSINC + + USAGE + VDSINC + + RETURNS + Non-negative on success/Negative on failure. + + DESCRIPTION + VDSINC + + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5S_select_project_intersection(const H5S_t *src_space, const H5S_t *dst_space, + const H5S_t *src_intersect_space, H5S_t **new_space_ptr) +{ + H5S_t *new_space = NULL; /* New dataspace constructed */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity checks */ + HDassert(src_space); + HDassert(dst_space); + HDassert(src_intersect_space); + HDassert(new_space_ptr); + + /* Create new space, using dst extent. Start wil "all" selection. */ + if(NULL == (new_space = H5S_create(H5S_SIMPLE))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "unable to create output dataspace") + if(H5S_extent_copy_real(&new_space->extent, &dst_space->extent, TRUE) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy destination space extent") + + /* Check intersecting space's selection type */ + switch(src_intersect_space->select.type->type) { + case H5S_SEL_NONE: + /* Since the intersecting space is "none", the intersection has no + * selection and so does the projection. Change to "none" selection + */ + if(H5S_select_none(new_space) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection") + + break; + + case H5S_SEL_POINTS: + HDassert(0 && "Not yet implemented...");//VDSINC + + break; + + case H5S_SEL_HYPERSLABS: + HDassert(0 && "Not yet implemented...");//VDSINC + + break; + + case H5S_SEL_ALL: + /* Since the intersecting space is "all", the intersection must be + * equal to the source space and the projection must be equal to the + * destination space. Copy the destination selection. + */ + if(H5S_select_copy(new_space, dst_space, FALSE) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy destination space selection") + + break; + + case H5S_SEL_ERROR: + case H5S_SEL_N: + default: + HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "invalid source dataspace selection type") + } /* end switch */ + + /* load the address of the new space into *new_space_ptr */ + *new_space_ptr = new_space; + +done: + /* Cleanup on error */ + if(ret_value < 0) { + if(new_space && H5S_close(new_space) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace") + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5S_select_project_intersection() */ + diff --git a/test/Makefile.am b/test/Makefile.am index 1546288..e45fbd3 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -151,7 +151,7 @@ CHECK_CLEANFILES+=accum.h5 cmpd_dset.h5 compact_dataset.h5 dataset.h5 dset_offse new_multi_file_v16-r.h5 new_multi_file_v16-s.h5 \ split_get_file_image_test-m.h5 split_get_file_image_test-r.h5 \ file_image_core_test.h5.copy unregister_filter_1.h5 unregister_filter_2.h5 \ - vds_1.h5 + vds_[1-2].h5 # Sources for testhdf5 executable testhdf5_SOURCES=testhdf5.c tarray.c tattr.c tchecksum.c tconfig.c tfile.c \ diff --git a/test/vds.c b/test/vds.c index 039bdc1..7376fb8 100644 --- a/test/vds.c +++ b/test/vds.c @@ -34,9 +34,15 @@ typedef enum { const char *FILENAME[] = { "vds_1", + "vds_2", NULL }; +/* I/O test config flags */ +#define TEST_IO_CLOSE_SRC 0x01u +#define TEST_IO_DIFFERENT_FILE 0x02u +#define TEST_IO_NTESTS 0x04u + #define LIST_DOUBLE_SIZE (H5D_VIRTUAL_DEF_LIST_SIZE + 1) #define FILENAME_BUF_SIZE 1024 @@ -848,7 +854,7 @@ test_api(test_api_config_t config, hid_t fapl) /* - * Test X: Enough Selections to trigger doubling of mapping list + * Test 6: Enough Selections to trigger doubling of mapping list */ /* Clear virtual layout in DCPL */ if(H5Pset_layout(dcpl, H5D_VIRTUAL) < 0) @@ -964,6 +970,208 @@ error: /*------------------------------------------------------------------------- + * Function: test_basic_io + * + * Purpose: Tests VDS I/O without unlimited selections or + * pattern-matching file/dataset strings + * + * Return: Success: 0 + * + * Failure: number of errors + * + * Programmer: Neil Fortner + * Tuesday, March 3, 2015 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +test_basic_io(unsigned config, hid_t fapl) +{ + char srcfilename[FILENAME_BUF_SIZE]; + char vfilename[FILENAME_BUF_SIZE]; + hid_t srcfile[4] = {-1, -1, -1, -1}; /* Files with source dsets */ + hid_t vfile = -1; /* File with virtual dset */ + hid_t dcpl = -1; /* Dataset creation property list */ + hid_t srcspace[4] = {-1, -1, -1, -1}; /* Source dataspaces */ + hid_t vspace[4] = {-1, -1, -1, -1}; /* Virtual dset dataspaces */ + hid_t srcdset[4] = {-1, -1, -1, -1}; /* Source datsets */ + hid_t vdset = -1; /* Virtual dataset */ + hsize_t dims[2] = {10, 20}; /* Data space current size */ + hsize_t start[2]; /* Hyperslab start */ + hsize_t stride[2]; /* Hyperslab stride */ + hsize_t count[2]; /* Hyperslab count */ + hsize_t block[2]; /* Hyperslab block */ + hsize_t coord[10]; /* Point selection array */ + int buf[10][20]; /* Write and expecte read buffer */ + int rbuf[10][20]; /* Read buffer */ + int i, j; + + TESTING("basic virtual dataset I/O") + + h5_fixname(FILENAME[0], fapl, vfilename, sizeof vfilename); + h5_fixname(FILENAME[1], fapl, srcfilename, sizeof srcfilename); + + /* Create DCPL */ + if((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0) + TEST_ERROR + + /* + * Test 1: All - all selection + */ + /* Create source dataspace */ + if((srcspace[0] = H5Screate_simple(2, dims, NULL)) < 0) + TEST_ERROR + + /* Create virtual dataspace */ + if((vspace[0] = H5Screate_simple(2, dims, NULL)) < 0) + TEST_ERROR + + /* Select all (should not be necessary, but just to be sure) */ + if(H5Sselect_all(srcspace[0]) < 0) + TEST_ERROR + if(H5Sselect_all(vspace[0]) < 0) + TEST_ERROR + + /* Add virtual layout mapping */ + if(H5Pset_virtual(dcpl, vspace[0], config & TEST_IO_DIFFERENT_FILE ? srcfilename : ".", "src_dset", srcspace[0]) < 0) + TEST_ERROR + + /* Create virtual file */ + if((vfile = H5Fcreate(vfilename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + TEST_ERROR + + /* Create source file if requested */ + if(config & TEST_IO_DIFFERENT_FILE) { + if((srcfile[0] = H5Fcreate(srcfilename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + TEST_ERROR + } /* end if */ + else { + srcfile[0] = vfile; + if(H5Iinc_ref(srcfile[0]) < 0) + TEST_ERROR + } /* end if */ + + /* Create source dataset */ + if((srcdset[0] = H5Dcreate2(srcfile[0], "src_dset", H5T_NATIVE_INT, srcspace[0], H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) + TEST_ERROR + + /* Create virtual dataset */ + if((vdset = H5Dcreate2(vfile, "v_dset", H5T_NATIVE_INT, vspace[0], H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0) + TEST_ERROR + + /* Populate write buffer */ + for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++) + for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++) + buf[i][j] = (i * (int)(sizeof(buf[0]) / sizeof(buf[0][0]))) + j; + + /* Write data directly to source dataset */ + if(H5Dwrite(srcdset[0], H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf[0]) < 0) + TEST_ERROR + + /* Close srcdset if config option specified */ + if(config & TEST_IO_CLOSE_SRC) { + if(H5Dclose(srcdset[0]) < 0) + TEST_ERROR + srcdset[0] = -1; + } /* end if */ + + /* Read data through virtual dataset */ + HDmemset(rbuf[0], 0, sizeof(rbuf)); + if(H5Dread(vdset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, rbuf[0]) < 0) + TEST_ERROR + + /* Verify read data */ + for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++) + for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++) + if(rbuf[i][j] != buf[i][j]) + TEST_ERROR + + /* Adjust write buffer */ + for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++) + for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++) + buf[i][j] += (int)(sizeof(buf) / sizeof(buf[0][0])); + + /* Write data through virtual dataset */ + if(H5Dwrite(vdset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf[0]) < 0) + TEST_ERROR + + /* Reopen srcdset if config option specified */ + if(config & TEST_IO_CLOSE_SRC) + if((srcdset[0] = H5Dopen2(srcfile[0], "src_dset", H5P_DEFAULT)) < 0) + TEST_ERROR + + /* Read data directly from source dataset */ + HDmemset(rbuf[0], 0, sizeof(rbuf)); + if(H5Dread(srcdset[0], H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, rbuf[0]) < 0) + TEST_ERROR + + /* Verify read data */ + for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++) + for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++) + if(rbuf[i][j] != buf[i][j]) + TEST_ERROR + + /* Close */ + if(H5Dclose(srcdset[0]) < 0) + TEST_ERROR + srcdset[0] = -1; + if(H5Dclose(vdset) < 0) + TEST_ERROR + vdset = -1; + if(H5Fclose(srcfile[0]) < 0) + TEST_ERROR + if(H5Fclose(vfile) < 0) + TEST_ERROR + vfile = -1; + if(H5Sclose(srcspace[0]) < 0) + TEST_ERROR + srcspace[0] = -1; + if(H5Sclose(vspace[0]) < 0) + TEST_ERROR + vspace[0] = -1; + + + /* Close */ + if(H5Pclose(dcpl) < 0) + TEST_ERROR + dcpl = -1; + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + for(i = 0; i < (int)(sizeof(srcdset) / sizeof(srcdset[0])); i++) { + if(srcdset[i] >= 0) + (void)H5Dclose(srcdset[i]); + } /* end for */ + if(vdset >= 0) + (void)H5Dclose(vdset); + for(i = 0; i < (int)(sizeof(srcfile) / sizeof(srcfile[0])); i++) { + if(srcfile[i] >= 0) + (void)H5Fclose(srcfile[i]); + } /* end for */ + if(vfile >= 0) + (void)H5Fclose(vfile); + for(i = 0; i < (int)(sizeof(srcspace) / sizeof(srcspace[0])); i++) { + if(srcspace[i] >= 0) + (void)H5Sclose(srcspace[i]); + } /* end for */ + for(i = 0; i < (int)(sizeof(vspace) / sizeof(vspace[0])); i++) { + if(vspace[i] >= 0) + (void)H5Sclose(vspace[i]); + } /* end for */ + if(dcpl >= 0) + (void)H5Pclose(dcpl); + } H5E_END_TRY; + + return 1; +} /* end test_basic_io() */ + + +/*------------------------------------------------------------------------- * Function: main * * Purpose: Tests datasets with virtual layout @@ -983,6 +1191,7 @@ main(void) char filename[FILENAME_BUF_SIZE]; hid_t fapl; int test_api_config; + unsigned bit_config; int nerrors = 0; /* Testing setup */ @@ -993,6 +1202,10 @@ main(void) for(test_api_config = (int)TEST_API_BASIC; test_api_config < (int)TEST_API_NTESTS; test_api_config++) nerrors += test_api((test_api_config_t)test_api_config, fapl); + for(bit_config = 0; bit_config < TEST_IO_NTESTS; bit_config++) { + printf("Config: %s%s\n", bit_config & TEST_IO_CLOSE_SRC ? "closed source dataset, " : "", bit_config & TEST_IO_DIFFERENT_FILE ? "different source file" : "same source file"); + nerrors += test_basic_io(bit_config, fapl); + } /* end for */ /* Verify symbol table messages are cached */ nerrors += (h5_verify_cached_stabs(FILENAME, fapl) < 0 ? 1 : 0); -- cgit v0.12