summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/H5CX.c57
-rw-r--r--src/H5CXprivate.h2
-rw-r--r--src/H5Dvirtual.c119
-rw-r--r--src/H5FDmpio.c232
-rw-r--r--src/H5Fint.c19
-rw-r--r--src/H5Olayout.c10
-rw-r--r--src/H5Oprivate.h6
-rw-r--r--src/H5Smpio.c1
-rw-r--r--src/H5Sselect.c2
9 files changed, 402 insertions, 46 deletions
diff --git a/src/H5CX.c b/src/H5CX.c
index 22ed893..2287805 100644
--- a/src/H5CX.c
+++ b/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 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 */
@@ -1665,6 +1668,32 @@ H5CX_get_mpi_file_flushing(void)
/*-------------------------------------------------------------------------
+ * 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
*
* Purpose: Retrieves if the dataset meets read-with-rank0-and-bcast requirements for the current API call context.
@@ -2809,6 +2838,34 @@ H5CX_set_mpi_file_flushing(hbool_t 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
*
* Purpose: Sets the "dataset meets read-with-rank0-and-bcast requirements" flag for the current API call context.
diff --git a/src/H5CXprivate.h b/src/H5CXprivate.h
index 638c32a..91316e4 100644
--- a/src/H5CXprivate.h
+++ b/src/H5CXprivate.h
@@ -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 */
diff --git a/src/H5Dvirtual.c b/src/H5Dvirtual.c
index 53640e7..61e67f9 100644
--- a/src/H5Dvirtual.c
+++ b/src/H5Dvirtual.c
@@ -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 */
+#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")
diff --git a/src/H5FDmpio.c b/src/H5FDmpio.c
index d5aa170..50b5676 100644
--- a/src/H5FDmpio.c
+++ b/src/H5FDmpio.c
@@ -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 */
@@ -78,8 +96,9 @@ static void *H5FD__mpio_fapl_get(H5FD_t *_file);
static void *H5FD__mpio_fapl_copy(const void *_old_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,
- haddr_t maxaddr);
+ 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;
@@ -1064,6 +1169,129 @@ done:
/*-------------------------------------------------------------------------
+ * 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
*
* Purpose: Closes a file. This is collective.
diff --git a/src/H5Fint.c b/src/H5Fint.c
index 030fda8..bb092f3 100644
--- a/src/H5Fint.c
+++ b/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)))
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.
*/
- lock_env_var = HDgetenv("HDF5_USE_FILE_LOCKING");
- if(lock_env_var && !HDstrcmp(lock_env_var, "FALSE"))
+#ifdef H5_HAVE_PARALLEL
+ if(H5CX_get_disable_file_locking())
use_file_locking = FALSE;
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
diff --git a/src/H5Olayout.c b/src/H5Olayout.c
index 138f219..25cae05 100644
--- a/src/H5Olayout.c
+++ b/src/H5Olayout.c
@@ -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;
diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h
index 5987ecf..46e2845 100644
--- a/src/H5Oprivate.h
+++ b/src/H5Oprivate.h
@@ -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 {
diff --git a/src/H5Smpio.c b/src/H5Smpio.c
index aeec566..35daed1 100644
--- a/src/H5Smpio.c
+++ b/src/H5Smpio.c
@@ -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 */
diff --git a/src/H5Sselect.c b/src/H5Sselect.c
index c383fed..fdd897c 100644
--- a/src/H5Sselect.c
+++ b/src/H5Sselect.c
@@ -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) */