Compare commits
25 Commits
reduce-h5f
...
inactive/p
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
35c9af8371 | ||
|
|
c752332bfd | ||
|
|
602bdd1c6a | ||
|
|
3e445ef129 | ||
|
|
e14ec4276e | ||
|
|
291cd766bc | ||
|
|
b27f981ea6 | ||
|
|
0cc1d7d781 | ||
|
|
d007267f1b | ||
|
|
f7a62775c1 | ||
|
|
439de0afcc | ||
|
|
37ff3a38cc | ||
|
|
de64afbd39 | ||
|
|
8e4cb935fc | ||
|
|
963954e756 | ||
|
|
1657e0324d | ||
|
|
c946c72a30 | ||
|
|
6ad9585342 | ||
|
|
5ce8d5da40 | ||
|
|
e3a6bcc87a | ||
|
|
38ebfd7f4d | ||
|
|
8d7d1f1ab6 | ||
|
|
9b23d85f51 | ||
|
|
2a24cb0d0f | ||
|
|
de129217a4 |
2
MANIFEST
2
MANIFEST
@@ -1315,6 +1315,8 @@
|
|||||||
./testpar/t_shapesame.c
|
./testpar/t_shapesame.c
|
||||||
./testpar/t_pshutdown.c
|
./testpar/t_pshutdown.c
|
||||||
./testpar/t_prestart.c
|
./testpar/t_prestart.c
|
||||||
|
./testpar/t_psubfile.c
|
||||||
|
./testpar/t_pvds.c
|
||||||
./testpar/t_span_tree.c
|
./testpar/t_span_tree.c
|
||||||
./testpar/t_init_term.c
|
./testpar/t_init_term.c
|
||||||
./testpar/testpar.h
|
./testpar/testpar.h
|
||||||
|
|||||||
@@ -184,6 +184,19 @@ New Features
|
|||||||
|
|
||||||
Parallel Library:
|
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
|
- 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.
|
(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.
|
The dataset mush be contiguous, less than 2GB, and of an atomic datatype.
|
||||||
|
|||||||
57
src/H5CX.c
57
src/H5CX.c
@@ -209,6 +209,9 @@ typedef struct H5CX_t {
|
|||||||
MPI_Datatype btype; /* MPI datatype for buffer, when using collective I/O */
|
MPI_Datatype btype; /* MPI datatype for buffer, when using collective I/O */
|
||||||
MPI_Datatype ftype; /* MPI datatype for file, 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 */
|
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 */
|
hbool_t rank0_bcast; /* Whether a dataset meets read-with-rank0-and-bcast requirements */
|
||||||
#endif /* H5_HAVE_PARALLEL */
|
#endif /* H5_HAVE_PARALLEL */
|
||||||
|
|
||||||
@@ -1663,6 +1666,32 @@ H5CX_get_mpi_file_flushing(void)
|
|||||||
FUNC_LEAVE_NOAPI((*head)->ctx.mpi_file_flushing)
|
FUNC_LEAVE_NOAPI((*head)->ctx.mpi_file_flushing)
|
||||||
} /* end H5CX_get_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
|
* Function: H5CX_get_mpio_rank0_bcast
|
||||||
@@ -2807,6 +2836,34 @@ H5CX_set_mpi_file_flushing(hbool_t flushing)
|
|||||||
FUNC_LEAVE_NOAPI_VOID
|
FUNC_LEAVE_NOAPI_VOID
|
||||||
} /* end H5CX_set_mpi_file_flushing() */
|
} /* 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
|
* Function: H5CX_set_mpio_rank0_bcast
|
||||||
|
|||||||
@@ -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 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 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_mpi_file_flushing(void);
|
||||||
|
H5_DLL hbool_t H5CX_get_disable_file_locking(void);
|
||||||
H5_DLL hbool_t H5CX_get_mpio_rank0_bcast(void);
|
H5_DLL hbool_t H5CX_get_mpio_rank0_bcast(void);
|
||||||
#endif /* H5_HAVE_PARALLEL */
|
#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_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 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_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);
|
H5_DLL void H5CX_set_mpio_rank0_bcast(hbool_t rank0_bcast);
|
||||||
#endif /* H5_HAVE_PARALLEL */
|
#endif /* H5_HAVE_PARALLEL */
|
||||||
|
|
||||||
|
|||||||
119
src/H5Dvirtual.c
119
src/H5Dvirtual.c
@@ -57,6 +57,7 @@
|
|||||||
#include "H5Dpkg.h" /* Dataset functions */
|
#include "H5Dpkg.h" /* Dataset functions */
|
||||||
#include "H5Eprivate.h" /* Error handling */
|
#include "H5Eprivate.h" /* Error handling */
|
||||||
#include "H5Fprivate.h" /* Files */
|
#include "H5Fprivate.h" /* Files */
|
||||||
|
#include "H5FDsec2.h" /* Posix unbuffered I/O file driver */
|
||||||
#include "H5FLprivate.h" /* Free Lists */
|
#include "H5FLprivate.h" /* Free Lists */
|
||||||
#include "H5Gprivate.h" /* Groups */
|
#include "H5Gprivate.h" /* Groups */
|
||||||
#include "H5HGprivate.h" /* Global Heaps */
|
#include "H5HGprivate.h" /* Global Heaps */
|
||||||
@@ -483,12 +484,10 @@ H5D__virtual_store_layout(H5F_t *f, H5O_layout_t *layout)
|
|||||||
/* Checksum */
|
/* Checksum */
|
||||||
block_size += 4;
|
block_size += 4;
|
||||||
|
|
||||||
|
|
||||||
/* Allocate heap block */
|
/* Allocate heap block */
|
||||||
if(NULL == (heap_block = (uint8_t *)H5MM_malloc(block_size)))
|
if(NULL == (heap_block = (uint8_t *)H5MM_malloc(block_size)))
|
||||||
HGOTO_ERROR(H5E_OHDR, H5E_RESOURCE, FAIL, "unable to allocate heap block")
|
HGOTO_ERROR(H5E_OHDR, H5E_RESOURCE, FAIL, "unable to allocate heap block")
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Encode heap block
|
* Encode heap block
|
||||||
*/
|
*/
|
||||||
@@ -828,6 +827,7 @@ done:
|
|||||||
} /* end H5D__virtual_copy() */
|
} /* end H5D__virtual_copy() */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------
|
/*-------------------------------------------------------------------------
|
||||||
* Function: H5D__virtual_delete
|
* Function: H5D__virtual_delete
|
||||||
*
|
*
|
||||||
@@ -895,7 +895,6 @@ H5D__virtual_open_source_dset(const H5D_t *vdset,
|
|||||||
H5O_storage_virtual_srcdset_t *source_dset)
|
H5O_storage_virtual_srcdset_t *source_dset)
|
||||||
{
|
{
|
||||||
H5F_t *src_file = NULL; /* Source file */
|
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 */
|
herr_t ret_value = SUCCEED; /* Return value */
|
||||||
|
|
||||||
FUNC_ENTER_STATIC
|
FUNC_ENTER_STATIC
|
||||||
@@ -908,25 +907,47 @@ H5D__virtual_open_source_dset(const H5D_t *vdset,
|
|||||||
HDassert(source_dset->dset_name);
|
HDassert(source_dset->dset_name);
|
||||||
|
|
||||||
/* Check if we need to open the source file */
|
/* 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 */
|
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") */
|
/* Get the virtual dataset's file open flags ("intent") */
|
||||||
intent = H5F_INTENT(vdset->oloc.file);
|
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 */
|
/* 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);
|
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 */
|
#ifdef H5_HAVE_PARALLEL
|
||||||
if(src_file)
|
/* Reset "disable file locking" flag */
|
||||||
src_file_open = TRUE;
|
if(H5F_HAS_FEATURE(vdset->oloc.file, H5FD_FEAT_HAS_MPI)) {
|
||||||
else
|
H5CX_set_disable_file_locking(prev_disable_file_locking);
|
||||||
/* Reset the error stack */
|
} /* end if */
|
||||||
|
#endif /* H5_HAVE_PARALLEL */
|
||||||
|
|
||||||
|
/* Reset the error stack if we did not find the file */
|
||||||
|
if(!src_file)
|
||||||
H5E_clear_stack(NULL);
|
H5E_clear_stack(NULL);
|
||||||
|
|
||||||
|
source_dset->file = src_file;
|
||||||
} /* end if */
|
} /* end if */
|
||||||
else
|
|
||||||
/* Source file is ".", use the virtual dataset's file */
|
|
||||||
src_file = vdset->oloc.file;
|
|
||||||
|
|
||||||
if(src_file) {
|
if(src_file) {
|
||||||
H5G_loc_t src_root_loc; /* Object location of source file root group */
|
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);
|
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 */
|
/* Dataset does not exist */
|
||||||
if(NULL == source_dset->dset) {
|
if(NULL == source_dset->dset)
|
||||||
/* Reset the error stack */
|
/* Reset the error stack */
|
||||||
H5E_clear_stack(NULL);
|
H5E_clear_stack(NULL);
|
||||||
|
|
||||||
source_dset->dset_exists = FALSE;
|
|
||||||
} /* end if */
|
|
||||||
else {
|
else {
|
||||||
/* Dataset exists */
|
|
||||||
source_dset->dset_exists = TRUE;
|
|
||||||
|
|
||||||
/* Patch the source selection if necessary */
|
/* Patch the source selection if necessary */
|
||||||
if(virtual_ent->source_space_status != H5O_VIRTUAL_STATUS_CORRECT) {
|
if(virtual_ent->source_space_status != H5O_VIRTUAL_STATUS_CORRECT) {
|
||||||
if(H5S_extent_copy(virtual_ent->source_select, source_dset->dset->shared->space) < 0)
|
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 */
|
} /* end if */
|
||||||
|
|
||||||
done:
|
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)
|
FUNC_LEAVE_NOAPI(ret_value)
|
||||||
} /* end H5D__virtual_open_source_dset() */
|
} /* 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;
|
source_dset->dset = NULL;
|
||||||
} /* end if */
|
} /* 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 */
|
/* Free file name */
|
||||||
if(virtual_ent->parsed_source_file_name
|
if(virtual_ent->parsed_source_file_name
|
||||||
&& (source_dset->file_name
|
&& (source_dset->file_name
|
||||||
@@ -1578,6 +1598,12 @@ H5D__virtual_set_extent_unlim(const H5D_t *dset)
|
|||||||
/* printf mapping */
|
/* printf mapping */
|
||||||
hsize_t first_missing = 0; /* First missing dataset in the current block of missing datasets */
|
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 */
|
/* Search for source datasets */
|
||||||
HDassert(storage->printf_gap != HSIZE_UNDEF);
|
HDassert(storage->printf_gap != HSIZE_UNDEF);
|
||||||
for(j = 0; j <= (storage->printf_gap + first_missing); j++) {
|
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 */
|
} /* end if */
|
||||||
|
|
||||||
/* Check if the dataset was already opened */
|
/* 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;
|
first_missing = j + 1;
|
||||||
else {
|
else {
|
||||||
/* Resolve file name */
|
/* Resolve file name */
|
||||||
@@ -1993,6 +2019,12 @@ H5D__virtual_init_all(const H5D_t *dset)
|
|||||||
size_t sub_dset_max;
|
size_t sub_dset_max;
|
||||||
hbool_t partial_block;
|
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 */
|
/* 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);
|
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)
|
if(partial_block)
|
||||||
@@ -2110,6 +2142,7 @@ herr_t
|
|||||||
H5D__virtual_init(H5F_t *f, const H5D_t *dset, hid_t dapl_id)
|
H5D__virtual_init(H5F_t *f, const H5D_t *dset, hid_t dapl_id)
|
||||||
{
|
{
|
||||||
H5O_storage_virtual_t *storage; /* Convenience pointer */
|
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 */
|
H5P_genplist_t *dapl; /* Data access property list object pointer */
|
||||||
hssize_t old_offset[H5O_LAYOUT_NDIMS]; /* Old selection offset (unused) */
|
hssize_t old_offset[H5O_LAYOUT_NDIMS]; /* Old selection offset (unused) */
|
||||||
size_t i; /* Local index variables */
|
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);
|
HDassert(dset);
|
||||||
storage = &dset->shared->layout.storage.u.virt;
|
storage = &dset->shared->layout.storage.u.virt;
|
||||||
HDassert(storage->list || (storage->list_nused == 0));
|
HDassert(storage->list || (storage->list_nused == 0));
|
||||||
|
layout_dst = &dset->shared->layout;
|
||||||
|
|
||||||
/* Check that the dimensions of the VDS are large enough */
|
/* Check that the dimensions of the VDS are large enough */
|
||||||
if(H5D_virtual_check_min_dims(dset) < 0)
|
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")
|
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)
|
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")
|
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 */
|
} /* end for */
|
||||||
|
|
||||||
/* Get dataset access property list */
|
/* 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;
|
storage->printf_gap = (hsize_t)0;
|
||||||
|
|
||||||
/* Retrieve VDS file FAPL to layout */
|
/* 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)
|
if((storage->source_fapl = H5F_get_access_plist(f, FALSE)) < 0)
|
||||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get fapl")
|
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 */
|
/* Copy DAPL to layout */
|
||||||
if(storage->source_dapl <= 0)
|
if(storage->source_dapl <= 0)
|
||||||
if((storage->source_dapl = H5P_copy_plist(dapl, FALSE)) < 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) */
|
* unlimited/printf selections) */
|
||||||
storage->init = FALSE;
|
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:
|
done:
|
||||||
FUNC_LEAVE_NOAPI(ret_value)
|
FUNC_LEAVE_NOAPI(ret_value)
|
||||||
} /* end H5D__virtual_init() */
|
} /* 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;
|
storage = &io_info->dset->shared->layout.storage.u.virt;
|
||||||
HDassert((storage->view == H5D_VDS_FIRST_MISSING) || (storage->view == H5D_VDS_LAST_AVAILABLE));
|
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 */
|
/* Prepare for I/O operation */
|
||||||
if(H5D__virtual_pre_io(io_info, storage, file_space, mem_space, &tot_nelmts) < 0)
|
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")
|
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;
|
storage = &io_info->dset->shared->layout.storage.u.virt;
|
||||||
HDassert((storage->view == H5D_VDS_FIRST_MISSING) || (storage->view == H5D_VDS_LAST_AVAILABLE));
|
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 */
|
/* Prepare for I/O operation */
|
||||||
if(H5D__virtual_pre_io(io_info, storage, file_space, mem_space, &tot_nelmts) < 0)
|
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")
|
HGOTO_ERROR(H5E_DATASET, H5E_CANTCLIP, FAIL, "unable to prepare for I/O operation")
|
||||||
|
|||||||
232
src/H5FDmpio.c
232
src/H5FDmpio.c
@@ -59,6 +59,24 @@ static char H5FD_mpi_native_g[] = "native";
|
|||||||
*/
|
*/
|
||||||
typedef struct H5FD_mpio_t {
|
typedef struct H5FD_mpio_t {
|
||||||
H5FD_t pub; /*public stuff, must be first */
|
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_File f; /*MPIO file handle */
|
||||||
MPI_Comm comm; /*communicator */
|
MPI_Comm comm; /*communicator */
|
||||||
MPI_Info info; /*file information */
|
MPI_Info info; /*file information */
|
||||||
@@ -78,8 +96,9 @@ static void *H5FD__mpio_fapl_get(H5FD_t *_file);
|
|||||||
static void *H5FD__mpio_fapl_copy(const void *_old_fa);
|
static void *H5FD__mpio_fapl_copy(const void *_old_fa);
|
||||||
static herr_t H5FD__mpio_fapl_free(void *_fa);
|
static herr_t H5FD__mpio_fapl_free(void *_fa);
|
||||||
static H5FD_t *H5FD__mpio_open(const char *name, unsigned flags, hid_t fapl_id,
|
static H5FD_t *H5FD__mpio_open(const char *name, unsigned flags, hid_t fapl_id,
|
||||||
haddr_t maxaddr);
|
haddr_t maxaddr);
|
||||||
static herr_t H5FD__mpio_close(H5FD_t *_file);
|
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 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 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);
|
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 */
|
NULL, /*dxpl_free */
|
||||||
H5FD__mpio_open, /*open */
|
H5FD__mpio_open, /*open */
|
||||||
H5FD__mpio_close, /*close */
|
H5FD__mpio_close, /*close */
|
||||||
NULL, /*cmp */
|
H5FD__mpio_cmp, /*cmp */
|
||||||
H5FD__mpio_query, /*query */
|
H5FD__mpio_query, /*query */
|
||||||
NULL, /*get_type_map */
|
NULL, /*get_type_map */
|
||||||
NULL, /*alloc */
|
NULL, /*alloc */
|
||||||
@@ -907,6 +926,87 @@ done:
|
|||||||
FUNC_LEAVE_NOAPI(ret_value)
|
FUNC_LEAVE_NOAPI(ret_value)
|
||||||
} /* end H5FD_get_mpio_atomicity() */
|
} /* 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
|
* 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->eof = H5FD_mpi_MPIOff_to_haddr(size);
|
||||||
file->local_eof = file->eof;
|
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 */
|
/* Set return value */
|
||||||
ret_value = (H5FD_t*)file;
|
ret_value = (H5FD_t*)file;
|
||||||
|
|
||||||
@@ -1062,6 +1167,129 @@ done:
|
|||||||
FUNC_LEAVE_NOAPI(ret_value)
|
FUNC_LEAVE_NOAPI(ret_value)
|
||||||
} /* end H5FD__mpio_open() */
|
} /* 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
|
* Function: H5FD__mpio_close
|
||||||
|
|||||||
19
src/H5Fint.c
19
src/H5Fint.c
@@ -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)))
|
if(NULL == (drvr = H5FD_get_class(fapl_id)))
|
||||||
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "unable to retrieve VFL class")
|
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "unable to retrieve VFL class")
|
||||||
|
|
||||||
/* Check the environment variable that determines if we care
|
/* Check for file locking disabled internally, then check the environment
|
||||||
* about file locking. File locking should be used unless explicitly
|
* variable that determines if we care about file locking. File locking
|
||||||
* disabled.
|
* should be used unless explicitly disabled.
|
||||||
*/
|
*/
|
||||||
lock_env_var = HDgetenv("HDF5_USE_FILE_LOCKING");
|
#ifdef H5_HAVE_PARALLEL
|
||||||
if(lock_env_var && !HDstrcmp(lock_env_var, "FALSE"))
|
if(H5CX_get_disable_file_locking())
|
||||||
use_file_locking = FALSE;
|
use_file_locking = FALSE;
|
||||||
else
|
else
|
||||||
use_file_locking = TRUE;
|
#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
|
* Opening a file is a two step process. First we try to open the
|
||||||
|
|||||||
@@ -679,7 +679,15 @@ H5O__layout_encode(H5F_t *f, hbool_t H5_ATTR_UNUSED disable_shared, uint8_t *p,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case H5D_VIRTUAL:
|
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);
|
H5F_addr_encode(f, &p, mesg->storage.u.virt.serial_list_hobjid.addr);
|
||||||
UINT32ENCODE(p, mesg->storage.u.virt.serial_list_hobjid.idx);
|
UINT32ENCODE(p, mesg->storage.u.virt.serial_list_hobjid.idx);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -432,6 +432,9 @@ typedef struct H5O_efl_t {
|
|||||||
* and 'size' callbacks for places to change when updating this. */
|
* and 'size' callbacks for places to change when updating this. */
|
||||||
#define H5O_LAYOUT_VERSION_LATEST H5O_LAYOUT_VERSION_4
|
#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 */
|
/* Forward declaration of structs used below */
|
||||||
struct H5D_layout_ops_t; /* Defined in H5Dpkg.h */
|
struct H5D_layout_ops_t; /* Defined in H5Dpkg.h */
|
||||||
struct H5D_chunk_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_source_select; /* Clipped version of source_select */
|
||||||
struct H5S_t *clipped_virtual_select; /* Clipped version of virtual_select */
|
struct H5S_t *clipped_virtual_select; /* Clipped version of virtual_select */
|
||||||
struct H5D_t *dset; /* Source dataset */
|
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 */
|
/* 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 */
|
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 */
|
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 source_space_status; /* Extent patching status of source_select */
|
||||||
H5O_virtual_space_status_t virtual_space_status; /* Extent patching status of virtual_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;
|
} H5O_storage_virtual_ent_t;
|
||||||
|
|
||||||
typedef struct H5O_storage_virtual_t {
|
typedef struct H5O_storage_virtual_t {
|
||||||
|
|||||||
@@ -1478,6 +1478,7 @@ H5S__mpio_create_large_type(hsize_t num_elements, MPI_Aint stride_bytes,
|
|||||||
int block_len[2];
|
int block_len[2];
|
||||||
int mpi_code; /* MPI return code */
|
int mpi_code; /* MPI return code */
|
||||||
MPI_Datatype inner_type, outer_type, leftover_type, type[2];
|
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;
|
MPI_Aint disp[2], old_extent;
|
||||||
herr_t ret_value = SUCCEED; /* Return value */
|
herr_t ret_value = SUCCEED; /* Return value */
|
||||||
|
|
||||||
|
|||||||
@@ -1713,6 +1713,8 @@ H5S_select_shape_same(const H5S_t *space1, const H5S_t *space2)
|
|||||||
/* Check for different number of elements selected */
|
/* Check for different number of elements selected */
|
||||||
if(H5S_GET_SELECT_NPOINTS(space1) != H5S_GET_SELECT_NPOINTS(space2))
|
if(H5S_GET_SELECT_NPOINTS(space1) != H5S_GET_SELECT_NPOINTS(space2))
|
||||||
HGOTO_DONE(FALSE)
|
HGOTO_DONE(FALSE)
|
||||||
|
else if (space1 == space2)
|
||||||
|
HGOTO_DONE(TRUE);
|
||||||
|
|
||||||
/* Check special cases if both dataspaces aren't scalar */
|
/* Check special cases if both dataspaces aren't scalar */
|
||||||
/* (If only one is, the number of selected points check is sufficient) */
|
/* (If only one is, the number of selected points check is sufficient) */
|
||||||
|
|||||||
@@ -67,6 +67,8 @@ set (H5P_TESTS
|
|||||||
t_pread
|
t_pread
|
||||||
t_pshutdown
|
t_pshutdown
|
||||||
t_prestart
|
t_prestart
|
||||||
|
t_psubfile
|
||||||
|
t_pvds
|
||||||
t_init_term
|
t_init_term
|
||||||
t_shapesame
|
t_shapesame
|
||||||
t_filters_parallel
|
t_filters_parallel
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ check_SCRIPTS = $(TEST_SCRIPT_PARA)
|
|||||||
|
|
||||||
# Test programs. These are our main targets.
|
# 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
|
# t_pflush1 and t_pflush2 are used by testpflush.sh
|
||||||
check_PROGRAMS = $(TEST_PROG_PARA) t_pflush1 t_pflush2
|
check_PROGRAMS = $(TEST_PROG_PARA) t_pflush1 t_pflush2
|
||||||
|
|||||||
1007
testpar/t_psubfile.c
Normal file
1007
testpar/t_psubfile.c
Normal file
File diff suppressed because it is too large
Load Diff
6892
testpar/t_pvds.c
Normal file
6892
testpar/t_pvds.c
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user