Compare commits

...

25 Commits

Author SHA1 Message Date
M. Scot Breitenfeld
35c9af8371 Merge branch 'develop' into parallel_vds_develop 2019-06-25 12:39:35 -05:00
M. Scot Breitenfeld
c752332bfd Merge branch 'develop' into parallel_vds_develop 2019-02-08 12:00:14 -06:00
M. Scot Breitenfeld
602bdd1c6a Merge branch 'develop' into parallel_vds_develop 2019-01-02 10:55:37 -06:00
M. Scot Breitenfeld
3e445ef129 Merge branch 'develop' into parallel_vds_develop 2018-12-12 09:43:05 -06:00
Scot Breitenfeld
e14ec4276e Removed libverbounds set, it was remove in develop. 2018-12-05 09:00:22 -06:00
Scot Breitenfeld
291cd766bc Merge branch 'develop' into parallel_vds_develop 2018-12-04 10:47:53 -06:00
Neil Fortner
b27f981ea6 Fix uninitialized variable warning. Extend t_pvds to test different
source file without reopening the virtual dataset (except where
necessary).
2018-08-07 16:07:01 -05:00
Neil Fortner
0cc1d7d781 Fix error in MPIO file comparison. Modify H5F_sfile_search to always
pass the base file first to the comparison callback so the base file's
communicator is used for the broadcast.  Modify t_pvds to avoid
situations that won't work with the new scheme for opening source files
independently.
2018-08-06 17:56:36 -05:00
Neil Fortner
d007267f1b Modify VDS to open source files using the SEC2 driver when the VDS file
is openend in parallel.  Disable file locking on these source files.
Add independent read test to t_psubfile (from Richard).  Various
cleanup, etc.
2018-08-02 16:34:15 -05:00
Richard Warren
f7a62775c1 Fix spelling typo in the RELEASE.txt notes 2018-07-18 16:44:14 -04:00
Richard Warren
439de0afcc Addresses issues raised by Allen in PR review 2018-07-18 15:26:43 -04:00
Richard Warren
37ff3a38cc Use a basic VDS example from the documentation with parallel extensions 2018-07-17 18:12:53 -04:00
Richard Warren
de64afbd39 Merge branch 'develop' of https://bitbucket.hdfgroup.org/scm/hdffv/hdf5 into parallel_vds_develop 2018-07-17 18:06:05 -04:00
Richard Warren
8e4cb935fc Merge branch 'develop' of https://bitbucket.hdfgroup.org/scm/hdffv/hdf5 into parallel_vds_develop 2018-07-17 07:56:19 -04:00
Richard Warren
963954e756 Merge branch 'develop' of https://bitbucket.hdfgroup.org/scm/hdffv/hdf5 into parallel_vds_develop 2018-07-16 07:47:29 -04:00
Richard Warren
1657e0324d Merge branch 'develop' of https://bitbucket.hdfgroup.org/scm/hdffv/hdf5 into parallel_vds_develop 2018-07-13 20:31:31 -04:00
Richard Warren
c946c72a30 Added skeleton-code for subfiling test. NOT Functional at this point. Commit only for sharing purposes. 2018-07-11 10:42:22 -04:00
Richard Warren
6ad9585342 Fix some commentary around the H5FD_mpio_cmp function and remove test_printf and test_all from testpar/t_pvds.c to remove issues with testing printf style parallel VDS. 2018-07-05 16:30:08 -04:00
Richard Warren
5ce8d5da40 Addresses the PR issues raised by Neil. 2018-07-02 08:52:30 -04:00
Richard Warren
e3a6bcc87a Merge branch 'develop' of https://bitbucket.hdfgroup.org/scm/hdffv/hdf5 into parallel_vds_develop 2018-07-02 08:06:38 -04:00
Richard Warren
38ebfd7f4d Made code updates to reflect John Mainzer's comments. Also made a change unrelated to parallel vds, i.e. changed one instance of MPI_Type_extent to MPI_Type_get_extent to remove deprecated errors reported by OpenMPI 3.1 2018-06-14 20:24:11 -04:00
Richard Warren
8d7d1f1ab6 Merge branch 'develop' of https://bitbucket.hdfgroup.org/scm/hdffv/hdf5 into parallel_vds_develop 2018-06-14 19:28:48 -04:00
Richard Warren
9b23d85f51 Add some merge changes to bring the PR changes up to date. Includes removal of H5D__virtual_insert_gh_obj in favor of a merged version of H5D__virtual_store_layout 2018-06-11 19:53:41 -04:00
Richard Warren
2a24cb0d0f Merge branch 'develop' of https://bitbucket.hdfgroup.org/scm/hdffv/hdf5 into parallel_vds_develop 2018-05-31 10:02:46 -04:00
Richard Warren
de129217a4 Rebase parallel VDS work to develop branch for testing and review 2018-05-30 16:21:46 -04:00
15 changed files with 8319 additions and 47 deletions

View File

@@ -1315,6 +1315,8 @@
./testpar/t_shapesame.c
./testpar/t_pshutdown.c
./testpar/t_prestart.c
./testpar/t_psubfile.c
./testpar/t_pvds.c
./testpar/t_span_tree.c
./testpar/t_init_term.c
./testpar/testpar.h

View File

@@ -184,6 +184,19 @@ New Features
Parallel Library:
-----------------
- Create VDS in parallel
The creation, along with reading and writing of Virtual Data Sets (VDS)
is now supported.
The VDS functionality is substantially that of the serial VDS version
with a major exception being that we don't support "printf" style
source file selections for parallel VDS. The rationale for this
restriction is that we require all file operations to be
collective and printf VDS support may break that particular
requirement.
(HDFFV-10287, RAW, 2018/07/18)
- Changed the default behavior in parallel when reading the same dataset in its entirely
(i.e. H5S_ALL dataset selection) which is being read by all the processes collectively.
The dataset mush be contiguous, less than 2GB, and of an atomic datatype.

View File

@@ -209,6 +209,9 @@ typedef struct H5CX_t {
MPI_Datatype btype; /* MPI datatype for buffer, when using collective I/O */
MPI_Datatype ftype; /* MPI datatype for file, when using collective I/O */
hbool_t mpi_file_flushing; /* Whether an MPI-opened file is being flushed */
/* Internal: File open settings (not inherently related to parallel but currently only used in parallel) */
hbool_t disable_file_locking;
hbool_t rank0_bcast; /* Whether a dataset meets read-with-rank0-and-bcast requirements */
#endif /* H5_HAVE_PARALLEL */
@@ -1663,6 +1666,32 @@ H5CX_get_mpi_file_flushing(void)
FUNC_LEAVE_NOAPI((*head)->ctx.mpi_file_flushing)
} /* end H5CX_get_mpi_file_flushing() */
/*-------------------------------------------------------------------------
* Function: H5CX_get_disable_file_locking
*
* Purpose: Retrieves the "disable file locking" flag for the current API call context.
*
* Return: TRUE / FALSE on success / <can't fail>
*
* Programmer: Neil Fortner
* August 2, 2018
*
*-------------------------------------------------------------------------
*/
hbool_t
H5CX_get_disable_file_locking(void)
{
H5CX_node_t **head = H5CX_get_my_context(); /* Get the pointer to the head of the API context, for this thread */
FUNC_ENTER_NOAPI_NOINIT_NOERR
/* Sanity check */
HDassert(head && *head);
FUNC_LEAVE_NOAPI((*head)->ctx.disable_file_locking)
} /* end H5CX_get_disable_file_locking() */
/*-------------------------------------------------------------------------
* Function: H5CX_get_mpio_rank0_bcast
@@ -2807,6 +2836,34 @@ H5CX_set_mpi_file_flushing(hbool_t flushing)
FUNC_LEAVE_NOAPI_VOID
} /* end H5CX_set_mpi_file_flushing() */
/*-------------------------------------------------------------------------
* Function: H5CX_set_disable_file_locking
*
* Purpose: Sets the "disable file locking" flag for the current API call context.
*
* Return: <none>
*
* Programmer: Neil Fortner
* August 2, 2018
*
*-------------------------------------------------------------------------
*/
void
H5CX_set_disable_file_locking(hbool_t disable_file_locking)
{
H5CX_node_t **head = H5CX_get_my_context(); /* Get the pointer to the head of the API context, for this thread */
FUNC_ENTER_NOAPI_NOINIT_NOERR
/* Sanity check */
HDassert(head && *head);
(*head)->ctx.disable_file_locking = disable_file_locking;
FUNC_LEAVE_NOAPI_VOID
} /* end H5CX_set_disable_file_locking() */
/*-------------------------------------------------------------------------
* Function: H5CX_set_mpio_rank0_bcast

View File

@@ -97,6 +97,7 @@ H5_DLL H5AC_ring_t H5CX_get_ring(void);
H5_DLL hbool_t H5CX_get_coll_metadata_read(void);
H5_DLL herr_t H5CX_get_mpi_coll_datatypes(MPI_Datatype *btype, MPI_Datatype *ftype);
H5_DLL hbool_t H5CX_get_mpi_file_flushing(void);
H5_DLL hbool_t H5CX_get_disable_file_locking(void);
H5_DLL hbool_t H5CX_get_mpio_rank0_bcast(void);
#endif /* H5_HAVE_PARALLEL */
@@ -143,6 +144,7 @@ H5_DLL void H5CX_set_coll_metadata_read(hbool_t cmdr);
H5_DLL herr_t H5CX_set_mpi_coll_datatypes(MPI_Datatype btype, MPI_Datatype ftype);
H5_DLL herr_t H5CX_set_mpio_coll_opt(H5FD_mpio_collective_opt_t mpio_coll_opt);
H5_DLL void H5CX_set_mpi_file_flushing(hbool_t flushing);
H5_DLL void H5CX_set_disable_file_locking(hbool_t disable_file_locking);
H5_DLL void H5CX_set_mpio_rank0_bcast(hbool_t rank0_bcast);
#endif /* H5_HAVE_PARALLEL */

View File

@@ -57,6 +57,7 @@
#include "H5Dpkg.h" /* Dataset functions */
#include "H5Eprivate.h" /* Error handling */
#include "H5Fprivate.h" /* Files */
#include "H5FDsec2.h" /* Posix unbuffered I/O file driver */
#include "H5FLprivate.h" /* Free Lists */
#include "H5Gprivate.h" /* Groups */
#include "H5HGprivate.h" /* Global Heaps */
@@ -483,12 +484,10 @@ H5D__virtual_store_layout(H5F_t *f, H5O_layout_t *layout)
/* Checksum */
block_size += 4;
/* Allocate heap block */
if(NULL == (heap_block = (uint8_t *)H5MM_malloc(block_size)))
HGOTO_ERROR(H5E_OHDR, H5E_RESOURCE, FAIL, "unable to allocate heap block")
/*
* Encode heap block
*/
@@ -828,6 +827,7 @@ done:
} /* end H5D__virtual_copy() */
/*-------------------------------------------------------------------------
* Function: H5D__virtual_delete
*
@@ -895,7 +895,6 @@ H5D__virtual_open_source_dset(const H5D_t *vdset,
H5O_storage_virtual_srcdset_t *source_dset)
{
H5F_t *src_file = NULL; /* Source file */
hbool_t src_file_open = FALSE; /* Whether we have opened and need to close src_file */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC
@@ -908,25 +907,47 @@ H5D__virtual_open_source_dset(const H5D_t *vdset,
HDassert(source_dset->dset_name);
/* Check if we need to open the source file */
if(HDstrcmp(source_dset->file_name, ".")) {
if(!HDstrcmp(source_dset->file_name, "."))
/* Source file is ".", use the virtual dataset's file */
src_file = vdset->oloc.file;
else if(source_dset->file)
/* Use previously opened file */
src_file = source_dset->file;
else {
unsigned intent; /* File access permissions */
#ifdef H5_HAVE_PARALLEL
hbool_t prev_disable_file_locking = FALSE; /* Whether file locking was previously disabled */
#endif /* H5_HAVE_PARALLEL */
/* Get the virtual dataset's file open flags ("intent") */
intent = H5F_INTENT(vdset->oloc.file);
#ifdef H5_HAVE_PARALLEL
/* Since the parallel implementation currently uses one independent open
* per process on source files, we must disable file locking on source
* files if the VDS is opened in parallel */
if(H5F_HAS_FEATURE(vdset->oloc.file, H5FD_FEAT_HAS_MPI)) {
prev_disable_file_locking = H5CX_get_disable_file_locking();
H5CX_set_disable_file_locking(TRUE);
} /* end if */
#endif /* H5_HAVE_PARALLEL */
/* Try opening the file */
src_file = H5F_prefix_open_file(vdset->oloc.file, H5F_PREFIX_VDS, vdset->shared->vds_prefix, source_dset->file_name, intent, vdset->shared->layout.storage.u.virt.source_fapl);
/* If we opened the source file here, we should close it when leaving */
if(src_file)
src_file_open = TRUE;
else
/* Reset the error stack */
H5E_clear_stack(NULL);
#ifdef H5_HAVE_PARALLEL
/* Reset "disable file locking" flag */
if(H5F_HAS_FEATURE(vdset->oloc.file, H5FD_FEAT_HAS_MPI)) {
H5CX_set_disable_file_locking(prev_disable_file_locking);
} /* end if */
#endif /* H5_HAVE_PARALLEL */
/* Reset the error stack if we did not find the file */
if(!src_file)
H5E_clear_stack(NULL);
source_dset->file = src_file;
} /* end if */
else
/* Source file is ".", use the virtual dataset's file */
src_file = vdset->oloc.file;
if(src_file) {
H5G_loc_t src_root_loc; /* Object location of source file root group */
@@ -941,16 +962,11 @@ H5D__virtual_open_source_dset(const H5D_t *vdset,
source_dset->dset = H5D__open_name(&src_root_loc, source_dset->dset_name, vdset->shared->layout.storage.u.virt.source_dapl);
/* Dataset does not exist */
if(NULL == source_dset->dset) {
if(NULL == source_dset->dset)
/* Reset the error stack */
H5E_clear_stack(NULL);
source_dset->dset_exists = FALSE;
} /* end if */
else {
/* Dataset exists */
source_dset->dset_exists = TRUE;
/* Patch the source selection if necessary */
if(virtual_ent->source_space_status != H5O_VIRTUAL_STATUS_CORRECT) {
if(H5S_extent_copy(virtual_ent->source_select, source_dset->dset->shared->space) < 0)
@@ -961,10 +977,6 @@ H5D__virtual_open_source_dset(const H5D_t *vdset,
} /* end if */
done:
/* Release resources */
if(src_file_open)
if(H5F_efc_close(vdset->oloc.file, 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() */
@@ -1000,6 +1012,14 @@ H5D__virtual_reset_source_dset(H5O_storage_virtual_ent_t *virtual_ent,
source_dset->dset = NULL;
} /* end if */
/* Close file */
if(source_dset->file) {
HDassert(virtual_ent->virtual_file);
if(H5F_efc_close(virtual_ent->virtual_file, source_dset->file) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEFILE, FAIL, "can't close source file")
source_dset->file = NULL;
} /* end if */
/* Free file name */
if(virtual_ent->parsed_source_file_name
&& (source_dset->file_name
@@ -1578,6 +1598,12 @@ H5D__virtual_set_extent_unlim(const H5D_t *dset)
/* printf mapping */
hsize_t first_missing = 0; /* First missing dataset in the current block of missing datasets */
#ifdef H5_HAVE_PARALLEL
/* Parallel not yet supported with printf mappings */
if(H5F_HAS_FEATURE(dset->oloc.file, H5FD_FEAT_HAS_MPI))
HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "parallel operations on printf style datasets not supported")
#endif /* H5_HAVE_PARALLEL */
/* Search for source datasets */
HDassert(storage->printf_gap != HSIZE_UNDEF);
for(j = 0; j <= (storage->printf_gap + first_missing); j++) {
@@ -1606,7 +1632,7 @@ H5D__virtual_set_extent_unlim(const H5D_t *dset)
} /* end if */
/* Check if the dataset was already opened */
if(storage->list[i].sub_dset[j].dset_exists)
if(storage->list[i].sub_dset[j].dset)
first_missing = j + 1;
else {
/* Resolve file name */
@@ -1993,6 +2019,12 @@ H5D__virtual_init_all(const H5D_t *dset)
size_t sub_dset_max;
hbool_t partial_block;
#ifdef H5_HAVE_PARALLEL
/* Parallel not yet supported with printf mappings */
if(H5F_HAS_FEATURE(dset->oloc.file, H5FD_FEAT_HAS_MPI))
HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "parallel operations on printf style datasets not supported")
#endif /* H5_HAVE_PARALLEL */
/* Get number of sub-source datasets in current extent */
sub_dset_max = (size_t)H5S_hyper_get_first_inc_block(storage->list[i].source_dset.virtual_select, virtual_dims[storage->list[i].unlim_dim_virtual], &partial_block);
if(partial_block)
@@ -2110,6 +2142,7 @@ herr_t
H5D__virtual_init(H5F_t *f, const H5D_t *dset, hid_t dapl_id)
{
H5O_storage_virtual_t *storage; /* Convenience pointer */
H5O_layout_t *layout_dst; /* Another convenence pointer */
H5P_genplist_t *dapl; /* Data access property list object pointer */
hssize_t old_offset[H5O_LAYOUT_NDIMS]; /* Old selection offset (unused) */
size_t i; /* Local index variables */
@@ -2121,6 +2154,7 @@ H5D__virtual_init(H5F_t *f, const H5D_t *dset, hid_t dapl_id)
HDassert(dset);
storage = &dset->shared->layout.storage.u.virt;
HDassert(storage->list || (storage->list_nused == 0));
layout_dst = &dset->shared->layout;
/* Check that the dimensions of the VDS are large enough */
if(H5D_virtual_check_min_dims(dset) < 0)
@@ -2150,6 +2184,9 @@ H5D__virtual_init(H5F_t *f, const H5D_t *dset, hid_t dapl_id)
HGOTO_ERROR(H5E_DATASET, H5E_BADSELECT, FAIL, "unable to normalize dataspace by offset")
if(H5S_hyper_normalize_offset(storage->list[i].source_select, old_offset) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_BADSELECT, FAIL, "unable to normalize dataspace by offset")
/* Save pointer to virtual dataset in entry */
storage->list[i].virtual_file = (H5F_t *)dset->oloc.file;
} /* end for */
/* Get dataset access property list */
@@ -2169,10 +2206,24 @@ H5D__virtual_init(H5F_t *f, const H5D_t *dset, hid_t dapl_id)
storage->printf_gap = (hsize_t)0;
/* Retrieve VDS file FAPL to layout */
if(storage->source_fapl <= 0)
if(storage->source_fapl <= 0) {
if((storage->source_fapl = H5F_get_access_plist(f, FALSE)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get fapl")
#ifdef H5_HAVE_PARALLEL
/* For now, in the parallel case, open all source files with the sec2
* driver */
if(H5F_HAS_FEATURE(f, H5FD_FEAT_HAS_MPI)) {
H5P_genplist_t *source_fapl_ptr;
if(NULL == (source_fapl_ptr = H5P_object_verify(storage->source_fapl, H5P_FILE_ACCESS)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list")
if(H5P_set_driver(source_fapl_ptr, H5FD_SEC2, NULL) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set sec2 driver on source fapl")
} /* end if */
#endif /* H5_HAVE_PARALLEL */
} /* end if */
/* Copy DAPL to layout */
if(storage->source_dapl <= 0)
if((storage->source_dapl = H5P_copy_plist(dapl, FALSE)) < 0)
@@ -2182,6 +2233,14 @@ H5D__virtual_init(H5F_t *f, const H5D_t *dset, hid_t dapl_id)
* unlimited/printf selections) */
storage->init = FALSE;
/* Insert global heap object if it does not already exist. Do this now so
* we don't have to insert an object into the cache when encoding the
* layout, which would cause problems in parallel. */
if(storage->serial_list_hobjid.addr == HADDR_UNDEF)
/* Write the VDS data to destination file's heap */
if(H5D__virtual_store_layout(f, layout_dst) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to store VDS info")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__virtual_init() */
@@ -2650,12 +2709,6 @@ 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;
HDassert((storage->view == H5D_VDS_FIRST_MISSING) || (storage->view == H5D_VDS_LAST_AVAILABLE));
#ifdef H5_HAVE_PARALLEL
/* Parallel reads are not supported (yet) */
if(H5F_HAS_FEATURE(io_info->dset->oloc.file, H5FD_FEAT_HAS_MPI))
HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "parallel reads not supported on virtual datasets")
#endif /* H5_HAVE_PARALLEL */
/* Prepare for I/O operation */
if(H5D__virtual_pre_io(io_info, storage, file_space, mem_space, &tot_nelmts) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCLIP, FAIL, "unable to prepare for I/O operation")
@@ -2840,12 +2893,6 @@ 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;
HDassert((storage->view == H5D_VDS_FIRST_MISSING) || (storage->view == H5D_VDS_LAST_AVAILABLE));
#ifdef H5_HAVE_PARALLEL
/* Parallel writes are not supported (yet) */
if(H5F_HAS_FEATURE(io_info->dset->oloc.file, H5FD_FEAT_HAS_MPI))
HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "parallel writes not supported on virtual datasets")
#endif /* H5_HAVE_PARALLEL */
/* Prepare for I/O operation */
if(H5D__virtual_pre_io(io_info, storage, file_space, mem_space, &tot_nelmts) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCLIP, FAIL, "unable to prepare for I/O operation")

View File

@@ -59,6 +59,24 @@ static char H5FD_mpi_native_g[] = "native";
*/
typedef struct H5FD_mpio_t {
H5FD_t pub; /*public stuff, must be first */
/* For comparisons */
#ifndef H5_HAVE_WIN32_API
/* On most systems the combination of device and i-node number uniquely
* identify a file. Note that Cygwin, MinGW and other Windows POSIX
* environments have the stat function (which fakes inodes)
* and will use the 'device + inodes' scheme as opposed to the
* Windows code further below.
*/
dev_t device; /* file device number */
ino_t inode; /* file i-node number */
#else
DWORD nFileIndexLow;
DWORD nFileIndexHigh;
DWORD dwVolumeSerialNumber;
#endif
MPI_File f; /*MPIO file handle */
MPI_Comm comm; /*communicator */
MPI_Info info; /*file information */
@@ -80,6 +98,7 @@ static herr_t H5FD__mpio_fapl_free(void *_fa);
static H5FD_t *H5FD__mpio_open(const char *name, unsigned flags, hid_t fapl_id,
haddr_t maxaddr);
static herr_t H5FD__mpio_close(H5FD_t *_file);
static int H5FD__mpio_cmp(const H5FD_t *_f1, const H5FD_t *_f2);
static herr_t H5FD__mpio_query(const H5FD_t *_f1, unsigned long *flags);
static haddr_t H5FD__mpio_get_eoa(const H5FD_t *_file, H5FD_mem_t type);
static herr_t H5FD__mpio_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t addr);
@@ -115,7 +134,7 @@ static const H5FD_class_mpi_t H5FD_mpio_g = {
NULL, /*dxpl_free */
H5FD__mpio_open, /*open */
H5FD__mpio_close, /*close */
NULL, /*cmp */
H5FD__mpio_cmp, /*cmp */
H5FD__mpio_query, /*query */
NULL, /*get_type_map */
NULL, /*alloc */
@@ -907,6 +926,87 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5FD_get_mpio_atomicity() */
/*
* Function: H5FD_mpio_fileinfo_get
*
* Purpose: Implements a normal (posix) file open for MPI rank 0.
* Replicates the functionality of H5FD_sec2_open. We
* open the file and cache a few key structures before
* closing. These cached structures are those which
* are eventually utilized for MPIO file comparisons.
*
* N.B. The file handles returned by the collective MPI
* File open function are not guaranteed to have a relation to
* an actual posix file handle. This then, provides the
* requirement that we do a "normal" file open to provide
* an actual file handle with which we can gather more
* detailed information to eventually implement file
* comparisons (see: H5FD__mpio_cmp)
*
* Return: Success: Non-negative
*
* Failure: Negative
* Indicates too, that the information used for
* MPIO file comparisons will most likely not
* be initialized and this in turn can lead to
* runtime issues, e.g. File comparison failures.
*/
static herr_t
H5FD_mpio_fileinfo_get(const char *name, unsigned flags, H5FD_mpio_t *file)
{
int status;
int fd = -1; /* File descriptor */
int o_flags; /* Flags for open() call */
h5_stat_t sb;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_NOINIT
#ifdef H5FDmpio_DEBUG
if (H5FD_mpio_Debug[(int)'t'])
fprintf(stdout, "Entering H5FD_mpio_fileinfo_get\n");
#endif
#ifdef H5_HAVE_WIN32_API
struct _BY_HANDLE_FILE_INFORMATION fileinfo;
HANDLE hFile; /* Native windows file handle */
#endif
o_flags = (H5F_ACC_RDWR & flags) ? O_RDWR : O_RDONLY;
/* Open the file */
if((fd = HDopen(name, o_flags, H5_POSIX_CREATE_MODE_RW)) < 0)
HMPI_GOTO_ERROR(FAIL, "HDopen failed", fd)
if((status = HDfstat(fd, &sb)) < 0)
HMPI_GOTO_ERROR(FAIL, "HDfstat failed", status)
#ifdef H5_HAVE_WIN32_API
hFile = (HANDLE)_get_osfhandle(fd);
if(INVALID_HANDLE_VALUE == hFile)
HMPI_GOTO_ERROR(FAIL, "_get_osfhandle failed", -1)
if(!GetFileInformationByHandle((HANDLE)hFile, &fileinfo))
HMPI_GOTO_ERROR(FAIL, "GetFileInformationByHandle failed", 0)
file->nFileIndexHigh = fileinfo.nFileIndexHigh;
file->nFileIndexLow = fileinfo.nFileIndexLow;
file->dwVolumeSerialNumber = fileinfo.dwVolumeSerialNumber;
#else /* H5_HAVE_WIN32_API */
file->device = sb.st_dev;
file->inode = sb.st_ino;
#endif /* H5_HAVE_WIN32_API */
done:
if(fd >= 0)
HDclose(fd);
#ifdef H5FDmpio_DEBUG
if (H5FD_mpio_Debug[(int)'t'])
fprintf(stdout, "Leaving H5FD_mpio_fileinfo_get\n");
#endif
FUNC_LEAVE_NOAPI(ret_value)
}
/*-------------------------------------------------------------------------
* Function: H5FD__mpio_open
@@ -1039,6 +1139,11 @@ H5FD__mpio_open(const char *name, unsigned flags, hid_t fapl_id,
file->eof = H5FD_mpi_MPIOff_to_haddr(size);
file->local_eof = file->eof;
if (mpi_rank == 0) {
/* Gather some file info for future comparisons */
if (H5FD_mpio_fileinfo_get( name, flags, file ) < 0)
HMPI_GOTO_ERROR(NULL, "H5FD_mpio_fileinfo_get failed", -1)
}
/* Set return value */
ret_value = (H5FD_t*)file;
@@ -1062,6 +1167,129 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5FD__mpio_open() */
/*-------------------------------------------------------------------------
* Function: H5FD__mpio_cmp
*
* Purpose: This version of the 'cmp' function is used to compare two
* files which have been created and opened using the MPI-IO
* driver.
* The peculiarity of this is that unlike POSIX io, the
* handle returned from an MPI_File_open operation may be
* an abstract value and not have any relation to an actual
* filestem handle. The net result is that additional
* filesystem information needs to be gathered to subsequently
* utilize the stronger filesystem based methodology used in
* other HDF5 drivers, e.g. H5FD_sec2_cmp()
* The approach is two fold:
* 1. The MPI communicators used to access parallel files
* will be compared.
* 2. MPI rank 0 is tasked with collecting the additional
* POSIX or Windows NTFS information that is subsequently
* used here for comparison purposes. The result is
* then broadcast to the participating MPI ranks to effect
* a global result.
*
* Return: An integer value similar to that returned by strcmp()
* NOTE: This function can't FAIL. In those cases where
* where we would normally return FAILURE, e.g. when MPI
* returns an error, we treat these as unequal comparisons.
*
* Programmer: Richard Warren
* Originally borrowed from H5FD_sec2_cmp (Robb Matzke) and
* modified as described above.
*
*-------------------------------------------------------------------------
*/
static int
H5FD__mpio_cmp(const H5FD_t *_f1, const H5FD_t *_f2)
{
const H5FD_mpio_t *f1 = (const H5FD_mpio_t *)_f1;
const H5FD_mpio_t *f2 = (const H5FD_mpio_t *)_f2;
int ret_value = 0;
int cmp_value = 0;
int mpi_result;
MPI_Group f1_grp;
MPI_Group f2_grp;
FUNC_ENTER_NOAPI_NOINIT
if ((mpi_result = MPI_Comm_group(f1->comm, &f1_grp)) != MPI_SUCCESS)
HMPI_GOTO_ERROR(-1, "MPI_Comm_group(comm1) failed", mpi_result)
if ((mpi_result = MPI_Comm_group(f2->comm, &f2_grp)) != MPI_SUCCESS)
HMPI_GOTO_ERROR(-1, "MPI_Comm_group(comm2) failed", mpi_result)
if ((mpi_result = MPI_Group_compare(f1_grp, f2_grp, &cmp_value)) != MPI_SUCCESS)
HMPI_GOTO_ERROR(-1, "MPI_Group_compare failed", mpi_result)
/* The group compare return values can be one of the following:
* MPI_IDENT(0) == two groups/communicators are identical
* ---------------- Those below can lead to unexpected
* ---------------- results, so we will return unequal
* for the file comparison.
* MPI_CONGRUENT(1) == two groups/communicators are equal but
* are distinct communication domains
* MPI_SIMILAR(2) == two groups have the same members but
* ordering may be different
* MPI_UNEQUAL(3) == self descriptive (unequal)
*
* Note: Congruent groups would seem to satisfy the equality
* condition from the file perspective, but there may be conditions
* in which collective operations would cause an application to
* hang if two different communicators are in use, e.g. any
* sort of synchronization (Barrier, Bcast).
*/
if (cmp_value >= MPI_CONGRUENT)
HGOTO_DONE(-1)
if (f1->mpi_rank == 0) {
/* Because MPI file handles may NOT have any relation to
* to actual file handle, we utilize a "regular" file open
* on MPI rank 0 prior to opening with the MPI-IO routines.
* The H5FD_mpio_t structure is utilized to cache the
* relevant comparison values which we use for comparisons
* below.
*/
#ifdef H5_HAVE_WIN32_API
if ((f1->dwVolumeSerialNumber < f2->dwVolumeSerialNumber) ||
(f1->nFileIndexHigh < f2->nFileIndexHigh) ||
(f1->nFileIndexLow < f2->nFileIndexLow))
cmp_value = -1;
else
if ((f1->dwVolumeSerialNumber > f2->dwVolumeSerialNumber) ||
(f1->nFileIndexHigh > f2->nFileIndexHigh) ||
(f1->nFileIndexLow > f2->nFileIndexLow))
cmp_value = 1;
#else /* Not WIN32 */
#ifdef H5_DEV_T_IS_SCALAR
if (f1->device < f2->device) cmp_value = -1;
else if(f1->device > f2->device) cmp_value = 1;
#else /* H5_DEV_T_IS_SCALAR */
/* If dev_t isn't a scalar value on this system, just use memcmp to
* determine if the values are the same or not. The actual return value
* shouldn't really matter...
*/
cmp_value = HDmemcmp(&(f1->device), &(f2->device), sizeof(dev_t));
#endif /* H5_DEV_T_IS_SCALAR */
/* Continue checking ONLY if we haven't failed yet */
if (!cmp_value) {
if(f1->inode < f2->inode) cmp_value = -1;
else if(f1->inode > f2->inode) cmp_value = 1;
#endif /* H5_HAVE_WIN32_API */
}
}
if (MPI_SUCCESS != (mpi_result = MPI_Bcast(&cmp_value, 1, MPI_INT, 0, f1->comm)))
HMPI_GOTO_ERROR(-1, "MPI_Bcast failed", mpi_result)
ret_value = cmp_value;
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5FD__mpio_cmp() */
/*-------------------------------------------------------------------------
* Function: H5FD__mpio_close

View File

@@ -1519,15 +1519,22 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
if(NULL == (drvr = H5FD_get_class(fapl_id)))
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "unable to retrieve VFL class")
/* Check the environment variable that determines if we care
* about file locking. File locking should be used unless explicitly
* disabled.
/* Check for file locking disabled internally, then check the environment
* variable that determines if we care about file locking. File locking
* should be used unless explicitly disabled.
*/
#ifdef H5_HAVE_PARALLEL
if(H5CX_get_disable_file_locking())
use_file_locking = FALSE;
else
#endif /* H5_HAVE_PARALLEL */
{
lock_env_var = HDgetenv("HDF5_USE_FILE_LOCKING");
if(lock_env_var && !HDstrcmp(lock_env_var, "FALSE"))
use_file_locking = FALSE;
else
use_file_locking = TRUE;
} /* end block/else */
/*
* Opening a file is a two step process. First we try to open the

View File

@@ -679,7 +679,15 @@ H5O__layout_encode(H5F_t *f, hbool_t H5_ATTR_UNUSED disable_shared, uint8_t *p,
break;
case H5D_VIRTUAL:
/* Encode heap ID for VDS info */
/* Heap block should have been created already! */
HDassert((mesg->storage.u.virt.serial_list_hobjid.addr != HADDR_UNDEF)
|| (mesg->storage.u.virt.list_nused == 0));
/* Heap information
* During H5Fclose, the cache flushing can call H5O_msg_flush calls
* which we need to handle here...
*/
H5F_addr_encode(f, &p, mesg->storage.u.virt.serial_list_hobjid.addr);
UINT32ENCODE(p, mesg->storage.u.virt.serial_list_hobjid.idx);
break;

View File

@@ -432,6 +432,9 @@ typedef struct H5O_efl_t {
* and 'size' callbacks for places to change when updating this. */
#define H5O_LAYOUT_VERSION_LATEST H5O_LAYOUT_VERSION_4
/* Version # of encoded virtual dataset global heap blocks */
#define H5O_LAYOUT_VDS_GH_ENC_VERS 0
/* Forward declaration of structs used below */
struct H5D_layout_ops_t; /* Defined in H5Dpkg.h */
struct H5D_chunk_ops_t; /* Defined in H5Dpkg.h */
@@ -505,7 +508,7 @@ typedef struct H5O_storage_virtual_srcdset_t {
struct H5S_t *clipped_source_select; /* Clipped version of source_select */
struct H5S_t *clipped_virtual_select; /* Clipped version of virtual_select */
struct H5D_t *dset; /* Source dataset */
hbool_t dset_exists; /* Whether the dataset exists (was opened successfully) */
struct H5F_t *file; /* Source file (if one was opened for this dataset) */
/* Temporary - only used during I/O operation, NULL at all other times */
struct H5S_t *projected_mem_space; /* Selection within mem_space for this mapping */
@@ -550,6 +553,7 @@ typedef struct H5O_storage_virtual_ent_t {
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 */
H5F_t *virtual_file; /* Convenience pointer to file containing virtual dataset */
} H5O_storage_virtual_ent_t;
typedef struct H5O_storage_virtual_t {

View File

@@ -1478,6 +1478,7 @@ H5S__mpio_create_large_type(hsize_t num_elements, MPI_Aint stride_bytes,
int block_len[2];
int mpi_code; /* MPI return code */
MPI_Datatype inner_type, outer_type, leftover_type, type[2];
MPI_Aint lb; /* Needed as an argument for MPI_Type_get_extent */
MPI_Aint disp[2], old_extent;
herr_t ret_value = SUCCEED; /* Return value */

View File

@@ -1713,6 +1713,8 @@ H5S_select_shape_same(const H5S_t *space1, const H5S_t *space2)
/* Check for different number of elements selected */
if(H5S_GET_SELECT_NPOINTS(space1) != H5S_GET_SELECT_NPOINTS(space2))
HGOTO_DONE(FALSE)
else if (space1 == space2)
HGOTO_DONE(TRUE);
/* Check special cases if both dataspaces aren't scalar */
/* (If only one is, the number of selected points check is sufficient) */

View File

@@ -67,6 +67,8 @@ set (H5P_TESTS
t_pread
t_pshutdown
t_prestart
t_psubfile
t_pvds
t_init_term
t_shapesame
t_filters_parallel

View File

@@ -30,7 +30,7 @@ check_SCRIPTS = $(TEST_SCRIPT_PARA)
# Test programs. These are our main targets.
#
TEST_PROG_PARA=t_mpi t_bigio testphdf5 t_cache t_cache_image t_pread t_pshutdown t_prestart t_init_term t_shapesame t_filters_parallel
TEST_PROG_PARA=t_mpi t_bigio testphdf5 t_cache t_cache_image t_pread t_pshutdown t_prestart t_pvds t_init_term t_shapesame t_filters_parallel t_psubfile
# t_pflush1 and t_pflush2 are used by testpflush.sh
check_PROGRAMS = $(TEST_PROG_PARA) t_pflush1 t_pflush2

1007
testpar/t_psubfile.c Normal file

File diff suppressed because it is too large Load Diff

6892
testpar/t_pvds.c Normal file

File diff suppressed because it is too large Load Diff