summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MANIFEST2
-rw-r--r--release_docs/RELEASE.txt13
-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
-rw-r--r--testpar/CMakeLists.txt2
-rw-r--r--testpar/Makefile.am2
-rw-r--r--testpar/t_psubfile.c1007
-rw-r--r--testpar/t_pvds.c6892
15 files changed, 8319 insertions, 47 deletions
diff --git a/MANIFEST b/MANIFEST
index 3285ec2..01ee8d8 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -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
diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt
index c8061f5..647cb8f 100644
--- a/release_docs/RELEASE.txt
+++ b/release_docs/RELEASE.txt
@@ -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.
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) */
diff --git a/testpar/CMakeLists.txt b/testpar/CMakeLists.txt
index 1aecef6..95ff0de 100644
--- a/testpar/CMakeLists.txt
+++ b/testpar/CMakeLists.txt
@@ -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
diff --git a/testpar/Makefile.am b/testpar/Makefile.am
index 0e7898e..da2fd36 100644
--- a/testpar/Makefile.am
+++ b/testpar/Makefile.am
@@ -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
diff --git a/testpar/t_psubfile.c b/testpar/t_psubfile.c
new file mode 100644
index 0000000..0180902
--- /dev/null
+++ b/testpar/t_psubfile.c
@@ -0,0 +1,1007 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/************************************************************
+
+ This example illustrates the concept of virtual dataset
+ and is used to simulate the access patterns envisiond for
+ HDF5 subfiling. The program creates a collection of 2-dim source
+ datasets and writes data to them. Each source dataset is collectively
+ generated by either 1 or 2 process ranks which are split off from the
+ parallel MPI_COMM_WORLD group. It then collectively creates a 2-dim
+ virtual dataset utilizing all MPI process ranks and maps each row of this
+ virtual dataset to a rank specific row of data in the previously
+ created source datasets.
+
+ The program closes all datasets, and then reopens the virtual
+ dataset, and finds and prints its creation properties.
+ Then it reads the values.
+
+ This file is intended for use with HDF5 Library version 1.10
+
+ ************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "hdf5.h"
+
+int mpi_rank;
+int mpi_size;
+int nerrors = 0;
+
+int mpi_global_rank;
+int mpi_global_size;
+
+#include "testpar.h"
+
+#define NFILENAMES 4
+
+const char *FILENAMES[NFILENAMES + 1]={"subfile_a",
+ "subfile_b",
+ "subfile_c",
+ "subfile_d",
+ NULL};
+
+const char *DSETNAMES[NFILENAMES + 1]={"A",
+ "B",
+ "C",
+ "D",
+ NULL};
+
+
+#define FILENAME_BUF_SIZE 1024
+
+#define RANK_ELEMENTS 100
+
+#define VDSFILE "subfile_vds.h5"
+#define DATASET "VDS"
+#define RANK2 2
+
+/* The following can be used for file cleanup
+ * after running the test.
+ */
+const char *SRC_FILE[] = {
+ "subfile_a.h5",
+ "subfile_b.h5",
+ "subfile_c.h5",
+ "subfile_d.h5"
+};
+
+const char *SRC_DATASET[] = {
+ "A",
+ "B",
+ "C"
+};
+
+
+
+/*
+ * The following are various utility routines used by the tests.
+ */
+
+/* Hyperslab layout styles */
+#define BYROW 1 /* divide into slabs of rows */
+#define BYCOL 2 /* divide into blocks of columns */
+#define ZROW 3 /* same as BYCOL except process 0 gets 0 rows */
+#define ZCOL 4 /* same as BYCOL except process 0 gets 0 columns */
+
+/*
+ * Setup the dimensions of the hyperslab.
+ * Two modes--by rows or by columns.
+ * Assume dimension rank is 2.
+ * BYROW divide into slabs of rows
+ * BYCOL divide into blocks of columns
+ * ZROW same as BYROW except process 0 gets 0 rows
+ * ZCOL same as BYCOL except process 0 gets 0 columns
+ */
+static void
+slab_set(hsize_t dim0, hsize_t dim1, hsize_t start[], hsize_t count[],
+ hsize_t stride[], hsize_t block[], int mode)
+{
+ switch (mode){
+ case BYROW:
+ /* Each process takes a slabs of rows. */
+ block[0] = dim0/(hsize_t)mpi_size;
+ block[1] = dim1;
+ stride[0] = block[0];
+ stride[1] = block[1];
+ count[0] = 1;
+ count[1] = 1;
+ start[0] = (hsize_t)mpi_rank*block[0];
+ start[1] = 0;
+ break;
+
+ case BYCOL:
+ /* Each process takes a block of columns. */
+ block[0] = dim0;
+ block[1] = dim1/(hsize_t)mpi_size;
+ stride[0] = block[0];
+ stride[1] = block[1];
+ count[0] = 1;
+ count[1] = 1;
+ start[0] = 0;
+ start[1] = (hsize_t)mpi_rank*block[1];
+ break;
+
+ case ZROW:
+ /* Similar to BYROW except process 0 gets 0 row */
+ block[0] = (mpi_rank ? dim0/(hsize_t)mpi_size : 0);
+ block[1] = dim1;
+ stride[0] = (mpi_rank ? block[0] : 1); /* avoid setting stride to 0 */
+ stride[1] = block[1];
+ count[0] = 1;
+ count[1] = 1;
+ start[0] = (mpi_rank? (hsize_t)mpi_rank*block[0] : 0);
+ start[1] = 0;
+ break;
+
+ case ZCOL:
+ /* Similar to BYCOL except process 0 gets 0 column */
+ block[0] = dim0;
+ block[1] = (mpi_rank ? dim1/(hsize_t)mpi_size : 0);
+ stride[0] = block[0];
+ stride[1] = (mpi_rank ? block[1] : 1); /* avoid setting stride to 0 */
+ count[0] = 1;
+ count[1] = 1;
+ start[0] = 0;
+ start[1] = (mpi_rank? (hsize_t)mpi_rank*block[1] : 0);
+ break;
+
+ default:
+ /* Unknown mode. Set it to cover the whole dataset. */
+ block[0] = dim0;
+ block[1] = dim1;
+ stride[0] = block[0];
+ stride[1] = block[1];
+ count[0] = 1;
+ count[1] = 1;
+ start[0] = 0;
+ start[1] = 0;
+ if(VERBOSE_MED) printf("slab_set wholeset\n");
+ break;
+ } /* end switch */
+
+ if(VERBOSE_MED){
+ printf("start[]=(%lu,%lu), count[]=(%lu,%lu), stride[]=(%lu,%lu), block[]=(%lu,%lu), total datapoints=%lu\n",
+ (unsigned long)start[0], (unsigned long)start[1], (unsigned long)count[0], (unsigned long)count[1],
+ (unsigned long)stride[0], (unsigned long)stride[1], (unsigned long)block[0], (unsigned long)block[1],
+ (unsigned long)(block[0]*block[1]*count[0]*count[1]));
+ } /* end if */
+} /* end slab_set() */
+
+/* File_Access_type bits */
+#define FACC_DEFAULT 0x0 /* default */
+#define FACC_MPIO 0x1 /* MPIO */
+#define FACC_SPLIT 0x2 /* Split File */
+
+/*
+ * Create the appropriate File access property list
+ */
+static hid_t
+create_faccess_plist(MPI_Comm comm, MPI_Info info, int l_facc_type)
+{
+ hid_t ret_pl = -1;
+ herr_t ret; /* generic return value */
+
+ ret_pl = H5Pcreate (H5P_FILE_ACCESS);
+ VRFY((ret_pl >= 0), "H5P_FILE_ACCESS");
+
+ if(l_facc_type == FACC_DEFAULT)
+ return (ret_pl);
+
+ if(l_facc_type == FACC_MPIO){
+ /* set Parallel access with communicator */
+ ret = H5Pset_fapl_mpio(ret_pl, comm, info);
+ VRFY((ret >= 0), "");
+ ret = H5Pset_all_coll_metadata_ops(ret_pl, TRUE);
+ VRFY((ret >= 0), "");
+ ret = H5Pset_coll_metadata_write(ret_pl, TRUE);
+ VRFY((ret >= 0), "");
+ return(ret_pl);
+ } /* end if */
+
+ if(l_facc_type == (FACC_MPIO | FACC_SPLIT)){
+ hid_t mpio_pl;
+
+ mpio_pl = H5Pcreate (H5P_FILE_ACCESS);
+ VRFY((mpio_pl >= 0), "");
+ /* set Parallel access with communicator */
+ ret = H5Pset_fapl_mpio(mpio_pl, comm, info);
+ VRFY((ret >= 0), "");
+
+ /* setup file access template */
+ ret_pl = H5Pcreate (H5P_FILE_ACCESS);
+ VRFY((ret_pl >= 0), "");
+
+ /* set Parallel access with communicator */
+ ret = H5Pset_fapl_split(ret_pl, ".meta", mpio_pl, ".raw", mpio_pl);
+ VRFY((ret >= 0), "H5Pset_fapl_split succeeded");
+ H5Pclose(mpio_pl);
+ return(ret_pl);
+ } /* end if */
+
+ /* unknown file access types */
+ return ret_pl;
+} /* end create_faccess_plist() */
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: generate_test_files
+ *
+ * Purpose: This function is called to produce HDF5 dataset files
+ * which will eventually be used as the 'src' files in a
+ * containing Virtual Data Set (VDS) file.
+ *
+ * Since data will be read back and validated, we generate
+ * data in a predictable manner rather than randomly.
+ * For now, we simply use the global mpi_rank of the writing
+ * process as a starting component for the data generation.
+ * Subsequent writes are increments from the initial start
+ * value.
+ *
+ * Return: Success: 0
+ *
+ * Failure: 1
+ *
+ * Programmer: Richard Warren
+ * 10/1/17
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+generate_test_files( MPI_Comm comm, int group_id )
+{
+ const char *fcn_name = "generate_test_files()";
+ const char *failure_mssg = NULL;
+ const char *dset_name = NULL;
+
+ char data_filename[FILENAME_BUF_SIZE];
+
+ int i, status;
+ int group_size;
+ int group_rank;
+ int local_failure = 0;
+ int global_failures = 0;
+ int start_value;
+ int written[RANK_ELEMENTS], /* Data to write */
+ retrieved[RANK_ELEMENTS]; /* Data read in */
+
+ hsize_t srcspace_dims[2] = {2, RANK_ELEMENTS};
+ hsize_t memspace_dims[2] = {1, RANK_ELEMENTS};
+ hsize_t start[2]; /* for hyperslab setting */
+ hsize_t count[2], stride[2]; /* for hyperslab setting */
+ hsize_t block[2]; /* for hyperslab setting */
+
+ hsize_t orig_size=RANK_ELEMENTS; /* Original dataset dim size */
+ hid_t fid = -1;
+ hid_t fs; /* File dataspace ID */
+ hid_t ms; /* Memory dataspace ID */
+ hid_t dataset = -1;
+ hid_t fapl = -1;
+ hid_t dcpl = -1;
+ hbool_t pass = true;
+ float *data_slice = NULL;
+ herr_t ret;
+
+ HDassert(comm != MPI_COMM_NULL);
+ status = MPI_Comm_rank(comm, &group_rank);
+ VRFY((status == MPI_SUCCESS), "MPI_Comm_rank succeeded");
+ status = MPI_Comm_size(comm, &group_size);
+ VRFY((status == MPI_SUCCESS), "MPI_Comm_size succeeded");
+
+ /* Some error reporting use the globals: mpi_rank and/or mpi_size */
+ mpi_rank = group_rank;
+ if((mpi_size = group_size) == 1)
+ srcspace_dims[0] = 1;
+
+ /* setup file access template */
+ fapl = create_faccess_plist(comm, MPI_INFO_NULL, FACC_MPIO);
+ VRFY((fapl >= 0), "create_faccess_plist succeeded");
+
+ h5_fixname(FILENAMES[group_id], fapl, data_filename, sizeof data_filename);
+ dset_name =DSETNAMES[group_id];
+ /* -------------------
+ * START AN HDF5 FILE
+ * -------------------*/
+ /* create the file collectively */
+ fid = H5Fcreate(data_filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl);
+ VRFY((fid >= 0), "H5Fcreate succeeded");
+
+ /* Release file-access template */
+ ret = H5Pclose(fapl);
+ VRFY((ret >= 0), "H5Pclose succeeded");
+
+ /* --------------------------------------------------------------
+ * Define the dimensions of the overall datasets and create them.
+ * ------------------------------------------------------------- */
+
+ /* set up dataset storage chunk sizes and creation property list */
+ dcpl = H5Pcreate(H5P_DATASET_CREATE);
+ VRFY((dcpl >= 0), "H5Pcreate succeeded");
+
+ /* setup dimensionality object */
+ /* File space is the global view */
+ fs = H5Screate_simple (2, srcspace_dims, NULL);
+ VRFY((fs >= 0), "H5Screate_simple succeeded");
+
+ /* Collectively create a dataset */
+ dataset = H5Dcreate2(fid, dset_name, H5T_NATIVE_INT, fs, H5P_DEFAULT, dcpl, H5P_DEFAULT);
+ VRFY((dataset >= 0), "H5Dcreate2 succeeded");
+
+ /* release resource */
+ ret = H5Pclose(dcpl);
+ VRFY((ret >= 0), "H5Pclose succeeded");
+
+ slab_set(srcspace_dims[0], srcspace_dims[1], start, count, stride, block, BYROW);
+
+ /* -------------------------
+ * Test writing to dataset
+ * -------------------------*/
+ /* create a memory dataspace independently */
+ /* Memory space is a local view */
+ ms = H5Screate_simple(2, memspace_dims, NULL);
+ VRFY((ms >= 0), "H5Screate_simple succeeded");
+
+ ret = H5Sselect_hyperslab(fs, H5S_SELECT_SET, start, NULL, count, block);
+ VRFY((ret >= 0), "H5Sselect_hyperslab succeeded");
+
+ /* put some trivial (rank specific) data in the data_array */
+ start_value = ((int)(orig_size) * mpi_global_rank);
+ for(i = 0; i < (int)(orig_size); i++)
+ written[i] = start_value + i;
+ MESG("data array initialized");
+ if(VERBOSE_MED) {
+ MESG("writing at offset zero: ");
+ for(i = 0; i < (int)orig_size; i++)
+ printf("%s%d", i?", ":"", written[i]);
+ printf("\n");
+ }
+ ret = H5Dwrite(dataset, H5T_NATIVE_INT, ms, fs, H5P_DEFAULT, written);
+ VRFY((ret >= 0), "H5Dwrite succeeded");
+
+ /* -------------------------
+ * Read initial data from dataset.
+ * -------------------------*/
+ ret = H5Dread(dataset, H5T_NATIVE_INT, ms, fs, H5P_DEFAULT, retrieved);
+ VRFY((ret >= 0), "H5Dread succeeded");
+ for (i=0; i<(int)orig_size; i++)
+ if(written[i]!=retrieved[i]) {
+ printf("Line #%d: written!=retrieved: written[%d]=%d, retrieved[%d]=%d\n",__LINE__,
+ i,written[i], i,retrieved[i]);
+ nerrors++;
+ }
+ if(VERBOSE_MED){
+ MESG("read at offset zero: ");
+ for (i=0; i<(int)orig_size; i++)
+ printf("%s%d", i?", ":"", retrieved[i]);
+ printf("\n");
+ }
+
+ ret = H5Dclose(dataset);
+ VRFY((ret >= 0), "H5Dclose succeeded");
+
+ ret = H5Fclose(fid);
+ VRFY((ret >= 0), "H5Fclose succeeded");
+
+ /* collect results from other processes.
+ * Only overwrite the failure message if no previous error
+ * has been detected
+ */
+ local_failure = ( nerrors > 0 ? 1 : 0 );
+
+ /* This is a global all reduce (NOT group specific) */
+ if(MPI_Allreduce(&local_failure, &global_failures, 1,
+ MPI_INT, MPI_SUM, MPI_COMM_WORLD) != MPI_SUCCESS) {
+ if ( pass ) {
+ pass = FALSE;
+ failure_mssg = "MPI_Allreduce() failed.\n";
+ }
+ } else if ( global_failures > 0 ) {
+ pass = FALSE;
+ failure_mssg = "One or more processes report failure.\n";
+ }
+
+ /* report results */
+ if(mpi_global_rank == 0) {
+ if(pass)
+ HDfprintf(stdout, "Done.\n");
+ else {
+ HDfprintf(stdout, "FAILED.\n");
+ HDfprintf(stdout, "%s: failure_mssg = \"%s\"\n",
+ fcn_name, failure_mssg);
+ } /* end else */
+ } /* end if */
+
+ /* free data_slice if it has been allocated */
+ if(data_slice != NULL) {
+ HDfree(data_slice);
+ data_slice = NULL;
+ } /* end if */
+
+ return !pass;
+} /* end generate_test_file() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: generate_vds_container
+ *
+ * Purpose: Create a parallel VDS container using the source files
+ * previously created in generate_test_files().
+ *
+ * Return: Success: 0
+ *
+ * Failure: 1
+ *
+ * Programmer: Richard Warren
+ * 10/1/17
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+generate_vds_container(MPI_Comm comm)
+{
+ hid_t file, src_space, vspace, dset; /* Handles */
+ hid_t odd_space = -1;
+ hid_t fapl;
+ hid_t dcpl;
+ herr_t status;
+ hsize_t n_elements = RANK_ELEMENTS;
+ hsize_t vdsdims[2] = {2, RANK_ELEMENTS}, /* Virtual datasets dimension */
+ srcdims[2] = {2, RANK_ELEMENTS}, /* Source datasets dimensions */
+ extradims[2] = {1, RANK_ELEMENTS},
+ start[2], /* Hyperslab parameters */
+ count[2],
+ block[2];
+ hsize_t start_out[2],
+ stride_out[2],
+ count_out[2],
+ block_out[2];
+ int *rdata;
+ int expected = 0;
+ int i, j, k, l;
+ int fill_value = -1; /* Fill value for VDS */
+ int local_failure = 0;
+ int global_failures = 0;
+ int group_size;
+ int group_rank;
+ int n_groups;
+
+ H5D_layout_t layout; /* Storage layout */
+ size_t num_map; /* Number of mappings */
+ size_t len; /* Length of the string; also a return value */
+ char *filename;
+ char *dsetname;
+ hssize_t nblocks;
+ hsize_t *buf = NULL; /* Buffer to hold hyperslab coordinates */
+
+ HDassert(comm != MPI_COMM_NULL);
+ status = MPI_Comm_rank(comm, &group_rank);
+ VRFY((status == MPI_SUCCESS), "MPI_Comm_rank succeeded");
+ status = MPI_Comm_size(comm, &group_size);
+ VRFY((status == MPI_SUCCESS), "MPI_Comm_size succeeded");
+
+ n_groups = group_size/2;
+ vdsdims[0] = (hsize_t)group_size; /* [mpi_size][RANK_ELEMENTS] */
+
+ /* setup for error reporting and slab_set() */
+ mpi_rank = group_rank;
+ mpi_size = group_size;
+ n_elements = (hsize_t)mpi_size * vdsdims[1];
+
+ /* setup file access template */
+ fapl = create_faccess_plist(comm, MPI_INFO_NULL, FACC_MPIO);
+ VRFY((fapl >= 0), "create_faccess_plist succeeded");
+
+ /* Create file in which virtual dataset will be stored. */
+ file = H5Fcreate (VDSFILE, H5F_ACC_TRUNC, H5P_DEFAULT, fapl);
+ VRFY((file >= 0), "H5Fcreate succeeded");
+
+ /* Create VDS dataspace. */
+ vspace = H5Screate_simple (RANK2, vdsdims, NULL);
+ VRFY((vspace >= 0), "H5Screate_simple succeeded");
+
+ /* Set VDS creation property. */
+ dcpl = H5Pcreate (H5P_DATASET_CREATE);
+ VRFY((dcpl >= 0), "H5Pcreate succeeded");
+
+ status = H5Pset_fill_value (dcpl, H5T_NATIVE_INT, &fill_value);
+ VRFY((status >= 0), "H5Pset_fill_value succeeded");
+
+ start[0] = 0;
+ start[1] = 0;
+ count[0] = 1;
+ count[1] = 1;
+ block[0] = 2;
+ block[1] = 100;
+
+ /*
+ * Build the mappings.
+ * Selections in the source datasets are H5S_ALL.
+ * In the virtual dataset we select the first, the second and the third rows
+ * and map each row to the data in the corresponding source dataset.
+ */
+ src_space = H5Screate_simple (RANK2, srcdims, NULL);
+ VRFY((src_space >= 0), "H5Screate_simple succeeded");
+
+ /* Each src dataset is a 2D array (2 x 100)
+ * and we want to select the entire space.
+ * The exception to this is if there are an ODD number
+ * of MPI ranks; which forced us to create 1 additional
+ * dataset of size (1 x 100).
+ */
+ status = H5Sselect_hyperslab(src_space, H5S_SELECT_SET, start, NULL, count, block);
+ VRFY((status >= 0), "H5Sselect_hyperslab succeeded");
+
+ for(i = 0; i < n_groups; i++) {
+ start[0] = (hsize_t)i*2;
+ /* Select i-th row in the virtual dataset; selection in the source datasets is the same. */
+ status = H5Sselect_hyperslab (vspace, H5S_SELECT_SET, start, NULL, count, block);
+ VRFY((status >= 0), "H5Sselect_hyperslab succeeded");
+ status = H5Pset_virtual (dcpl, vspace, SRC_FILE[i], SRC_DATASET[i], src_space);
+ VRFY((status >= 0), "H5Pset_virtual succeeded");
+ } /* end for */
+
+ /* A final source file is added if the group size is odd {1,3,5} */
+ if(group_size % 2) {
+ block[0] = 1;
+ srcdims[0] = 1;
+ odd_space = H5Screate_simple (RANK2, extradims, NULL);
+ VRFY((odd_space >= 0), "H5Screate_simple succeeded");
+ start[0] += 2;
+ status = H5Sselect_hyperslab(src_space, H5S_SELECT_SET, start, NULL, count, block);
+ VRFY((status >= 0), "H5Sselect_hyperslab succeeded");
+ status = H5Sselect_hyperslab (vspace, H5S_SELECT_SET, start, NULL, count, block);
+ VRFY((status >= 0), "H5Sselect_hyperslab succeeded");
+ status = H5Pset_virtual (dcpl, vspace, SRC_FILE[i], SRC_DATASET[i], odd_space);
+ VRFY((status >= 0), "H5Pset_virtual succeeded");
+ } /* end if */
+
+ /* Create a virtual dataset. */
+ dset = H5Dcreate2 (file, DATASET, H5T_NATIVE_INT, vspace, H5P_DEFAULT, dcpl, H5P_DEFAULT);
+ VRFY((dset >= 0), "H5Dcreate2 succeeded");
+ status = H5Sclose (vspace);
+ VRFY((status >= 0), "H5Sclose succeeded");
+ status = H5Sclose (src_space);
+ VRFY((status >= 0), "H5Sclose succeeded");
+ if(odd_space >= 0) {
+ status = H5Sclose (odd_space);
+ VRFY((status >= 0), "H5Sclose succeeded");
+ } /* end if */
+ status = H5Dclose (dset);
+ VRFY((status >= 0), "H5Dclose succeeded");
+ status = H5Fclose (file);
+ VRFY((status >= 0), "H5Fclose succeeded");
+
+ /*
+ * Now we begin the read section of this example.
+ */
+
+ /*
+ * Open the file and virtual dataset.
+ */
+ file = H5Fopen (VDSFILE, H5F_ACC_RDONLY, fapl);
+ VRFY((file >= 0), "H5Fopen succeeded");
+ dset = H5Dopen2 (file, DATASET, H5P_DEFAULT);
+ VRFY((dset >= 0), "H5Dopen2 succeeded");
+
+ /*
+ * Get creation property list and mapping properties.
+ */
+ dcpl = H5Dget_create_plist (dset);
+ VRFY((dcpl >= 0), "H5Dget_create_plist succeeded");
+
+ /*
+ * Get storage layout.
+ */
+ layout = H5Pget_layout (dcpl);
+ if(group_rank == 0) {
+ if (H5D_VIRTUAL == layout)
+ printf(" Dataset has a virtual layout \n");
+ else
+ printf(" Wrong layout found \n");
+ } /* end if */
+
+ /*
+ * Find the number of mappings.
+ */
+ status = H5Pget_virtual_count (dcpl, &num_map);
+ VRFY((status >= 0), "H5Pget_virtual_count succeeded");
+ if(group_rank == 0)
+ printf(" Number of mappings is %lu\n", (unsigned long)num_map);
+
+ /*
+ * Get mapping parameters for each mapping.
+ */
+ for(i = 0; i < (int)num_map; i++) {
+ if (group_rank == 0) {
+ printf(" Mapping %d \n", i);
+ printf(" Selection in the virtual dataset ");
+ } /* end if */
+
+ /* Get selection in the virtual dataset */
+ vspace = H5Pget_virtual_vspace (dcpl, (size_t)i);
+ VRFY((vspace >= 0), "H5Pget_virtual_vspace succeeded");
+
+ /* Make sure that this is a hyperslab selection and then print information. */
+ if(H5Sget_select_type(vspace) == H5S_SEL_HYPERSLABS) {
+ nblocks = H5Sget_select_hyper_nblocks (vspace);
+ buf = (hsize_t *)malloc(sizeof(hsize_t)*2*RANK2*(hsize_t)nblocks);
+ status = H5Sget_select_hyper_blocklist(vspace, (hsize_t)0, (hsize_t)nblocks, buf);
+ if(group_rank == 0) {
+ for(l=0; l<nblocks; l++) {
+ printf("(");
+ for (k=0; k<RANK2-1; k++)
+ printf("%d,", (int)buf[k]);
+ printf("%d ) - (", (int)buf[k]);
+ for (k=0; k<RANK2-1; k++)
+ printf("%d,", (int)buf[RANK2+k]);
+ printf("%d)\n", (int)buf[RANK2+k]);
+ } /* end for */
+ } /* end if */
+
+ /* We also can use new APIs to get start, stride, count and block */
+ if(H5Sis_regular_hyperslab(vspace)) {
+ status = H5Sget_regular_hyperslab (vspace, start_out, stride_out, count_out, block_out);
+ if(group_rank == 0) {
+ printf(" start = [%llu, %llu] \n", (unsigned long long)start_out[0], (unsigned long long)start_out[1]);
+ printf(" stride = [%llu, %llu] \n", (unsigned long long)stride_out[0], (unsigned long long)stride_out[1]);
+ printf(" count = [%llu, %llu] \n", (unsigned long long)count_out[0], (unsigned long long)count_out[1]);
+ printf(" block = [%llu, %llu] \n", (unsigned long long)block_out[0], (unsigned long long)block_out[1]);
+ } /* end if */
+ } /* end if */
+ } /* end if */
+
+ /* Get source file name. */
+ len = (size_t)H5Pget_virtual_filename (dcpl, (size_t)i, NULL, 0);
+ filename = (char *)malloc(len*sizeof(char)+1);
+ H5Pget_virtual_filename (dcpl, (size_t)i, filename, len+1);
+ if(group_rank == 0)
+ printf(" Source filename %s\n", filename);
+
+ /* Get source dataset name. */
+ len = (size_t)H5Pget_virtual_dsetname (dcpl, (size_t)i, NULL, 0);
+ dsetname = (char *)malloc((size_t)len*sizeof(char)+1);
+ H5Pget_virtual_dsetname (dcpl, (size_t)i, dsetname, len+1);
+ if(group_rank == 0)
+ printf(" Source dataset name %s\n", dsetname);
+
+ /* Get selection in the source dataset. */
+ if(group_rank == 0)
+ printf(" Selection in the source dataset ");
+ src_space = H5Pget_virtual_srcspace (dcpl, (size_t)i);
+
+ /* Make sure it is ALL selection and then print the coordinates. */
+ if(H5Sget_select_type(src_space) == H5S_SEL_ALL) {
+ if (group_rank == 0)
+ printf("(0) - (99) \n");
+ } /* end if */
+ if (group_rank == 0)
+ puts("");
+ H5Sclose(vspace);
+ H5Sclose(src_space);
+ free(filename);
+ free(dsetname);
+ free(buf);
+ } /* end for */
+
+ /*
+ * Read the data using the default properties.
+ */
+ rdata = (int *)malloc(sizeof(int)*n_elements);
+ VRFY((rdata != NULL), "malloc succeeded");
+
+ status = H5Dread (dset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, rdata);
+ VRFY((status >= 0), "H5Dread succeeded");
+ /* MPI rank 0 does the validation check */
+ if(mpi_global_rank == 0) {
+ expected = 0;
+ k=0;
+ for(i=0; i< (int)vdsdims[0]; i++) {
+ for(j=0; j<(int)vdsdims[1]; j++) {
+ if (rdata[k++] != expected++)
+ local_failure++;
+ } /* end for */
+ } /* end for */
+ } /* end if */
+
+ /*
+ * Close and release resources.
+ */
+ status = H5Pclose (dcpl);
+ status = H5Dclose (dset);
+ status = H5Fclose (file);
+
+ /* collect results from other processes.
+ * Only overwrite the failure message if no previous error
+ * has been detected
+ */
+
+ status = MPI_Allreduce( &local_failure, &global_failures, 1,
+ MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+
+ VRFY((status == MPI_SUCCESS), "MPI_Allreduce succeeded");
+
+ return global_failures;
+} /* end generate_vds_container() */
+
+/* #define SERIAL_ACCESS */
+
+/*-------------------------------------------------------------------------
+ * Function: independent_read_vds
+ *
+ * Purpose: Each mpi process reads 1/Nth of the data contained in a
+ * VDS file previously created by generate_vds_container().
+ * The 'N' in this case is the number of parallel ranks in
+ * MPI_COMM_WORLD.
+ * The function reads thru the VDS file (as opposed to reading
+ * the component 'source' files) and is treated as a normal
+ * HDF5 dataset.
+ *
+ * Return: Success: 0
+ *
+ * Failure: 1
+ *
+ * Programmer: Richard Warren
+ * 10/1/17
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+independent_read_vds(MPI_Comm comm)
+{
+ int status;
+ int expected = 100;
+ int local_failure = 0;
+ int global_failures = 0;
+ hid_t vfile = -1; /* File with virtual dset */
+ hid_t vdset = -1; /* Virtual dataset */
+ hid_t fapl;
+ hid_t file_dataspace; /* File dataspace ID */
+ hid_t mem_dataspace; /* memory dataspace ID */
+
+ hsize_t vdsdims[2] = {2, RANK_ELEMENTS}; /* Virtual datasets dimension */
+ hsize_t stride[2],
+ start[2], /* Hyperslab parameters */
+ count[2],
+ block[2];
+ int rdata[8][RANK_ELEMENTS];
+ int i;
+ herr_t ret;
+
+
+ HDassert(comm != MPI_COMM_NULL);
+ status = MPI_Comm_rank(comm, &mpi_rank);
+ VRFY((status == MPI_SUCCESS), "MPI_Comm_rank succeeded");
+ status = MPI_Comm_size(comm, &mpi_size);
+ VRFY((status == MPI_SUCCESS), "MPI_Comm_size succeeded");
+
+
+ /* setup file access template */
+ fapl = create_faccess_plist(comm, MPI_INFO_NULL, FACC_MPIO);
+ VRFY((fapl >= 0), "create_faccess_plist succeeded");
+
+ /* The VDS is a 2D object containing 'mpi_size' rows
+ * with 'RANK_ELEMENTS' number of columns.
+ *
+ */
+ vdsdims[0] = (hsize_t)mpi_size;
+ slab_set(vdsdims[0], vdsdims[1], start, count, stride, block, BYROW);
+#ifdef SERIAL_ACCESS
+ if (mpi_rank != 0) {
+ MPI_Status stat;
+ int flag=0;
+ MPI_Recv(&flag, 1, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, comm, &stat);
+ }
+ vfile = H5Fopen(VDSFILE, H5F_ACC_RDWR, H5P_DEFAULT);
+#else
+ vfile = H5Fopen(VDSFILE, H5F_ACC_RDWR, fapl);
+#endif
+
+ VRFY((vfile >= 0), "H5Fopen succeeded");
+
+ /* No longer need the fapl */
+ ret = H5Pclose(fapl);
+ VRFY((ret >= 0), "H5Pclose succeeded");
+
+ vdset = H5Dopen2(vfile, DATASET, H5P_DEFAULT);
+ VRFY((vdset >= 0), "H5Dopen2 succeeded");
+
+ file_dataspace = H5Dget_space (vdset);
+ VRFY((file_dataspace >= 0), "H5Dget_space succeeded");
+ ret = H5Sselect_hyperslab(file_dataspace, H5S_SELECT_SET, start, stride, count, block);
+ VRFY((ret >= 0), "H5Sset_hyperslab succeeded");
+
+ /* create a memory dataspace independently */
+ mem_dataspace = H5Screate_simple (2, block, NULL);
+ VRFY((mem_dataspace >= 0), "");
+
+
+#ifdef SERIAL_ACCESS
+ ret = H5Dread(vdset, H5T_NATIVE_INT, mem_dataspace, file_dataspace, H5P_DEFAULT, rdata[0]);
+#else
+ ret = H5Dread(vdset, H5T_NATIVE_INT, mem_dataspace, file_dataspace, H5P_DEFAULT, rdata[0]);
+#endif
+ VRFY((ret >= 0), "H5Dread succeeded");
+ ret = H5Dclose(vdset);
+ VRFY((ret >= 0), "H5Dclose succeeded");
+ ret = H5Fclose(vfile);
+ VRFY((ret >= 0), "H5Fclose succeeded");
+
+#ifdef SERIAL_ACCESS
+ {
+ int mpi_next = mpi_rank+1;
+ if (mpi_next < mpi_size)
+ MPI_Send(&mpi_next, 1, MPI_INT, mpi_next, 0x0acc, comm);
+ } /* end block */
+#endif
+ expected *= mpi_rank;
+ for(i=0; i<100; i++) {
+ if(rdata[0][i] != expected++)
+ local_failure++;
+ } /* end for */
+
+ status = MPI_Allreduce( &local_failure, &global_failures, 1,
+ MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+
+ VRFY((status == MPI_SUCCESS), "MPI_Allreduce succeeded");
+
+ return global_failures;
+} /* end independent_read_vds() */
+
+
+int
+main (int argc, char **argv)
+{
+ int nerrs = 0;
+ int which_group = 0;
+ MPI_Comm group_comm = MPI_COMM_NULL;
+
+ if((MPI_Init(&argc, &argv)) != MPI_SUCCESS) {
+ HDfprintf(stderr, "FATAL: Unable to initialize MPI\n");
+ HDexit(EXIT_FAILURE);
+ } /* end if */
+
+ if((MPI_Comm_rank(MPI_COMM_WORLD, &mpi_global_rank)) != MPI_SUCCESS) {
+ HDfprintf(stderr, "FATAL: MPI_Comm_rank returned an error\n");
+ HDexit(EXIT_FAILURE);
+ } /* end if */
+
+ if((MPI_Comm_size(MPI_COMM_WORLD, &mpi_global_size)) != MPI_SUCCESS) {
+ HDfprintf(stderr, "FATAL: MPI_Comm_size returned an error\n");
+ HDexit(EXIT_FAILURE);
+ } /* end if */
+
+ /* Attempt to turn off atexit post processing so that in case errors
+ * happen during the test and the process is aborted, it will not get
+ * hang in the atexit post processing in which it may try to make MPI
+ * calls. By then, MPI calls may not work.
+ */
+ if(H5dont_atexit() < 0)
+ printf("Failed to turn off atexit processing. Continue.\n");
+ H5open();
+ h5_show_hostname();
+
+ mpi_rank = mpi_global_rank;
+ mpi_size = mpi_global_size;
+
+ if((mpi_size < 4) || (mpi_size > 6)) {
+ nerrs++;
+
+ if(mpi_global_rank == 0)
+ HDprintf("MPI size = %d, need at least 4 processes, max = 6. Exiting.\n", mpi_size);
+ goto finish;
+ } /* end if */
+
+ if(mpi_rank == 0) {
+ HDfprintf(stdout, "============================================\n");
+ HDfprintf(stdout, "Subfiling functionality (parallel VDS) tests\n");
+ HDfprintf(stdout, " mpi_size = %d\n", mpi_size);
+ HDfprintf(stdout, "============================================\n");
+ } /* end if */
+
+ /* ------ Create MPI groups of 2 ------
+ *
+ * We split MPI_COMM_WORLD into n groups of size 2.
+ * The resulting communicators will be used to generate
+ * HDF dataset files which in turn will be opened in parallel and the
+ * contents verified in the second read test below.
+ */
+
+ which_group = mpi_rank / 2;
+
+ if((MPI_Comm_split(MPI_COMM_WORLD,
+ which_group,
+ 0,
+ &group_comm)) != MPI_SUCCESS) {
+
+ HDfprintf(stderr, "FATAL: MPI_Comm_split returned an error\n");
+ HDexit(EXIT_FAILURE);
+ } /* end if */
+
+ /* ------ Generate all source files ------ */
+ nerrs += generate_test_files( group_comm, which_group );
+
+ if(nerrs > 0) {
+ if(mpi_global_rank == 0)
+ HDprintf(" SubFile construction failed -- skipping tests.\n");
+ goto finish;
+ } /* end if */
+
+ /* We generate a containing VDS file and read the data
+ * from the multiple containers produced in 'generate_test_files'.
+ */
+ nerrs += generate_vds_container( MPI_COMM_WORLD );
+
+ if(nerrs > 0) {
+ if(mpi_global_rank == 0)
+ HDprintf(" VDS file construction failed -- skipping tests.\n");
+ goto finish;
+ } /* end if */
+
+ nerrs += independent_read_vds( MPI_COMM_WORLD );
+
+ if(nerrs > 0)
+ if(mpi_global_rank == 0)
+ HDprintf(" VDS file independent read failed.\n");
+
+finish:
+ if((group_comm != MPI_COMM_NULL) &&
+ (MPI_Comm_free(&group_comm)) != MPI_SUCCESS)
+ HDfprintf(stderr, "MPI_Comm_free failed!\n");
+
+ /* make sure all processes are finished before final report, cleanup
+ * and exit.
+ */
+ MPI_Barrier(MPI_COMM_WORLD);
+
+ if(mpi_global_rank == 0) { /* only process 0 reports */
+ int i;
+ const char *header = "Subfiling validation tests";
+
+ HDfprintf(stdout, "===================================\n");
+ if(nerrs > 0) {
+ HDfprintf(stdout, "***%s detected %d failures***\n", header, nerrs);
+ H5_FAILED();
+ } /* end if */
+ else {
+ HDfprintf(stdout, "%s finished with no failures\n", header);
+ PASSED();
+ } /* end else */
+ HDfprintf(stdout, "===================================\n");
+
+ /* File cleanup */
+ for(i=0; i<NFILENAMES; i++)
+ HDremove(SRC_FILE[i]);
+ HDremove(VDSFILE);
+ } /* end if */
+
+ /* close HDF5 library */
+ if(H5close() != SUCCEED)
+ HDfprintf(stdout, "H5close() failed. (Ignoring)\n");
+
+ /* MPI_Finalize must be called AFTER H5close which may use MPI calls */
+ MPI_Finalize();
+
+ /* cannot just return (nerrs) because exit code is limited to 1byte */
+ return (nerrs > 0) ? EXIT_FAILURE : EXIT_SUCCESS;
+} /* end main() */
+
diff --git a/testpar/t_pvds.c b/testpar/t_pvds.c
new file mode 100644
index 0000000..56463ff
--- /dev/null
+++ b/testpar/t_pvds.c
@@ -0,0 +1,6892 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Programmer: Neil Fortner <nfortne2@hdfgroup.org>
+ * Monday, February 16, 2015
+ *
+ * Modified by: Richard Warren
+ * to add parallel/collective file-io operations
+ * Purpose: Tests datasets with virtual layout.
+ */
+#include "h5test.h"
+#include "testpar.h"
+#include "H5Dprivate.h" /* For H5D_VIRTUAL_DEF_LIST_SIZE */
+
+typedef enum {
+ TEST_API_BASIC,
+ TEST_API_COPY_PLIST,
+ TEST_API_ENCDEC_PLIST,
+ TEST_API_CREATE_DSET,
+ TEST_API_REOPEN_DSET,
+ TEST_API_REOPEN_FILE,
+ TEST_API_NTESTS
+} test_api_config_t;
+
+const char *FILENAME[] = {
+ "vds_virt_0",
+ "vds_virt_1",
+ "vds_src_0",
+ "vds_src_1",
+ "vds%%_src",
+ "vds_dapl",
+ NULL
+};
+
+
+static int mpi_rank = 0;
+static int mpi_size = 1;
+
+hid_t create_faccess_plist(MPI_Comm comm, MPI_Info info, int l_facc_type);
+
+/* I/O test config flags */
+#define TEST_IO_CLOSE_SRC 0x01u
+#define TEST_IO_DIFFERENT_FILE 0x02u
+#define TEST_IO_REOPEN_VIRT 0x04u
+#define TEST_IO_NTESTS 0x08u
+
+#define LIST_DOUBLE_SIZE (H5D_VIRTUAL_DEF_LIST_SIZE + 1)
+
+#define FILENAME_BUF_SIZE 1024
+
+/* File_Access_type bits */
+#define FACC_DEFAULT 0x0 /* default */
+#define FACC_MPIO 0x1 /* MPIO */
+#define FACC_SPLIT 0x2 /* Split File */
+
+/*
+ * Create the appropriate File access property list
+ */
+hid_t
+create_faccess_plist(MPI_Comm comm, MPI_Info info, int l_facc_type)
+{
+ hid_t ret_pl = -1;
+ herr_t ret; /* generic return value */
+ int this_rank; /* mpi variables */
+ int nerrors = 0;
+
+ /* need the rank for error checking macros */
+ MPI_Comm_rank(MPI_COMM_WORLD, &this_rank);
+
+ ret_pl = H5Pcreate (H5P_FILE_ACCESS);
+ VRFY((ret_pl >= 0), "H5P_FILE_ACCESS");
+
+ if (l_facc_type == FACC_DEFAULT)
+ return (ret_pl);
+
+ if (l_facc_type == FACC_MPIO){
+ /* set Parallel access with communicator */
+ ret = H5Pset_fapl_mpio(ret_pl, comm, info);
+ VRFY((ret >= 0), "");
+ ret = H5Pset_all_coll_metadata_ops(ret_pl, TRUE);
+ VRFY((ret >= 0), "");
+ ret = H5Pset_coll_metadata_write(ret_pl, TRUE);
+ VRFY((ret >= 0), "");
+ return(ret_pl);
+ }
+
+ if (l_facc_type == (FACC_MPIO | FACC_SPLIT)){
+ hid_t mpio_pl;
+
+ mpio_pl = H5Pcreate (H5P_FILE_ACCESS);
+ VRFY((mpio_pl >= 0), "");
+ /* set Parallel access with communicator */
+ ret = H5Pset_fapl_mpio(mpio_pl, comm, info);
+ VRFY((ret >= 0), "");
+
+ /* setup file access template */
+ ret_pl = H5Pcreate (H5P_FILE_ACCESS);
+ VRFY((ret_pl >= 0), "");
+ /* set Parallel access with communicator */
+ ret = H5Pset_fapl_split(ret_pl, ".meta", mpio_pl, ".raw", mpio_pl);
+ VRFY((ret >= 0), "H5Pset_fapl_split succeeded");
+ H5Pclose(mpio_pl);
+ return(ret_pl);
+ }
+
+ /* unknown file access types */
+ return (ret_pl);
+}
+
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: vds_select_equal
+ *
+ * Purpose: Helper function to check if the selections in the two
+ * provided dataspaces are the same.
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Neil Fortner
+ * Monday, March 2, 2015
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static htri_t
+vds_select_equal(hid_t space1, hid_t space2)
+{
+ H5S_sel_type type1;
+ H5S_sel_type type2;
+ hsize_t *buf1 = NULL;
+ hsize_t *buf2 = NULL;
+ size_t i;
+ htri_t ret_value = TRUE;
+
+ /* Get and compare selection types */
+ if((type1 = H5Sget_select_type(space1)) < 0)
+ TEST_ERROR
+ if((type2 = H5Sget_select_type(space2)) < 0)
+ TEST_ERROR
+ if(type1 != type2)
+ return FALSE;
+
+ /* Check selection type */
+ switch(type1) {
+ case H5S_SEL_NONE:
+ case H5S_SEL_ALL:
+ break;
+
+ case H5S_SEL_POINTS:
+ {
+ int rank1;
+ int rank2;
+ hssize_t npoints1;
+ hssize_t npoints2;
+
+ /* Get and compare rank */
+ if((rank1 = H5Sget_simple_extent_ndims(space1)) < 0)
+ TEST_ERROR
+ if((rank2 = H5Sget_simple_extent_ndims(space2)) < 0)
+ TEST_ERROR
+ if(rank1 != rank2)
+ return FALSE;
+
+ /* Get and compare number of points */
+ if((npoints1 = H5Sget_select_elem_npoints(space1)) < 0)
+ TEST_ERROR
+ if((npoints2 = H5Sget_select_elem_npoints(space2)) < 0)
+ TEST_ERROR
+ if(npoints1 != npoints2)
+ return FALSE;
+
+ /* Allocate point lists. Do not return directly afer
+ * allocating, to make sure buffers are freed. */
+ if(NULL == (buf1 = (hsize_t *)HDmalloc((size_t)rank1 * (size_t)npoints1 * sizeof(hsize_t))))
+ TEST_ERROR
+ if(NULL == (buf2 = (hsize_t *)HDmalloc((size_t)rank1 * (size_t)npoints1 * sizeof(hsize_t))))
+ TEST_ERROR
+
+ /* Get and compare point lists */
+ if(H5Sget_select_elem_pointlist(space1, (hsize_t)0, (hsize_t)npoints1, buf1) < 0)
+ TEST_ERROR
+ if(H5Sget_select_elem_pointlist(space2, (hsize_t)0, (hsize_t)npoints1, buf2) < 0)
+ TEST_ERROR
+ for(i = 0; i < ((size_t)rank1 * (size_t)npoints1); i++)
+ if(buf1[i] != buf2[i]) {
+ ret_value = FALSE;
+ break;
+ } /* end if */
+
+ /* Free buffers */
+ HDfree(buf1);
+ buf1 = NULL;
+ HDfree(buf2);
+ buf2 = NULL;
+ } /* end block */
+
+ break;
+
+ case H5S_SEL_HYPERSLABS:
+ {
+ int rank1;
+ int rank2;
+ hssize_t nblocks1;
+ hssize_t nblocks2;
+
+ /* Get and compare rank */
+ if((rank1 = H5Sget_simple_extent_ndims(space1)) < 0)
+ TEST_ERROR
+ if((rank2 = H5Sget_simple_extent_ndims(space2)) < 0)
+ TEST_ERROR
+ if(rank1 != rank2)
+ return FALSE;
+
+ /* Get and compare number of blocks */
+ if((nblocks1 = H5Sget_select_hyper_nblocks(space1)) < 0)
+ TEST_ERROR
+ if((nblocks2 = H5Sget_select_hyper_nblocks(space2)) < 0)
+ TEST_ERROR
+ if(nblocks1 != nblocks2)
+ return FALSE;
+
+ /* Allocate block lists. Do not return directly afer
+ * allocating, to make sure buffers are freed. */
+ if(NULL == (buf1 = (hsize_t *)HDmalloc((size_t)2 * (size_t)rank1 * (size_t)nblocks1 * sizeof(*buf1))))
+ TEST_ERROR
+ if(NULL == (buf2 = (hsize_t *)HDmalloc((size_t)2 * (size_t)rank1 * (size_t)nblocks1 * sizeof(*buf2))))
+ TEST_ERROR
+
+ /* Get and compare block lists */
+ if(H5Sget_select_hyper_blocklist(space1, (hsize_t)0, (hsize_t)nblocks1, buf1) < 0)
+ TEST_ERROR
+ if(H5Sget_select_hyper_blocklist(space2, (hsize_t)0, (hsize_t)nblocks1, buf2) < 0)
+ TEST_ERROR
+ for(i = 0; i < ((size_t)2 * (size_t)rank1 * (size_t)nblocks1); i++)
+ if(buf1[i] != buf2[i]) {
+ ret_value = FALSE;
+ break;
+ } /* end if */
+
+ /* Free buffers */
+ HDfree(buf1);
+ buf1 = NULL;
+ HDfree(buf2);
+ buf2 = NULL;
+ } /* end block */
+
+ break;
+
+ case H5S_SEL_ERROR:
+ case H5S_SEL_N:
+ default:
+ TEST_ERROR
+ } /* end switch */
+
+ return ret_value;
+
+error:
+ if(buf1)
+ HDfree(buf1);
+ if(buf2)
+ HDfree(buf2);
+
+ return -1;
+} /* end vds_select_equal() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: vds_check_mapping
+ *
+ * Purpose: Helper function to check if the ith virtual mapping in the
+ * provided dcpl is the same as that described by the other
+ * parameters.
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Neil Fortner
+ * Monday, March 2, 2015
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+vds_check_mapping(hid_t dcpl, size_t i, hid_t vspace, hid_t srcspace,
+ const char *filename, const char *dsetname)
+{
+ hid_t space_out = -1;
+ char name_out[32];
+ htri_t tri_ret;
+ ssize_t str_len;
+
+ HDassert(dcpl >= 0);
+ HDassert(vspace >= 0);
+ HDassert(srcspace >= 0);
+ HDassert(filename);
+ HDassert(dsetname);
+
+ /* Check vspace */
+ if((space_out = H5Pget_virtual_vspace(dcpl, i)) < 0)
+ TEST_ERROR
+ if((tri_ret = H5Sextent_equal(space_out, vspace)) < 0)
+ TEST_ERROR
+ if(!tri_ret)
+ TEST_ERROR
+ if((tri_ret = vds_select_equal(space_out, vspace)) < 0)
+ TEST_ERROR
+ if(!tri_ret)
+ TEST_ERROR
+ if(H5Sclose(space_out) < 0)
+ TEST_ERROR
+ space_out = -1;
+
+ /* Check srcspace */
+ if((space_out = H5Pget_virtual_srcspace(dcpl, i)) < 0)
+ TEST_ERROR
+ if((tri_ret = vds_select_equal(space_out, srcspace)) < 0)
+ TEST_ERROR
+ if(!tri_ret)
+ TEST_ERROR
+ if(H5Sclose(space_out) < 0)
+ TEST_ERROR
+ space_out = -1;
+
+ /* Check filename */
+ if((str_len = H5Pget_virtual_filename(dcpl, i, NULL, (size_t)0)) < 0)
+ TEST_ERROR
+ if((size_t)str_len != HDstrlen(filename))
+ TEST_ERROR
+ HDassert((size_t)str_len < sizeof(name_out));
+ if((str_len = H5Pget_virtual_filename(dcpl, i, name_out, sizeof(name_out))) < 0)
+ TEST_ERROR
+ if((size_t)str_len != HDstrlen(filename))
+ TEST_ERROR
+ if(HDstrncmp(name_out, filename, (size_t)str_len + 1) != 0)
+ TEST_ERROR
+
+ /* Check dsetname */
+ if((str_len = H5Pget_virtual_dsetname(dcpl, i, NULL, (size_t)0)) < 0)
+ TEST_ERROR
+ if((size_t)str_len != HDstrlen(dsetname))
+ TEST_ERROR
+ HDassert((size_t)str_len < sizeof(name_out));
+ if((str_len = H5Pget_virtual_dsetname(dcpl, i, name_out, sizeof(name_out))) < 0)
+ TEST_ERROR
+ if((size_t)str_len != HDstrlen(dsetname))
+ TEST_ERROR
+ if(HDstrncmp(name_out, dsetname, (size_t)str_len + 1) != 0)
+ TEST_ERROR
+
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ if(space_out >= 0)
+ (void)H5Sclose(space_out);
+ } H5E_END_TRY
+
+ return -1;
+} /* end vds_check_mapping() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_api_get_ex_dcpl
+ *
+ * Purpose: Tests API functions related to virtual datasets.
+ *
+ * Return: Success: 0
+ *
+ * Failure: number of errors
+ *
+ * Programmer: Neil Fortner
+ * Monday, February 16, 2015
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+/* Helper function to get DCPL for examination depending on config */
+static int
+test_api_get_ex_dcpl(test_api_config_t config, hid_t fapl, hid_t dcpl,
+ hid_t *ex_dcpl, hid_t vspace, char *filename, hsize_t exp_meta_size)
+{
+ hid_t file = -1; /* File */
+ hid_t dset = -1; /* Virtual dataset */
+ H5D_space_status_t space_status; /* Dataset space status */
+ void *plist_buf = NULL; /* Serialized property list buffer */
+ H5O_info_t oinfo; /* Object info struct */
+ htri_t tri_ret;
+
+ HDassert((config >= TEST_API_BASIC) && (config < TEST_API_NTESTS));
+ HDassert(fapl >= 0);
+ HDassert(dcpl >= 0);
+ HDassert(ex_dcpl);
+ HDassert(*ex_dcpl < 0);
+ HDassert(vspace >= 0);
+ HDassert(filename);
+
+ /* Take different action depending on test configuration */
+ if(config >= TEST_API_CREATE_DSET) {
+ /* Create file and dataset */
+ if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ TEST_ERROR
+ if((dset = H5Dcreate2(file, "vdset", H5T_NATIVE_INT, vspace, H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Test H5Dget_space_status */
+ if(H5Dget_space_status(dset, &space_status) < 0)
+ TEST_ERROR
+ if(space_status != H5D_SPACE_STATUS_ALLOCATED)
+ TEST_ERROR
+
+ /* Reopen dataset if requested */
+ if(config >= TEST_API_REOPEN_DSET) {
+ /* Close dataset */
+ if(H5Dclose(dset) < 0)
+ TEST_ERROR
+ dset = -1;
+
+ /* Reopen file if requested */
+ if(config == TEST_API_REOPEN_FILE) {
+ if(H5Fclose(file) < 0)
+ TEST_ERROR
+ file = -1;
+ if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Open dataset */
+ if((dset = H5Dopen2(file, "vdset", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Get DCPL from dataset */
+ if((*ex_dcpl = H5Dget_create_plist(dset)) < 0)
+ TEST_ERROR
+
+ /* Test H5Dget_offset() (just returns HADDR_UNDEF) */
+ if(HADDR_UNDEF != H5Dget_offset(dset))
+ TEST_ERROR
+
+ /* Test H5Oget_info returns correct metadata size */
+ if(H5Oget_info2(dset, &oinfo, H5O_INFO_META_SIZE) < 0)
+ TEST_ERROR
+ if(oinfo.meta_size.obj.index_size != (hsize_t)0)
+ TEST_ERROR
+ if(config == TEST_API_REOPEN_FILE) {
+ if (oinfo.meta_size.obj.heap_size != exp_meta_size) {
+ HDprintf("VDS metadata size: %llu Expected: %llu\n",
+ (long long unsigned)oinfo.meta_size.obj.heap_size,
+ (long long unsigned)exp_meta_size);
+ TEST_ERROR
+ } /* end if */
+ } /* end if */
+ else
+ if((oinfo.meta_size.obj.heap_size != exp_meta_size)
+ && (oinfo.meta_size.obj.heap_size != (hsize_t)0))
+ TEST_ERROR
+
+ if(oinfo.meta_size.attr.index_size != (hsize_t)0)
+ TEST_ERROR
+
+ /* Test H5Dget_space_status */
+ if(H5Dget_space_status(dset, &space_status) < 0)
+ TEST_ERROR
+ if(space_status != H5D_SPACE_STATUS_ALLOCATED)
+ TEST_ERROR
+ /* Verify examination DCPL is equal to original DCPL. Do not compare the
+ * plist to itself, and do not do the comparison if we reopened the file,
+ * because in that case the extent of the source dset will not be current.
+ *
+ * RAW - We do a comparison test here, because H5Dclose will eventually
+ * modify the contents of the dcpl property list, e.g. H5O_fill_reset.
+ * We'll disable the comparison test a bit further on when the config is
+ * defined as TEST_API_REOPEN_DSET to avoid the inevitable failure.
+ * Note too, that we skip the comparison tests in both locations if
+ * we're reopening the file.
+ */
+ if((*ex_dcpl != dcpl) && (config < TEST_API_REOPEN_DSET)) {
+ if((tri_ret = H5Pequal(dcpl, *ex_dcpl)) <= 0) {
+ if (mpi_rank == 0) {
+ printf("H5Pequal failed!\n");
+ }
+ MPI_Barrier(MPI_COMM_WORLD);
+ TEST_ERROR
+ }
+ }
+ /* Close dataset */
+ if(H5Dclose(dset) < 0)
+ TEST_ERROR
+ dset = -1;
+
+ /* Delete dataset */
+ if(H5Ldelete(file, "vdset", H5P_DEFAULT) < 0)
+ TEST_ERROR
+
+ /* Close file */
+ if(H5Fclose(file) < 0)
+ TEST_ERROR
+ file = -1;
+ } /* end if */
+ else if(config == TEST_API_COPY_PLIST) {
+ /* Copy property list */
+ if((*ex_dcpl = H5Pcopy(dcpl)) < 0)
+ TEST_ERROR
+ } /* end if */
+ else if(config == TEST_API_ENCDEC_PLIST) {
+ size_t plist_buf_size;
+
+ /* Encode property list to plist_buf */
+ if(H5Pencode2(dcpl, NULL, &plist_buf_size, H5P_DEFAULT) < 0)
+ TEST_ERROR
+ if(NULL == (plist_buf = HDmalloc(plist_buf_size)))
+ TEST_ERROR
+ if(H5Pencode2(dcpl, plist_buf, &plist_buf_size, H5P_DEFAULT) < 0)
+ TEST_ERROR
+
+ /* Decode serialized property list to *ex_dcpl */
+ if((*ex_dcpl = H5Pdecode(plist_buf)) < 0)
+ TEST_ERROR
+
+ /* Free plist_buf */
+ HDfree(plist_buf);
+ plist_buf = NULL;
+ } /* end if */
+ else {
+ /* Simply copy the id to ex_dcpl and increment the ref count so ex_dcpl
+ * can be closed */
+ if(H5Iinc_ref(dcpl) < 0)
+ TEST_ERROR
+ *ex_dcpl = dcpl;
+ } /* end else */
+
+ /* Verify examination DCPL is equal to original DCPL. Do not compare the
+ * plist to itself, and do not do the comparison if we reopened the file,
+ * (or the dataset) because in that case the extent of the source dset
+ * will not be current.
+ */
+ if((*ex_dcpl != dcpl) && (config != TEST_API_REOPEN_DSET) &&
+ (config != TEST_API_REOPEN_FILE)) {
+ if((tri_ret = H5Pequal(dcpl, *ex_dcpl)) <= 0) {
+ if (mpi_rank == 0) {
+ printf("H5Pequal failed!\n");
+ }
+ MPI_Barrier(MPI_COMM_WORLD);
+ TEST_ERROR
+ /* if(!tri_ret)
+ TEST_ERROR */
+ }
+ } /* end if */
+
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ if(file >= 0)
+ (void)H5Fclose(file);
+ if(dset >= 0)
+ (void)H5Dclose(dset);
+ } H5E_END_TRY;
+ if(plist_buf)
+ HDfree(plist_buf);
+
+ return -1;
+} /* end test_api_get_ex_dcpl() */
+
+/* Main test function */
+static int
+test_api(test_api_config_t config, hid_t fapl)
+{
+ char filename[FILENAME_BUF_SIZE];
+ hid_t dcpl = -1; /* Dataset creation property list */
+ hid_t ex_dcpl = -1; /* Temporary dcpl for examination */
+ hid_t xfer_plist = -1; /* Dataset XFER property list */
+ hid_t srcspace[4] = {-1, -1, -1, -1}; /* Source dataspaces */
+ hid_t vspace[LIST_DOUBLE_SIZE]; /* Virtual dset dataspaces */
+ const char *src_file[4] = {"src_file1", "src_file2.", "src_file3..", "src_file4..."}; /* Source file names (different lengths) */
+ const char *src_dset[4] = {"src_dset1....", "src_dset2.....", "src_dset3......", "src_dset4......."}; /* Source dataset names (different lengths) */
+ char tmp_filename[32];
+ char tmp_dsetname[32];
+ hsize_t dims[2] = {10, 20}; /* Data space current size */
+ hsize_t start[2]; /* Hyperslab start */
+ hsize_t stride[2]; /* Hyperslab stride */
+ hsize_t count[2]; /* Hyperslab count */
+ hsize_t block[2]; /* Hyperslab block */
+ hsize_t coord[10]; /* Point selection array */
+ size_t size_out;
+ herr_t ret;
+ unsigned i;
+
+ /* Initialize vspace */
+ for(i = 0; i < (unsigned)(sizeof(vspace) / sizeof(vspace[0])); i++)
+ vspace[i] = -1;
+
+ switch(config) {
+ case TEST_API_BASIC:
+ if (mpi_rank == 0)
+ TESTING("virtual dataset API functions")
+ break;
+ case TEST_API_COPY_PLIST:
+ if (mpi_rank == 0)
+ TESTING("virtual dataset API functions with copied plists")
+ break;
+ case TEST_API_ENCDEC_PLIST:
+ if (mpi_rank == 0)
+ TESTING("virtual dataset API functions with encoded and decoded plists")
+ break;
+ case TEST_API_CREATE_DSET:
+ if (mpi_rank == 0)
+ TESTING("virtual dataset create")
+ break;
+ case TEST_API_REOPEN_DSET:
+ if (mpi_rank == 0)
+ TESTING("virtual dataset create with reopened dataset")
+ break;
+ case TEST_API_REOPEN_FILE:
+ if (mpi_rank == 0)
+ TESTING("virtual dataset create with reopened file")
+ break;
+ case TEST_API_NTESTS:
+ default:
+ TEST_ERROR
+ } /* end switch */
+
+ h5_fixname(FILENAME[0], fapl, filename, sizeof filename);
+
+ /* Create DCPL */
+ if((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0)
+ TEST_ERROR
+
+ /* Setup the collective (parallel) transfer property list */
+ if((xfer_plist = H5Pcreate(H5P_DATASET_XFER)) < 0)
+ TEST_ERROR
+
+ if (H5Pset_dxpl_mpio(xfer_plist, H5FD_MPIO_COLLECTIVE) < 0)
+ TEST_ERROR
+ /* Setup chunk information */
+
+
+ /*
+ * Test 1: All - all selection
+ */
+ /* Create source dataspace */
+ if((srcspace[0] = H5Screate_simple(2, dims, NULL)) < 0)
+ TEST_ERROR
+
+ /* Create virtual dataspace */
+ if((vspace[0] = H5Screate_simple(2, dims, NULL)) < 0)
+ TEST_ERROR
+
+ /* Select all (should not be necessary, but just to be sure) */
+ if(H5Sselect_all(srcspace[0]) < 0)
+ TEST_ERROR
+ if(H5Sselect_all(vspace[0]) < 0)
+ TEST_ERROR
+
+ /* Add virtual layout mapping */
+ if(H5Pset_virtual(dcpl, vspace[0], src_file[0], src_dset[0], srcspace[0]) < 0)
+ TEST_ERROR
+
+ /* Get examination DCPL */
+ if(test_api_get_ex_dcpl(config, fapl, dcpl, &ex_dcpl, vspace[0], filename, (hsize_t)69) < 0)
+ TEST_ERROR
+
+ /* Test H5Pget_virtual_count */
+ if(H5Pget_virtual_count(ex_dcpl, &size_out) < 0)
+ TEST_ERROR
+ if(size_out != (size_t)1)
+ TEST_ERROR
+
+ /* Check that the mapping in the DCPL is correct */
+ if(vds_check_mapping(ex_dcpl, (size_t)0, vspace[0], srcspace[0], src_file[0], src_dset[0]) < 0)
+ TEST_ERROR
+
+ /* Close */
+#if 1
+ if (H5Pclose(xfer_plist) < 0)
+ TEST_ERROR
+ xfer_plist = -1;
+#endif
+ if(H5Sclose(srcspace[0]) < 0)
+ TEST_ERROR
+ srcspace[0] = -1;
+ if(H5Sclose(vspace[0]) < 0)
+ TEST_ERROR
+ vspace[0] = -1;
+ if(H5Pclose(ex_dcpl) < 0)
+ TEST_ERROR
+ ex_dcpl = -1;
+
+
+ /*
+ * Test 2: Hyper - hyper selection
+ */
+ /* Clear virtual layout in DCPL */
+ if(H5Pset_layout(dcpl, H5D_VIRTUAL) < 0)
+ TEST_ERROR
+
+ /* Create source dataspace */
+ if((srcspace[0] = H5Screate_simple(2, dims, NULL)) < 0)
+ TEST_ERROR
+
+ /* Create virtual dataspace */
+ if((vspace[0] = H5Screate_simple(2, dims, NULL)) < 0)
+ TEST_ERROR
+
+ /* Select regular hyperslab in source space */
+ start[0] = 2;
+ start[1] = 1;
+ stride[0] = 3;
+ stride[1] = 5;
+ count[0] = 2;
+ count[1] = 3;
+ block[0] = 2;
+ block[1] = 4;
+ if(H5Sselect_hyperslab(srcspace[0], H5S_SELECT_SET, start, stride, count, block) < 0)
+ TEST_ERROR
+
+ /* Select composite hyperslab in virtual space */
+ count[0] = 1;
+ count[1] = 1;
+ block[0] = 5;
+ block[1] = 6;
+ if(H5Sselect_hyperslab(vspace[0], H5S_SELECT_SET, start, NULL, count, block) < 0)
+ TEST_ERROR
+ start[0] = 7;
+ start[1] = 0;
+ block[0] = 1;
+ block[1] = 18;
+ if(H5Sselect_hyperslab(vspace[0], H5S_SELECT_OR, start, NULL, count, block) < 0)
+ TEST_ERROR
+
+ /* Add virtual layout mapping */
+ if(H5Pset_virtual(dcpl, vspace[0], src_file[0], src_dset[0], srcspace[0]) < 0)
+ TEST_ERROR
+
+ /* Get examination DCPL */
+ // if(test_api_get_ex_dcpl(config, fapl, dcpl, &ex_dcpl, vspace[0], filename, (hsize_t)174) < 0)
+ if(test_api_get_ex_dcpl(config, fapl, dcpl, &ex_dcpl, vspace[0], filename, (hsize_t)213) < 0)
+ TEST_ERROR
+
+ /* Test H5Pget_virtual_count */
+ if(H5Pget_virtual_count(ex_dcpl, &size_out) < 0)
+ TEST_ERROR
+ if(size_out != (size_t)1)
+ TEST_ERROR
+
+ /* Check that the mapping in the DCPL is correct */
+ if(vds_check_mapping(ex_dcpl, (size_t)0, vspace[0], srcspace[0], src_file[0], src_dset[0]) < 0)
+ TEST_ERROR
+
+ /* Close */
+ if(H5Sclose(srcspace[0]) < 0)
+ TEST_ERROR
+ srcspace[0] = -1;
+ if(H5Sclose(vspace[0]) < 0)
+ TEST_ERROR
+ vspace[0] = -1;
+ if(H5Pclose(ex_dcpl) < 0)
+ TEST_ERROR
+ ex_dcpl = -1;
+
+
+#ifdef VDS_POINT_SELECTIONS /* VDS does not currently support point selections */
+ /*
+ * Test 3: Point - point selection
+ */
+ /* Clear virtual layout in DCPL */
+ if(H5Pset_layout(dcpl, H5D_VIRTUAL) < 0)
+ TEST_ERROR
+
+ /* Create source dataspace */
+ if((srcspace[0] = H5Screate_simple(2, dims, NULL)) < 0)
+ TEST_ERROR
+
+ /* Create virtual dataspace */
+ if((vspace[0] = H5Screate_simple(2, dims, NULL)) < 0)
+ TEST_ERROR
+
+ /* Select points in source space */
+ coord[0] = 5;
+ coord[1] = 15;
+ coord[2] = 7;
+ coord[3] = 19;
+ coord[4] = 8;
+ coord[5] = 0;
+ coord[6] = 2;
+ coord[7] = 14;
+ coord[8] = 8;
+ coord[9] = 18;
+ if(H5Sselect_elements(srcspace[0], H5S_SELECT_SET, (size_t)5, coord) < 0)
+ TEST_ERROR
+
+ /* Select points in virtual space */
+ coord[0] = 3;
+ coord[1] = 12;
+ coord[2] = 7;
+ coord[3] = 11;
+ coord[4] = 4;
+ coord[5] = 9;
+ coord[6] = 7;
+ coord[7] = 11;
+ coord[8] = 5;
+ coord[9] = 5;
+ if(H5Sselect_elements(vspace[0], H5S_SELECT_SET, (size_t)5, coord) < 0)
+ TEST_ERROR
+
+ /* Add virtual layout mapping */
+ if(H5Pset_virtual(dcpl, vspace[0], src_file[0], src_dset[0], srcspace[0]) < 0)
+ TEST_ERROR
+
+ /* Get examination DCPL */
+ if(test_api_get_ex_dcpl(config, fapl, dcpl, &ex_dcpl, vspace[0], filename, (hsize_t)0) < 0)
+ TEST_ERROR
+
+ /* Test H5Pget_virtual_count */
+ if(H5Pget_virtual_count(ex_dcpl, &size_out) < 0)
+ TEST_ERROR
+ if(size_out != (size_t)1)
+ TEST_ERROR
+
+ /* Check that the mapping in the DCPL is correct */
+ if(vds_check_mapping(ex_dcpl, (size_t)0, vspace[0], srcspace[0], src_file[0], src_dset[0]) < 0)
+ TEST_ERROR
+
+ /* Close */
+ if(H5Sclose(srcspace[0]) < 0)
+ TEST_ERROR
+ srcspace[0] = -1;
+ if(H5Sclose(vspace[0]) < 0)
+ TEST_ERROR
+ vspace[0] = -1;
+ if(H5Pclose(ex_dcpl) < 0)
+ TEST_ERROR
+ ex_dcpl = -1;
+
+
+ /*
+ * Test 4: Point - hyper selection
+ */
+ /* Clear virtual layout in DCPL */
+ if(H5Pset_layout(dcpl, H5D_VIRTUAL) < 0)
+ TEST_ERROR
+
+ /* Create source dataspace */
+ if((srcspace[0] = H5Screate_simple(2, dims, NULL)) < 0)
+ TEST_ERROR
+
+ /* Create virtual dataspace */
+ if((vspace[0] = H5Screate_simple(2, dims, NULL)) < 0)
+ TEST_ERROR
+
+ /* Select hyperslab in source space */
+ start[0] = 2;
+ start[1] = 7;
+ count[0] = 1;
+ count[1] = 1;
+ block[0] = 1;
+ block[1] = 5;
+ if(H5Sselect_hyperslab(srcspace[0], H5S_SELECT_SET, start, NULL, count, block) < 0)
+ TEST_ERROR
+
+ /* Select points in virtual space */
+ coord[0] = 1;
+ coord[1] = 1;
+ coord[2] = 4;
+ coord[3] = 17;
+ coord[4] = 3;
+ coord[5] = 9;
+ coord[6] = 5;
+ coord[7] = 13;
+ coord[8] = 7;
+ coord[9] = 16;
+ if(H5Sselect_elements(vspace[0], H5S_SELECT_SET, (size_t)5, coord) < 0)
+ TEST_ERROR
+
+ /* Add virtual layout mapping */
+ if(H5Pset_virtual(dcpl, vspace[0], src_file[0], src_dset[0], srcspace[0]) < 0)
+ TEST_ERROR
+
+ /* Get examination DCPL */
+ if(test_api_get_ex_dcpl(config, fapl, dcpl, &ex_dcpl, vspace[0], filename, (hsize_t)0) < 0)
+ TEST_ERROR
+
+ /* Test H5Pget_virtual_count */
+ if(H5Pget_virtual_count(ex_dcpl, &size_out) < 0)
+ TEST_ERROR
+ if(size_out != (size_t)1)
+ TEST_ERROR
+
+ /* Check that the mapping in the DCPL is correct */
+ if(vds_check_mapping(ex_dcpl, (size_t)0, vspace[0], srcspace[0], src_file[0], src_dset[0]) < 0)
+ TEST_ERROR
+
+ /* Close */
+ if(H5Sclose(srcspace[0]) < 0)
+ TEST_ERROR
+ srcspace[0] = -1;
+ if(H5Sclose(vspace[0]) < 0)
+ TEST_ERROR
+ vspace[0] = -1;
+ if(H5Pclose(ex_dcpl) < 0)
+ TEST_ERROR
+ ex_dcpl = -1;
+
+
+ /*
+ * Test 5: All previous mappings together
+ */
+ /* Clear virtual layout in DCPL */
+ if(H5Pset_layout(dcpl, H5D_VIRTUAL) < 0)
+ TEST_ERROR
+
+ /* Create dataspaces */
+ for(i = 0; i < 4; i++) {
+ /* Create source dataspace */
+ if((srcspace[i] = H5Screate_simple(2, dims, NULL)) < 0)
+ TEST_ERROR
+
+ /* Create virtual dataspace */
+ if((vspace[i] = H5Screate_simple(2, dims, NULL)) < 0)
+ TEST_ERROR
+ } /* end for */
+
+ /* Select all (should not be necessary, but just to be sure) */
+ if(H5Sselect_all(srcspace[0]) < 0)
+ TEST_ERROR
+ if(H5Sselect_all(vspace[0]) < 0)
+ TEST_ERROR
+
+ /* Select regular hyperslab in source space */
+ start[0] = 2;
+ start[1] = 1;
+ stride[0] = 3;
+ stride[1] = 5;
+ count[0] = 2;
+ count[1] = 3;
+ block[0] = 2;
+ block[1] = 4;
+ if(H5Sselect_hyperslab(srcspace[1], H5S_SELECT_SET, start, stride, count, block) < 0)
+ TEST_ERROR
+
+ /* Select composite hyperslab in virtual space */
+ count[0] = 1;
+ count[1] = 1;
+ block[0] = 5;
+ block[1] = 6;
+ if(H5Sselect_hyperslab(vspace[1], H5S_SELECT_SET, start, NULL, count, block) < 0)
+ TEST_ERROR
+ start[0] = 7;
+ start[1] = 0;
+ block[0] = 1;
+ block[1] = 18;
+ if(H5Sselect_hyperslab(vspace[1], H5S_SELECT_OR, start, NULL, count, block) < 0)
+ TEST_ERROR
+
+ /* Select points in source space */
+ coord[0] = 5;
+ coord[1] = 15;
+ coord[2] = 7;
+ coord[3] = 19;
+ coord[4] = 8;
+ coord[5] = 0;
+ coord[6] = 2;
+ coord[7] = 14;
+ coord[8] = 8;
+ coord[9] = 18;
+ if(H5Sselect_elements(srcspace[2], H5S_SELECT_SET, (size_t)5, coord) < 0)
+ TEST_ERROR
+
+ /* Select points in virtual space */
+ coord[0] = 3;
+ coord[1] = 12;
+ coord[2] = 7;
+ coord[3] = 11;
+ coord[4] = 4;
+ coord[5] = 9;
+ coord[6] = 7;
+ coord[7] = 11;
+ coord[8] = 5;
+ coord[9] = 5;
+ if(H5Sselect_elements(vspace[2], H5S_SELECT_SET, (size_t)5, coord) < 0)
+ TEST_ERROR
+
+ /* Select hyperslab in source space */
+ start[0] = 2;
+ start[1] = 7;
+ count[0] = 1;
+ count[1] = 1;
+ block[0] = 1;
+ block[1] = 5;
+ if(H5Sselect_hyperslab(srcspace[3], H5S_SELECT_SET, start, NULL, count, block) < 0)
+ TEST_ERROR
+
+ /* Select points in virtual space */
+ coord[0] = 1;
+ coord[1] = 1;
+ coord[2] = 4;
+ coord[3] = 17;
+ coord[4] = 3;
+ coord[5] = 9;
+ coord[6] = 5;
+ coord[7] = 13;
+ coord[8] = 7;
+ coord[9] = 16;
+ if(H5Sselect_elements(vspace[3], H5S_SELECT_SET, (size_t)5, coord) < 0)
+ TEST_ERROR
+
+ /* Add virtual layout mappings */
+ for(i = 0; i < 4; i++)
+ if(H5Pset_virtual(dcpl, vspace[i], src_file[i], src_dset[i], srcspace[i]) < 0)
+ TEST_ERROR
+
+ /* Get examination DCPL */
+ if(test_api_get_ex_dcpl(config, fapl, dcpl, &ex_dcpl, vspace[0], filename, (hsize_t)0) < 0)
+ TEST_ERROR
+
+ /* Test H5Pget_virtual_count */
+ if(H5Pget_virtual_count(ex_dcpl, &size_out) < 0)
+ TEST_ERROR
+ if(size_out != (size_t)4)
+ TEST_ERROR
+
+ /* Check that the mappings in the DCPL are correct */
+ for(i = 0; i < 4; i++)
+ if(vds_check_mapping(ex_dcpl, (size_t)i, vspace[i], srcspace[i], src_file[i], src_dset[i]) < 0)
+ TEST_ERROR
+
+ /* Close */
+ for(i = 0; i < 4; i++) {
+ if(H5Sclose(srcspace[i]) < 0)
+ TEST_ERROR
+ srcspace[i] = -1;
+ if(H5Sclose(vspace[i]) < 0)
+ TEST_ERROR
+ vspace[i] = -1;
+ } /* end for */
+ if(H5Pclose(ex_dcpl) < 0)
+ TEST_ERROR
+ ex_dcpl = -1;
+
+#else /* VDS_POINT_SELECTIONS */
+
+ /*
+ * Test 3: Verify point selections fail
+ */
+ /* Clear virtual layout in DCPL */
+ if(H5Pset_layout(dcpl, H5D_VIRTUAL) < 0)
+ TEST_ERROR
+
+ /* Create source dataspace */
+ if((srcspace[0] = H5Screate_simple(2, dims, NULL)) < 0)
+ TEST_ERROR
+
+ /* Create virtual dataspace */
+ if((vspace[0] = H5Screate_simple(2, dims, NULL)) < 0)
+ TEST_ERROR
+
+ /* Select points in source space */
+ coord[0] = 5;
+ coord[1] = 15;
+ coord[2] = 7;
+ coord[3] = 19;
+ coord[4] = 8;
+ coord[5] = 0;
+ coord[6] = 2;
+ coord[7] = 14;
+ coord[8] = 8;
+ coord[9] = 18;
+ if(H5Sselect_elements(srcspace[0], H5S_SELECT_SET, (size_t)5, coord) < 0)
+ TEST_ERROR
+
+ /* Select points in virtual space */
+ coord[0] = 3;
+ coord[1] = 12;
+ coord[2] = 7;
+ coord[3] = 11;
+ coord[4] = 4;
+ coord[5] = 9;
+ coord[6] = 7;
+ coord[7] = 11;
+ coord[8] = 5;
+ coord[9] = 5;
+ if(H5Sselect_elements(vspace[0], H5S_SELECT_SET, (size_t)5, coord) < 0)
+ TEST_ERROR
+
+ /* Attempt to add virtual layout mapping */
+ H5E_BEGIN_TRY {
+ ret = H5Pset_virtual(dcpl, vspace[0], src_file[0], src_dset[0], srcspace[0]);
+ } H5E_END_TRY
+ if(ret >= 0)
+ TEST_ERROR
+#endif /* VDS_POINT_SELECTIONS */
+
+
+ /*
+ * Test 6: Enough Selections to trigger doubling of mapping list
+ */
+ /* Clear virtual layout in DCPL */
+ if(H5Pset_layout(dcpl, H5D_VIRTUAL) < 0)
+ TEST_ERROR
+
+ /* Create source dataspace */
+ dims[0] = 1;
+ if((srcspace[0] = H5Screate_simple(2, dims, NULL)) < 0)
+ TEST_ERROR
+
+ /* Select all in source space (should not be necessary, but just to be sure) */
+ if(H5Sselect_all(srcspace[0]) < 0)
+ TEST_ERROR
+
+ /* Init virtual space extent */
+ dims[0] = LIST_DOUBLE_SIZE;
+
+ /* Init hyperslab values */
+ start[0] = 0;
+ start[1] = 0;
+ count[0] = 1;
+ count[1] = 1;
+ block[0] = 1;
+ block[1] = 20;
+
+ /* Build virtual layout */
+ for(i = 0; i < LIST_DOUBLE_SIZE; i++) {
+ /* Create virtual dataspace */
+ if((vspace[i] = H5Screate_simple(2, dims, NULL)) < 0)
+ TEST_ERROR
+
+ /* Select row in virual dataspace */
+ start[0] = (hsize_t)i;
+ if(H5Sselect_hyperslab(vspace[i], H5S_SELECT_SET, start, NULL, count, block) < 0)
+ TEST_ERROR
+
+ /* Create file and dataset names */
+ (void)HDsnprintf(tmp_filename, sizeof(tmp_filename), "src_file%u", i);
+ tmp_filename[sizeof(tmp_filename) - 1] = '\0';
+ (void)HDsnprintf(tmp_dsetname, sizeof(tmp_dsetname), "src_dset%u", i);
+ tmp_dsetname[sizeof(tmp_dsetname) - 1] = '\0';
+
+ /* Add virtual layout mapping */
+ if(H5Pset_virtual(dcpl, vspace[i], tmp_filename, tmp_dsetname, srcspace[0]) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Get examination DCPL */
+ if(test_api_get_ex_dcpl(config, fapl, dcpl, &ex_dcpl, vspace[0], filename, (hsize_t)697) < 0)
+ TEST_ERROR
+
+ /* Test H5Pget_virtual_count */
+ if(H5Pget_virtual_count(ex_dcpl, &size_out) < 0)
+ TEST_ERROR
+ if(size_out != (size_t)LIST_DOUBLE_SIZE)
+ TEST_ERROR
+
+ /* Verify virtual layout */
+ for(i = 0; i < LIST_DOUBLE_SIZE; i++) {
+ /* Generate source file name */
+ (void)HDsnprintf(tmp_filename, sizeof(tmp_filename), "src_file%u", i);
+ tmp_filename[sizeof(tmp_filename) - 1] = '\0';
+
+ /* Generate source dset name */
+ (void)HDsnprintf(tmp_dsetname, sizeof(tmp_dsetname), "src_dset%u", i);
+ tmp_dsetname[sizeof(tmp_dsetname) - 1] = '\0';
+
+ /* Check that the mapping in the DCPL is correct */
+ if(vds_check_mapping(ex_dcpl, (size_t)i, vspace[i], srcspace[0], tmp_filename, tmp_dsetname) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Close */
+ if(H5Sclose(srcspace[0]) < 0)
+ TEST_ERROR
+ srcspace[0] = -1;
+ for(i = 0; i < LIST_DOUBLE_SIZE; i++) {
+ if(H5Sclose(vspace[i]) < 0)
+ TEST_ERROR
+ vspace[i] = -1;
+ } /* end for */
+ if(H5Pclose(ex_dcpl) < 0)
+ TEST_ERROR
+ ex_dcpl = -1;
+
+
+ /*
+ * Test 7: Empty VDS
+ */
+ /* Clear virtual layout in DCPL */
+ if(H5Pset_layout(dcpl, H5D_VIRTUAL) < 0)
+ TEST_ERROR
+
+ /* Create virtual dataspace */
+ if((vspace[0] = H5Screate_simple(2, dims, NULL)) < 0)
+ TEST_ERROR
+
+ /* Select all (should not be necessary, but just to be sure) */
+ if(H5Sselect_all(vspace[0]) < 0)
+ TEST_ERROR
+
+ /* Get examination DCPL */
+ if(test_api_get_ex_dcpl(config, fapl, dcpl, &ex_dcpl, vspace[0], filename, (hsize_t)0) < 0)
+ TEST_ERROR
+
+ /* Test H5Pget_virtual_count */
+ if(H5Pget_virtual_count(ex_dcpl, &size_out) < 0)
+ TEST_ERROR
+ if(size_out != (size_t)0)
+ TEST_ERROR
+
+ /* Close */
+ if(H5Sclose(vspace[0]) < 0)
+ TEST_ERROR
+ vspace[0] = -1;
+ if(H5Pclose(ex_dcpl) < 0)
+ TEST_ERROR
+ ex_dcpl = -1;
+
+
+ /* Close */
+ if(H5Pclose(dcpl) < 0)
+ TEST_ERROR
+ dcpl = -1;
+
+ if (mpi_rank == 0)
+ PASSED();
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ for(i = 0; i < (sizeof(srcspace) / sizeof(srcspace[0])); i++) {
+ if(srcspace[i] >= 0)
+ (void)H5Sclose(srcspace[i]);
+ } /* end for */
+ for(i = 0; i < (sizeof(vspace) / sizeof(vspace[0])); i++) {
+ if(vspace[i] >= 0)
+ (void)H5Sclose(vspace[i]);
+ } /* end for */
+ if(dcpl >= 0)
+ (void)H5Pclose(dcpl);
+ if(ex_dcpl >= 0)
+ (void)H5Pclose(ex_dcpl);
+ } H5E_END_TRY;
+
+ return 1;
+} /* end test_api() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_basic_io
+ *
+ * Purpose: Tests VDS I/O without unlimited selections or
+ * pattern-matching file/dataset strings
+ *
+ * Return: Success: 0
+ *
+ * Failure: number of errors
+ *
+ * Programmer: Neil Fortner
+ * Tuesday, March 3, 2015
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_basic_io(unsigned config, hid_t fapl)
+{
+ char srcfilename[FILENAME_BUF_SIZE];
+ char srcfilename_map[FILENAME_BUF_SIZE];
+ char vfilename[FILENAME_BUF_SIZE];
+ char vfilename2[FILENAME_BUF_SIZE];
+ char srcfilenamepct[FILENAME_BUF_SIZE];
+ char srcfilenamepct_map[FILENAME_BUF_SIZE];
+ const char *srcfilenamepct_map_orig = "vds%%%%_src";
+ hid_t srcfile[4] = {-1, -1, -1, -1}; /* Files with source dsets */
+ hid_t vfile = -1; /* File with virtual dset */
+ hid_t vfile2 = -1; /* File with copied virtual dset */
+ hid_t dcpl = -1; /* Dataset creation property list */
+ hid_t srcspace[4] = {-1, -1, -1, -1}; /* Source dataspaces */
+ hid_t vspace[4] = {-1, -1, -1, -1}; /* Virtual dset dataspaces */
+ hid_t memspace = -1; /* Memory dataspace */
+ hid_t srcdset[4] = {-1, -1, -1, -1}; /* Source datsets */
+ hid_t vdset = -1; /* Virtual dataset */
+ hid_t dxpl_id = -1; /* Dataset Transfer property */
+
+ hsize_t dims[4] = {10, 26, 0, 0}; /* Data space current size */
+ hsize_t start[4]; /* Hyperslab start */
+ hsize_t stride[4]; /* Hyperslab stride */
+ hsize_t count[4]; /* Hyperslab count */
+ hsize_t block[4]; /* Hyperslab block */
+ hssize_t offset[2] = {0, 0}; /* Selection offset */
+ int buf[10][26]; /* Write and expected read buffer */
+ int rbuf[10][26]; /* Read buffer */
+ int rbuf99[9][9]; /* 9x9 Read buffer */
+ int evbuf[10][26]; /* Expected VDS "buffer" */
+ int erbuf[10][26]; /* Expected read buffer */
+ int fill = -1; /* Fill value */
+ herr_t ret; /* Generic return value */
+ int i, j;
+
+ if (mpi_rank == 0)
+ TESTING("basic virtual dataset I/O")
+
+ h5_fixname(FILENAME[0], fapl, vfilename, sizeof vfilename);
+ h5_fixname(FILENAME[1], fapl, vfilename2, sizeof vfilename2);
+ h5_fixname(FILENAME[2], fapl, srcfilename, sizeof srcfilename);
+ h5_fixname_printf(FILENAME[2], fapl, srcfilename_map, sizeof srcfilename_map);
+ h5_fixname(FILENAME[4], fapl, srcfilenamepct, sizeof srcfilenamepct);
+ h5_fixname_printf(srcfilenamepct_map_orig, fapl, srcfilenamepct_map, sizeof srcfilenamepct_map);
+
+ if((dxpl_id = H5Pcreate(H5P_DATASET_XFER)) < 0 )
+ TEST_ERROR
+
+ if((H5Pset_dxpl_mpio(dxpl_id, H5FD_MPIO_COLLECTIVE)) < 0 )
+ TEST_ERROR
+
+ /* Create DCPL */
+ if((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0)
+ TEST_ERROR
+
+ /* Set fill value */
+ if(H5Pset_fill_value(dcpl, H5T_NATIVE_INT, &fill) < 0)
+ TEST_ERROR
+
+ /*
+ * Test 1: All - all selection
+ */
+ /* Create source dataspace */
+ if((srcspace[0] = H5Screate_simple(2, dims, NULL)) < 0)
+ TEST_ERROR
+
+ /* Create virtual dataspace */
+ if((vspace[0] = H5Screate_simple(2, dims, NULL)) < 0)
+ TEST_ERROR
+
+ /* Select all (should not be necessary, but just to be sure) */
+ if(H5Sselect_all(srcspace[0]) < 0)
+ TEST_ERROR
+ if(H5Sselect_all(vspace[0]) < 0)
+ TEST_ERROR
+
+ /* Add virtual layout mapping */
+ if(H5Pset_virtual(dcpl, vspace[0], config & TEST_IO_DIFFERENT_FILE ? srcfilename_map : ".", "src_dset", srcspace[0]) < 0)
+ TEST_ERROR
+
+ /* Create virtual file */
+ if((vfile = H5Fcreate(vfilename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ TEST_ERROR
+
+ /* Create source file if requested */
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ if((srcfile[0] = H5Fcreate(srcfilename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+ else {
+ srcfile[0] = vfile;
+ if(H5Iinc_ref(srcfile[0]) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Create source dataset */
+ if((srcdset[0] = H5Dcreate2(srcfile[0], "src_dset", H5T_NATIVE_INT, srcspace[0], H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Create virtual dataset */
+ if((vdset = H5Dcreate2(vfile, "v_dset", H5T_NATIVE_INT, vspace[0], H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Populate write buffer */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ buf[i][j] = (i * (int)(sizeof(buf[0]) / sizeof(buf[0][0]))) + j;
+
+ /* Write data directly to source dataset */
+ if(H5Dwrite(srcdset[0], H5T_NATIVE_INT, H5S_ALL, H5S_ALL, dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+
+ /* Close srcdset and srcfile if config option specified */
+ if(config & TEST_IO_CLOSE_SRC) {
+ if(H5Dclose(srcdset[0]) < 0)
+ TEST_ERROR
+ srcdset[0] = -1;
+
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ if(H5Fclose(srcfile[0]) < 0)
+ TEST_ERROR
+ srcfile[0] = -1;
+ } /* end if */
+ } /* end if */
+
+ /* Reopen virtual dataset and file if config option specified */
+ if(config & TEST_IO_REOPEN_VIRT) {
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ vdset = -1;
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if((vfile = H5Fopen(vfilename, H5F_ACC_RDWR, fapl)) < 0)
+ TEST_ERROR
+ if((vdset = H5Dopen2(vfile, "v_dset", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Read data through virtual dataset */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+ if(H5Dread(vdset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ if(rbuf[i][j] != buf[i][j])
+ TEST_ERROR
+
+#ifdef H5_HAVE_PARALLEL
+ /* Don't allow a following test to trash the current dataset while others
+ * might still be doing the previous READ validation..
+ */
+ MPI_Barrier(MPI_COMM_WORLD);
+#endif
+
+ /* Adjust write buffer */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ buf[i][j] += (int)(sizeof(buf) / sizeof(buf[0][0]));
+
+ if(H5Dwrite(vdset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+
+ /* Reopen srcdset and srcfile if config option specified */
+ if(config & TEST_IO_CLOSE_SRC) {
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ /* Flush virtual file. This is necessary since the parallel VDS
+ * implementation currently always opens source files independently
+ * with the sec2 driver, so HDF5 does not "match" the two and cannot
+ * share cached data. */
+ if(H5Fflush(vfile, H5F_SCOPE_GLOBAL) < 0)
+ TEST_ERROR
+
+ if((srcfile[0] = H5Fopen(srcfilename, H5F_ACC_RDONLY, fapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+ if((srcdset[0] = H5Dopen2(srcfile[0], "src_dset", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Read data directly from source dataset */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+ if(H5Dread(srcdset[0], H5T_NATIVE_INT, H5S_ALL, H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ if(rbuf[i][j] != buf[i][j])
+ TEST_ERROR
+
+ /* Close */
+ if(H5Dclose(srcdset[0]) < 0)
+ TEST_ERROR
+ srcdset[0] = -1;
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ vdset = -1;
+ if(H5Fclose(srcfile[0]) < 0)
+ TEST_ERROR
+ srcfile[0] = -1;
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if(H5Sclose(srcspace[0]) < 0)
+ TEST_ERROR
+ srcspace[0] = -1;
+ if(H5Sclose(vspace[0]) < 0)
+ TEST_ERROR
+ vspace[0] = -1;
+
+
+ /*
+ * Test 2: 2 Source datasets, hyperslab virtual mappings, '%' in source
+ * dataset name, also test H5Ocopy()
+ */
+ /* Clear virtual layout in DCPL */
+ if(H5Pset_layout(dcpl, H5D_VIRTUAL) < 0)
+ TEST_ERROR
+
+ /* Create virtual dataspaces */
+ if((vspace[0] = H5Screate_simple(2, dims, NULL)) < 0)
+ TEST_ERROR
+ if((vspace[1] = H5Screate_simple(2, dims, NULL)) < 0)
+ TEST_ERROR
+
+ /* Create source dataspace */
+ dims[1] = 13;
+ if((srcspace[0] = H5Screate_simple(2, dims, NULL)) < 0)
+ TEST_ERROR
+
+ /* Select all in source space (should not be necessary, but just to be sure)
+ */
+ if(H5Sselect_all(srcspace[0]) < 0)
+ TEST_ERROR
+
+ /* Select hyperslabs in virtual spaces */
+ start[0] = 0;
+ start[1] = 0;
+ if(H5Sselect_hyperslab(vspace[0], H5S_SELECT_SET, start, NULL, dims, NULL) < 0)
+ TEST_ERROR
+ start[1] = 13;
+ if(H5Sselect_hyperslab(vspace[1], H5S_SELECT_SET, start, NULL, dims, NULL) < 0)
+ TEST_ERROR
+
+ /* Add virtual layout mappings */
+ if(H5Pset_virtual(dcpl, vspace[0], config & TEST_IO_DIFFERENT_FILE ? srcfilename_map : ".", "%%src_dset1", srcspace[0]) < 0)
+ TEST_ERROR
+ if(H5Pset_virtual(dcpl, vspace[1], config & TEST_IO_DIFFERENT_FILE ? srcfilename_map : ".", "src_dset2%%", srcspace[0]) < 0)
+ TEST_ERROR
+
+ /* Reset dims */
+ dims[1] = 26;
+
+ /* Create virtual file */
+ if((vfile = H5Fcreate(vfilename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ TEST_ERROR
+
+ /* Create source file if requested */
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ if((srcfile[0] = H5Fcreate(srcfilename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+ else {
+ srcfile[0] = vfile;
+ if(H5Iinc_ref(srcfile[0]) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Create source datasets */
+ if((srcdset[0] = H5Dcreate2(srcfile[0], "%src_dset1", H5T_NATIVE_INT, srcspace[0], H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if((srcdset[1] = H5Dcreate2(srcfile[0], "src_dset2%", H5T_NATIVE_INT, srcspace[0], H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Create virtual dataset */
+ if((vdset = H5Dcreate2(vfile, "v_dset", H5T_NATIVE_INT, vspace[0], H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Populate write buffer */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ buf[i][j] = (i * (int)(sizeof(buf[0]) / sizeof(buf[0][0]))) + j;
+
+ /* Write data directly to source datasets */
+ if(H5Dwrite(srcdset[0], H5T_NATIVE_INT, vspace[0], H5S_ALL, dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+ if(H5Dwrite(srcdset[1], H5T_NATIVE_INT, vspace[1], H5S_ALL, dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+
+ /* Close srcdsets and srcfile if config option specified */
+ if(config & TEST_IO_CLOSE_SRC) {
+ if(H5Dclose(srcdset[0]) < 0)
+ TEST_ERROR
+ srcdset[0] = -1;
+ if(H5Dclose(srcdset[1]) < 0)
+ TEST_ERROR
+ srcdset[1] = -1;
+
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ if(H5Fclose(srcfile[0]) < 0)
+ TEST_ERROR
+ srcfile[0] = -1;
+ } /* end if */
+ } /* end if */
+
+ /* Reopen virtual dataset and file if config option specified */
+ if(config & TEST_IO_REOPEN_VIRT) {
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ vdset = -1;
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if((vfile = H5Fopen(vfilename, H5F_ACC_RDWR, fapl)) < 0)
+ TEST_ERROR
+ if((vdset = H5Dopen2(vfile, "v_dset", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Read data through virtual dataset */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+ if(H5Dread(vdset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ if(rbuf[i][j] != buf[i][j])
+ TEST_ERROR
+
+#ifdef H5_HAVE_PARALLEL
+ /* Don't allow test processes to trash the current dataset while others
+ * might still be doing the previous READ validation..
+ */
+ MPI_Barrier(MPI_COMM_WORLD);
+#endif
+
+ /* Adjust write buffer */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ buf[i][j] += (int)(sizeof(buf) / sizeof(buf[0][0]));
+
+ /* Write data through virtual dataset */
+ if(H5Dwrite(vdset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+
+ /* Reopen srcdsets and srcfile if config option specified */
+ if(config & TEST_IO_CLOSE_SRC) {
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ /* Flush virtual file. This is necessary since the parallel VDS
+ * implementation currently always opens source files independently
+ * with the sec2 driver, so HDF5 does not "match" the two and cannot
+ * share cached data. */
+ if(H5Fflush(vfile, H5F_SCOPE_GLOBAL) < 0)
+ TEST_ERROR
+
+ if((srcfile[0] = H5Fopen(srcfilename, H5F_ACC_RDWR, fapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+ if((srcdset[0] = H5Dopen2(srcfile[0], "%src_dset1", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if((srcdset[1] = H5Dopen2(srcfile[0], "src_dset2%", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Read data directly from source datasets */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+ if(H5Dread(srcdset[0], H5T_NATIVE_INT, vspace[0], H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+ if(H5Dread(srcdset[1], H5T_NATIVE_INT, vspace[1], H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ if(rbuf[i][j] != buf[i][j])
+ TEST_ERROR
+
+#ifdef H5_HAVE_PARALLEL
+ /* Don't allow test processes to trash the current dataset while others
+ * might still be doing the previous READ validation..
+ */
+ MPI_Barrier(MPI_COMM_WORLD);
+#endif
+ /* Test H5Ocopy() to same file */
+ /* Copy virtual dataset */
+ if(H5Ocopy(vfile, "v_dset", vfile, "v_dset2", H5P_DEFAULT, H5P_DEFAULT) < 0)
+ TEST_ERROR
+
+ /* Close v_dset */
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ vdset = -1;
+
+ /* Adjust write buffer */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ buf[i][j] += (int)(sizeof(buf) / sizeof(buf[0][0]));
+
+ /* Write data directly to source datasets */
+ if(H5Dwrite(srcdset[0], H5T_NATIVE_INT, vspace[0], H5S_ALL, dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+ if(H5Dwrite(srcdset[1], H5T_NATIVE_INT, vspace[1], H5S_ALL, dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+
+ /* Close srcdsets and srcfile if config option specified */
+ if(config & TEST_IO_CLOSE_SRC) {
+ if(H5Dclose(srcdset[0]) < 0)
+ TEST_ERROR
+ srcdset[0] = -1;
+ if(H5Dclose(srcdset[1]) < 0)
+ TEST_ERROR
+ srcdset[1] = -1;
+
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ if(H5Fclose(srcfile[0]) < 0)
+ TEST_ERROR
+ srcfile[0] = -1;
+ } /* end if */
+ } /* end if */
+
+ /* Reopen virtual file if config option specified */
+ if(config & TEST_IO_REOPEN_VIRT) {
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if((vfile = H5Fopen(vfilename, H5F_ACC_RDWR, fapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Open v_dset2 */
+ if((vdset = H5Dopen2(vfile, "v_dset2", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+#ifdef H5_HAVE_PARALLEL
+ /* Don't allow test processes to trash the current dataset while others
+ * might still be doing the previous READ validation..
+ */
+ MPI_Barrier(MPI_COMM_WORLD);
+#endif
+
+ /* Read data through copied virtual dataset */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+ if(H5Dread(vdset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ if(rbuf[i][j] != buf[i][j])
+ TEST_ERROR
+
+ /* Reopen srcdsets and srcfile if config option specified */
+ if(config & TEST_IO_CLOSE_SRC) {
+ if(config & TEST_IO_DIFFERENT_FILE)
+ if((srcfile[0] = H5Fopen(srcfilename, H5F_ACC_RDWR, fapl)) < 0)
+ TEST_ERROR
+ if((srcdset[0] = H5Dopen2(srcfile[0], "%src_dset1", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if((srcdset[1] = H5Dopen2(srcfile[0], "src_dset2%", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Only copy to a different file if the source datasets are in a different
+ * file */
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ /* Close v_dset2 */
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ vdset = -1;
+
+ /* Create file to copy virtual dataset to */
+ if((vfile2 = H5Fcreate(vfilename2, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ TEST_ERROR
+
+ /* Copy virtual dataset */
+ if(H5Ocopy(vfile, "v_dset", vfile2, "v_dset3", H5P_DEFAULT, H5P_DEFAULT) < 0)
+ TEST_ERROR
+
+ /* Adjust write buffer */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ buf[i][j] += (int)(sizeof(buf) / sizeof(buf[0][0]));
+
+ /* Write data directly to source datasets */
+ if(H5Dwrite(srcdset[0], H5T_NATIVE_INT, vspace[0], H5S_ALL, dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+ if(H5Dwrite(srcdset[1], H5T_NATIVE_INT, vspace[1], H5S_ALL, dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+
+ /* Close srcdsets and srcfile if config option specified */
+ if(config & TEST_IO_CLOSE_SRC) {
+ if(H5Dclose(srcdset[0]) < 0)
+ TEST_ERROR
+ srcdset[0] = -1;
+ if(H5Dclose(srcdset[1]) < 0)
+ TEST_ERROR
+ srcdset[1] = -1;
+
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ if(H5Fclose(srcfile[0]) < 0)
+ TEST_ERROR
+ srcfile[0] = -1;
+ } /* end if */
+ } /* end if */
+
+ /* Reopen copied virtual file if config option specified */
+ if(config & TEST_IO_REOPEN_VIRT) {
+ if(H5Fclose(vfile2) < 0)
+ TEST_ERROR
+ vfile2 = -1;
+ if((vfile2 = H5Fopen(vfilename2, H5F_ACC_RDWR, fapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Open v_dset3 */
+ if((vdset = H5Dopen2(vfile2, "v_dset3", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Read data through copied virtual dataset */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+ if(H5Dread(vdset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ if(rbuf[i][j] != buf[i][j])
+ TEST_ERROR
+
+ /* Reopen srcdsets and srcfile if config option specified */
+ if(config & TEST_IO_CLOSE_SRC) {
+ if(config & TEST_IO_DIFFERENT_FILE)
+ if((srcfile[0] = H5Fopen(srcfilename, H5F_ACC_RDONLY, fapl)) < 0)
+ TEST_ERROR
+ if((srcdset[0] = H5Dopen2(srcfile[0], "%src_dset1", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if((srcdset[1] = H5Dopen2(srcfile[0], "src_dset2%", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ } /* end if */
+
+ /* Close */
+ if(H5Dclose(srcdset[0]) < 0)
+ TEST_ERROR
+ srcdset[0] = -1;
+ if(H5Dclose(srcdset[1]) < 0)
+ TEST_ERROR
+ srcdset[1] = -1;
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ vdset = -1;
+ if(H5Fclose(srcfile[0]) < 0)
+ TEST_ERROR
+ srcfile[0] = -1;
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+
+ /* Close copied virtual file */
+ if((vfile2 != -1) && (H5Fclose(vfile2) < 0))
+ TEST_ERROR
+ vfile2 = -1;
+
+ if(H5Sclose(srcspace[0]) < 0)
+ TEST_ERROR
+ srcspace[0] = -1;
+ if(H5Sclose(vspace[0]) < 0)
+ TEST_ERROR
+ vspace[0] = -1;
+ if(H5Sclose(vspace[1]) < 0)
+ TEST_ERROR
+ vspace[1] = -1;
+
+
+ /*
+ * Test 3: 2 Source datasets, hyperslab virtual mappings with offsets
+ */
+ /* Clear virtual layout in DCPL */
+ if(H5Pset_layout(dcpl, H5D_VIRTUAL) < 0)
+ TEST_ERROR
+
+ /* Create virtual dataspaces */
+ if((vspace[0] = H5Screate_simple(2, dims, NULL)) < 0)
+ TEST_ERROR
+
+ /* Create source dataspace */
+ dims[1] = 13;
+ if((srcspace[0] = H5Screate_simple(2, dims, NULL)) < 0)
+ TEST_ERROR
+
+ /* Select all in source space (should not be necessary, but just to be sure)
+ */
+ if(H5Sselect_all(srcspace[0]) < 0)
+ TEST_ERROR
+
+ /* Select hyperslabs in virtual spaces */
+ start[0] = 0;
+ start[1] = 3;
+ if(H5Sselect_hyperslab(vspace[0], H5S_SELECT_SET, start, NULL, dims, NULL) < 0)
+ TEST_ERROR
+
+ /* Add virtual layout mappings */
+ offset[1] = -3;
+ if(H5Soffset_simple(vspace[0], offset) < 0)
+ TEST_ERROR
+ if(H5Pset_virtual(dcpl, vspace[0], config & TEST_IO_DIFFERENT_FILE ? srcfilename_map : ".", "%%src_dset1", srcspace[0]) < 0)
+ TEST_ERROR
+ offset[1] = 10;
+ if(H5Soffset_simple(vspace[0], offset) < 0)
+ TEST_ERROR
+ if(H5Pset_virtual(dcpl, vspace[0], config & TEST_IO_DIFFERENT_FILE ? srcfilename_map : ".", "src_dset2%%", srcspace[0]) < 0)
+ TEST_ERROR
+
+ /* Reset dims */
+ dims[1] = 26;
+
+ /* Create virtual file */
+ if((vfile = H5Fcreate(vfilename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ TEST_ERROR
+
+ /* Create source file if requested */
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ if((srcfile[0] = H5Fcreate(srcfilename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+ else {
+ srcfile[0] = vfile;
+ if(H5Iinc_ref(srcfile[0]) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Create source datasets */
+ if((srcdset[0] = H5Dcreate2(srcfile[0], "%src_dset1", H5T_NATIVE_INT, srcspace[0], H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if((srcdset[1] = H5Dcreate2(srcfile[0], "src_dset2%", H5T_NATIVE_INT, srcspace[0], H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Create virtual dataset */
+ if((vdset = H5Dcreate2(vfile, "v_dset", H5T_NATIVE_INT, vspace[0], H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Populate write buffer */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ buf[i][j] = (i * (int)(sizeof(buf[0]) / sizeof(buf[0][0]))) + j;
+
+ /* Write data directly to source datasets */
+ offset[1] = -3;
+ if(H5Soffset_simple(vspace[0], offset) < 0)
+ TEST_ERROR
+ if(H5Dwrite(srcdset[0], H5T_NATIVE_INT, vspace[0], H5S_ALL, dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+ offset[1] = 10;
+ if(H5Soffset_simple(vspace[0], offset) < 0)
+ TEST_ERROR
+ if(H5Dwrite(srcdset[1], H5T_NATIVE_INT, vspace[0], H5S_ALL, dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+
+ /* Close srcdsets and srcfile if config option specified */
+ if(config & TEST_IO_CLOSE_SRC) {
+ if(H5Dclose(srcdset[0]) < 0)
+ TEST_ERROR
+ srcdset[0] = -1;
+ if(H5Dclose(srcdset[1]) < 0)
+ TEST_ERROR
+ srcdset[1] = -1;
+
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ if(H5Fclose(srcfile[0]) < 0)
+ TEST_ERROR
+ srcfile[0] = -1;
+ } /* end if */
+ } /* end if */
+
+ /* Reopen virtual dataset and file if config option specified */
+ if(config & TEST_IO_REOPEN_VIRT) {
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ vdset = -1;
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if((vfile = H5Fopen(vfilename, H5F_ACC_RDWR, fapl)) < 0)
+ TEST_ERROR
+ if((vdset = H5Dopen2(vfile, "v_dset", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+#ifdef H5_HAVE_PARALLEL
+ /* Don't allow test processes to read the current dataset while others
+ * might still be doing the previous WRITE
+ */
+ MPI_Barrier(MPI_COMM_WORLD);
+#endif
+
+ /* Read data through virtual dataset */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+ if(H5Dread(vdset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ if(rbuf[i][j] != buf[i][j])
+ TEST_ERROR
+
+#ifdef H5_HAVE_PARALLEL
+ /* Don't allow test processes to read the current dataset while others
+ * might still be doing the previous WRITE
+ */
+ MPI_Barrier(MPI_COMM_WORLD);
+#endif
+
+ /* Adjust write buffer */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ buf[i][j] += (int)(sizeof(buf) / sizeof(buf[0][0]));
+
+ /* Write data through virtual dataset */
+ if(H5Dwrite(vdset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+
+ /* Reopen srcdsets and srcfile if config option specified */
+ if(config & TEST_IO_CLOSE_SRC) {
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ /* Flush virtual file. This is necessary since the parallel VDS
+ * implementation currently always opens source files independently
+ * with the sec2 driver, so HDF5 does not "match" the two and cannot
+ * share cached data. */
+ if(H5Fflush(vfile, H5F_SCOPE_GLOBAL) < 0)
+ TEST_ERROR
+
+ if((srcfile[0] = H5Fopen(srcfilename, H5F_ACC_RDONLY, fapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+ if((srcdset[0] = H5Dopen2(srcfile[0], "%src_dset1", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if((srcdset[1] = H5Dopen2(srcfile[0], "src_dset2%", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Read data directly from source datasets */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+ offset[1] = -3;
+ if(H5Soffset_simple(vspace[0], offset) < 0)
+ TEST_ERROR
+ if(H5Dread(srcdset[0], H5T_NATIVE_INT, vspace[0], H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+ offset[1] = 10;
+ if(H5Soffset_simple(vspace[0], offset) < 0)
+ TEST_ERROR
+ if(H5Dread(srcdset[1], H5T_NATIVE_INT, vspace[0], H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ if(rbuf[i][j] != buf[i][j])
+ TEST_ERROR
+
+ /* Close */
+ if(H5Dclose(srcdset[0]) < 0)
+ TEST_ERROR
+ srcdset[0] = -1;
+ if(H5Dclose(srcdset[1]) < 0)
+ TEST_ERROR
+ srcdset[1] = -1;
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ vdset = -1;
+ if(H5Fclose(srcfile[0]) < 0)
+ TEST_ERROR
+ srcfile[0] = -1;
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if(H5Sclose(srcspace[0]) < 0)
+ TEST_ERROR
+ srcspace[0] = -1;
+ if(H5Sclose(vspace[0]) < 0)
+ TEST_ERROR
+ vspace[0] = -1;
+
+
+ /*
+ * Test 4: 2 Source datasets, hyperslab virtual mappings on one mapping at a
+ * time, '%' in source file name
+ */
+ /* Clear virtual layout in DCPL */
+ if(H5Pset_layout(dcpl, H5D_VIRTUAL) < 0)
+ TEST_ERROR
+
+ /* Create virtual dataspaces */
+ if((vspace[0] = H5Screate_simple(2, dims, NULL)) < 0)
+ TEST_ERROR
+ if((vspace[1] = H5Screate_simple(2, dims, NULL)) < 0)
+ TEST_ERROR
+
+ /* Create source dataspace */
+ dims[1] = 13;
+ if((srcspace[0] = H5Screate_simple(2, dims, NULL)) < 0)
+ TEST_ERROR
+
+ /* Select all in source space (should not be necessary, but just to be sure)
+ */
+ if(H5Sselect_all(srcspace[0]) < 0)
+ TEST_ERROR
+
+ /* Select hyperslabs in virtual spaces */
+ start[0] = 0;
+ start[1] = 0;
+ if(H5Sselect_hyperslab(vspace[0], H5S_SELECT_SET, start, NULL, dims, NULL) < 0)
+ TEST_ERROR
+ start[1] = 13;
+ if(H5Sselect_hyperslab(vspace[1], H5S_SELECT_SET, start, NULL, dims, NULL) < 0)
+ TEST_ERROR
+
+ /* Add virtual layout mappings */
+ if(H5Pset_virtual(dcpl, vspace[0], config & TEST_IO_DIFFERENT_FILE ? srcfilenamepct_map : ".", "src_dset1", srcspace[0]) < 0)
+ TEST_ERROR
+ if(H5Pset_virtual(dcpl, vspace[1], config & TEST_IO_DIFFERENT_FILE ? srcfilenamepct_map : ".", "src_dset2", srcspace[0]) < 0)
+ TEST_ERROR
+
+ /* Reset dims */
+ dims[1] = 26;
+
+ /* Create virtual file */
+ if((vfile = H5Fcreate(vfilename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ TEST_ERROR
+
+ /* Create source file if requested */
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ if((srcfile[0] = H5Fcreate(srcfilenamepct, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+ else {
+ srcfile[0] = vfile;
+ if(H5Iinc_ref(srcfile[0]) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Create source datasets */
+ if((srcdset[0] = H5Dcreate2(srcfile[0], "src_dset1", H5T_NATIVE_INT, srcspace[0], H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if((srcdset[1] = H5Dcreate2(srcfile[0], "src_dset2", H5T_NATIVE_INT, srcspace[0], H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Create virtual dataset */
+ if((vdset = H5Dcreate2(vfile, "v_dset", H5T_NATIVE_INT, vspace[0], H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Populate write buffer */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ buf[i][j] = (i * (int)(sizeof(buf[0]) / sizeof(buf[0][0]))) + j;
+
+ /* Write data directly to source datasets */
+ if(H5Dwrite(srcdset[0], H5T_NATIVE_INT, vspace[0], H5S_ALL, dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+ if(H5Dwrite(srcdset[1], H5T_NATIVE_INT, vspace[1], H5S_ALL, dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+
+ /* Close srcdsets and srcfile if config option specified */
+ if(config & TEST_IO_CLOSE_SRC) {
+ if(H5Dclose(srcdset[0]) < 0)
+ TEST_ERROR
+ srcdset[0] = -1;
+ if(H5Dclose(srcdset[1]) < 0)
+ TEST_ERROR
+ srcdset[1] = -1;
+
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ if(H5Fclose(srcfile[0]) < 0)
+ TEST_ERROR
+ srcfile[0] = -1;
+ } /* end if */
+ } /* end if */
+
+ /* Reopen virtual dataset and file if config option specified */
+ if(config & TEST_IO_REOPEN_VIRT) {
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ vdset = -1;
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if((vfile = H5Fopen(vfilename, H5F_ACC_RDWR, fapl)) < 0)
+ TEST_ERROR
+ if((vdset = H5Dopen2(vfile, "v_dset", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Read first source dataset through virtual dataset */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+ if(H5Dread(vdset, H5T_NATIVE_INT, vspace[0], vspace[0], dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ if(rbuf[i][j] != (j < (int)(sizeof(buf[0]) / sizeof(buf[0][0]) / 2)
+ ? buf[i][j] : 0))
+ TEST_ERROR
+
+ /* Read second source dataset through virtual dataset */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+ if(H5Dread(vdset, H5T_NATIVE_INT, vspace[1], vspace[1], dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ if(rbuf[i][j] != (j < (int)(sizeof(buf[0]) / sizeof(buf[0][0]) / 2)
+ ? 0 : buf[i][j]))
+ TEST_ERROR
+
+ /* Adjust write buffer */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ buf[i][j] += (int)(sizeof(buf) / sizeof(buf[0][0]));
+
+ /* Write first source dataset through virtual dataset */
+ if(H5Dwrite(vdset, H5T_NATIVE_INT, vspace[0], vspace[0], dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+
+ /* Adjust write buffer */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ buf[i][j] += (int)(sizeof(buf) / sizeof(buf[0][0]));
+
+ /* Write second source dataset through virtual dataset */
+ if(H5Dwrite(vdset, H5T_NATIVE_INT, vspace[1], vspace[1], dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+
+ /* Reopen srcdsets and srcfile if config option specified */
+ if(config & TEST_IO_CLOSE_SRC) {
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ /* Flush virtual file. This is necessary since the parallel VDS
+ * implementation currently always opens source files independently
+ * with the sec2 driver, so HDF5 does not "match" the two and cannot
+ * share cached data. */
+ if(H5Fflush(vfile, H5F_SCOPE_GLOBAL) < 0)
+ TEST_ERROR
+
+ if((srcfile[0] = H5Fopen(srcfilenamepct, H5F_ACC_RDONLY, fapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+ if((srcdset[0] = H5Dopen2(srcfile[0], "src_dset1", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if((srcdset[1] = H5Dopen2(srcfile[0], "src_dset2", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Read data directly from source datasets */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+ if(H5Dread(srcdset[0], H5T_NATIVE_INT, vspace[0], H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+ if(H5Dread(srcdset[1], H5T_NATIVE_INT, vspace[1], H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ if(rbuf[i][j] != (j < (int)(sizeof(buf[0]) / sizeof(buf[0][0]) / 2)
+ ? (buf[i][j] - (int)(sizeof(buf) / sizeof(buf[0][0])))
+ : buf[i][j]))
+ TEST_ERROR
+
+ /* Close */
+ if(H5Dclose(srcdset[0]) < 0)
+ TEST_ERROR
+ srcdset[0] = -1;
+ if(H5Dclose(srcdset[1]) < 0)
+ TEST_ERROR
+ srcdset[1] = -1;
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ vdset = -1;
+ if(H5Fclose(srcfile[0]) < 0)
+ TEST_ERROR
+ srcfile[0] = -1;
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if(H5Sclose(srcspace[0]) < 0)
+ TEST_ERROR
+ srcspace[0] = -1;
+ if(H5Sclose(vspace[0]) < 0)
+ TEST_ERROR
+ vspace[0] = -1;
+ if(H5Sclose(vspace[1]) < 0)
+ TEST_ERROR
+ vspace[1] = -1;
+
+
+ /*
+ * Test 5: 2 Source datasets, hyperslab virtual mappings and selections
+ */
+ /* Clear virtual layout in DCPL */
+ if(H5Pset_layout(dcpl, H5D_VIRTUAL) < 0)
+ TEST_ERROR
+
+ /* Create virtual dataspaces */
+ if((vspace[0] = H5Screate_simple(2, dims, NULL)) < 0)
+ TEST_ERROR
+ if((vspace[1] = H5Screate_simple(2, dims, NULL)) < 0)
+ TEST_ERROR
+
+ /* Create source dataspaces */
+ if((srcspace[0] = H5Screate_simple(2, dims, NULL)) < 0)
+ TEST_ERROR
+ if((srcspace[1] = H5Screate_simple(2, dims, NULL)) < 0)
+ TEST_ERROR
+
+ /* Select hyperslabs in source space */
+ start[0] = 0;
+ start[1] = 0;
+ count[0] = 10;
+ count[1] = 13;
+ if(H5Sselect_hyperslab(srcspace[0], H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+ start[1] = 13;
+ if(H5Sselect_hyperslab(srcspace[1], H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+
+ /* Select hyperslabs in virtual spaces */
+ start[0] = 0;
+ start[1] = 0;
+ count[0] = 5;
+ count[1] = 26;
+ if(H5Sselect_hyperslab(vspace[0], H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+ start[0] = 5;
+ if(H5Sselect_hyperslab(vspace[1], H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+
+ /* Add virtual layout mappings */
+ if(H5Pset_virtual(dcpl, vspace[0], config & TEST_IO_DIFFERENT_FILE ? srcfilename_map : ".", "src_dset1", srcspace[0]) < 0)
+ TEST_ERROR
+ if(H5Pset_virtual(dcpl, vspace[1], config & TEST_IO_DIFFERENT_FILE ? srcfilename_map : ".", "src_dset2", srcspace[1]) < 0)
+ TEST_ERROR
+
+ /* Create virtual file */
+ if((vfile = H5Fcreate(vfilename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ TEST_ERROR
+
+ /* Create source file if requested */
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ if((srcfile[0] = H5Fcreate(srcfilename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+ else {
+ srcfile[0] = vfile;
+ if(H5Iinc_ref(srcfile[0]) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Create source datasets */
+ if((srcdset[0] = H5Dcreate2(srcfile[0], "src_dset1", H5T_NATIVE_INT, srcspace[0], H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if((srcdset[1] = H5Dcreate2(srcfile[0], "src_dset2", H5T_NATIVE_INT, srcspace[1], H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Create virtual dataset */
+ if((vdset = H5Dcreate2(vfile, "v_dset", H5T_NATIVE_INT, vspace[0], H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Populate write buffer */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ buf[i][j] = (i * (int)(sizeof(buf[0]) / sizeof(buf[0][0]))) + j;
+
+ /* Write data directly to source datasets */
+ /* Write first dataset */
+ if(H5Dwrite(srcdset[0], H5T_NATIVE_INT, H5S_ALL, H5S_ALL, dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+
+ /* Update evbuf */
+ for(i = 0; i < 5; i++) {
+ for(j = 0; j < 13; j++)
+ evbuf[i][j] = buf[2 * i][j];
+ for(/* j = 13 */; j < 26; j++)
+ evbuf[i][j] = buf[2 * i + 1][j - 13];
+ } /* end for */
+
+ /* Adjust write buffer */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ buf[i][j] += (int)(sizeof(buf) / sizeof(buf[0][0]));
+
+ /* Write second dataset */
+ if(H5Dwrite(srcdset[1], H5T_NATIVE_INT, H5S_ALL, H5S_ALL, dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+
+ /* Update evbuf */
+ for(i = 0; i < 5; i++) {
+ for(j = 0; j < 13; j++)
+ evbuf[i + 5][j] = buf[2 * i][j + 13];
+ for(/* j = 13 */; j < 26; j++)
+ evbuf[i + 5][j] = buf[2 * i + 1][j];
+ } /* end for */
+
+ /* Close srcdsets and srcfile if config option specified */
+ if(config & TEST_IO_CLOSE_SRC) {
+ if(H5Dclose(srcdset[0]) < 0)
+ TEST_ERROR
+ srcdset[0] = -1;
+ if(H5Dclose(srcdset[1]) < 0)
+ TEST_ERROR
+ srcdset[1] = -1;
+
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ if(H5Fclose(srcfile[0]) < 0)
+ TEST_ERROR
+ srcfile[0] = -1;
+ } /* end if */
+ } /* end if */
+
+ /* Reopen virtual dataset and file if config option specified */
+ if(config & TEST_IO_REOPEN_VIRT) {
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ vdset = -1;
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if((vfile = H5Fopen(vfilename, H5F_ACC_RDWR, fapl)) < 0)
+ TEST_ERROR
+ if((vdset = H5Dopen2(vfile, "v_dset", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Read data through virtual dataset by hyperslab */
+ /* Reset rbuf */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+
+ /* Read first slice */
+ if(H5Dread(vdset, H5T_NATIVE_INT, vspace[0], srcspace[0], dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Update erbuf */
+ for(i = 0; i < 5; i++) {
+ for(j = 0; j < 13; j++)
+ erbuf[i][j] = evbuf[2 * i][j];
+ for(/* j = 13 */; j < 26; j++)
+ erbuf[i][j] = evbuf[2 * i + 1][j - 13];
+ } /* end for */
+
+ /* Read second slice */
+ if(H5Dread(vdset, H5T_NATIVE_INT, vspace[1], srcspace[1], dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Update erbuf */
+ for(i = 0; i < 5; i++) {
+ for(j = 0; j < 13; j++)
+ erbuf[i + 5][j] = evbuf[2 * i][j + 13];
+ for(/* j = 13 */; j < 26; j++)
+ erbuf[i + 5][j] = evbuf[2 * i + 1][j];
+ } /* end for */
+
+ /* Verify read data */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+
+ /* Adjust write buffer */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ buf[i][j] += (int)(sizeof(buf) / sizeof(buf[0][0]));
+
+ /* Write data through virtual dataset */
+ /* Write first slice */
+ if(H5Dwrite(vdset, H5T_NATIVE_INT, vspace[0], srcspace[0], dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+
+ /* Update evbuf */
+ for(i = 0; i < 5; i++) {
+ for(j = 0; j < 13; j++)
+ evbuf[2 * i][j] = buf[i][j];
+ for(/* j = 13 */; j < 26; j++)
+ evbuf[2 * i + 1][j - 13] = buf[i][j];
+ } /* end for */
+
+ /* Adjust write buffer */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ buf[i][j] += (int)(sizeof(buf) / sizeof(buf[0][0]));
+
+ /* Write second slice */
+ if(H5Dwrite(vdset, H5T_NATIVE_INT, vspace[1], srcspace[1], dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+
+ /* Update evbuf */
+ for(i = 0; i < 5; i++) {
+ for(j = 0; j < 13; j++)
+ evbuf[2 * i][j + 13] = buf[i + 5][j];
+ for(/* j = 13 */; j < 26; j++)
+ evbuf[2 * i + 1][j] = buf[i + 5][j];
+ } /* end for */
+
+ /* Reopen srcdsets and srcfile if config option specified */
+ if(config & TEST_IO_CLOSE_SRC) {
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ /* Flush virtual file. This is necessary since the parallel VDS
+ * implementation currently always opens source files independently
+ * with the sec2 driver, so HDF5 does not "match" the two and cannot
+ * share cached data. */
+ if(H5Fflush(vfile, H5F_SCOPE_GLOBAL) < 0)
+ TEST_ERROR
+
+ if((srcfile[0] = H5Fopen(srcfilename, H5F_ACC_RDONLY, fapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+ if((srcdset[0] = H5Dopen2(srcfile[0], "src_dset1", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if((srcdset[1] = H5Dopen2(srcfile[0], "src_dset2", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Read data directly from source datasets */
+ /* Reset rbuf */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+
+ /* Read first dataset */
+ if(H5Dread(srcdset[0], H5T_NATIVE_INT, srcspace[0], srcspace[0], dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Update erbuf */
+ for(i = 0; i < 5; i++) {
+ for(j = 0; j < 13; j++)
+ erbuf[2 * i][j] = evbuf[i][j];
+ for(/* j = 13 */; j < 26; j++)
+ erbuf[2 * i + 1][j - 13] = evbuf[i][j];
+ } /* end for */
+
+ /* Read second dataset */
+ if(H5Dread(srcdset[1], H5T_NATIVE_INT, srcspace[1], srcspace[1], dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Update erbuf */
+ for(i = 0; i < 5; i++) {
+ for(j = 0; j < 13; j++)
+ erbuf[2 * i][j + 13] = evbuf[i + 5][j];
+ for(/* j = 13 */; j < 26; j++)
+ erbuf[2 * i + 1][j] = evbuf[i + 5][j];
+ } /* end for */
+
+ /* Verify read data */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+
+ /* Close */
+ if(H5Dclose(srcdset[0]) < 0)
+ TEST_ERROR
+ srcdset[0] = -1;
+ if(H5Dclose(srcdset[1]) < 0)
+ TEST_ERROR
+ srcdset[1] = -1;
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ vdset = -1;
+ if(H5Fclose(srcfile[0]) < 0)
+ TEST_ERROR
+ srcfile[0] = -1;
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if(H5Sclose(srcspace[0]) < 0)
+ TEST_ERROR
+ srcspace[0] = -1;
+ if(H5Sclose(srcspace[1]) < 0)
+ TEST_ERROR
+ srcspace[1] = -1;
+ if(H5Sclose(vspace[0]) < 0)
+ TEST_ERROR
+ vspace[0] = -1;
+ if(H5Sclose(vspace[1]) < 0)
+ TEST_ERROR
+ vspace[1] = -1;
+
+
+ /*
+ * Test 6: 2 Source datasets, checkerboard/stripe pattern to trigger
+ * sequence list refresh internally
+ */
+ /* Clear virtual layout in DCPL */
+ if(H5Pset_layout(dcpl, H5D_VIRTUAL) < 0)
+ TEST_ERROR
+
+ /* Create memory dataspace */
+ if((memspace = H5Screate_simple(2, dims, NULL)) < 0)
+ TEST_ERROR
+
+ /* Create virtual dataspaces */
+ dims[1] = 52;
+ if((vspace[0] = H5Screate_simple(2, dims, NULL)) < 0)
+ TEST_ERROR
+ if((vspace[1] = H5Screate_simple(2, dims, NULL)) < 0)
+ TEST_ERROR
+
+ /* Create source dataspace and file space for second operation (srcspace[1])
+ */
+ if((srcspace[0] = H5Screate_simple(2, dims, NULL)) < 0)
+ TEST_ERROR
+ if((srcspace[1] = H5Screate_simple(2, dims, NULL)) < 0)
+ TEST_ERROR
+
+ /* Reset dims */
+ dims[1] = 26;
+
+ /* Select hyperslabs (stripe) in source space and file space for second
+ * operation (srcspace[1]) */
+ start[0] = 0;
+ start[1] = 0;
+ stride[0] = 1;
+ stride[1] = 2;
+ count[0] = 1;
+ count[1] = 26;
+ block[0] = 10;
+ block[1] = 1;
+ if(H5Sselect_hyperslab(srcspace[0], H5S_SELECT_SET, start, stride, count, block) < 0)
+ TEST_ERROR
+ start[1] = 1;
+ if(H5Sselect_hyperslab(srcspace[1], H5S_SELECT_SET, start, stride, count, block) < 0)
+ TEST_ERROR
+
+ /* Select hyperslabs (checkerboard) in virtual spaces */
+ start[0] = 0;
+ start[1] = 0;
+ stride[0] = 2;
+ stride[1] = 2;
+ count[0] = 5;
+ count[1] = 26;
+ block[0] = 1;
+ block[1] = 1;
+ if(H5Sselect_hyperslab(vspace[0], H5S_SELECT_SET, start, stride, count, block) < 0)
+ TEST_ERROR
+ start[0] = 1;
+ start[1] = 1;
+ if(H5Sselect_hyperslab(vspace[0], H5S_SELECT_OR, start, stride, count, block) < 0)
+ TEST_ERROR
+ start[0] = 0;
+ if(H5Sselect_hyperslab(vspace[1], H5S_SELECT_SET, start, stride, count, block) < 0)
+ TEST_ERROR
+ start[0] = 1;
+ start[1] = 0;
+ if(H5Sselect_hyperslab(vspace[1], H5S_SELECT_OR, start, stride, count, block) < 0)
+ TEST_ERROR
+
+ /* Add virtual layout mappings */
+ if(H5Pset_virtual(dcpl, vspace[0], config & TEST_IO_DIFFERENT_FILE ? srcfilename_map : ".", "src_dset1", srcspace[0]) < 0)
+ TEST_ERROR
+ if(H5Pset_virtual(dcpl, vspace[1], config & TEST_IO_DIFFERENT_FILE ? srcfilename_map : ".", "src_dset2", srcspace[0]) < 0)
+ TEST_ERROR
+
+ /* Create virtual file */
+ if((vfile = H5Fcreate(vfilename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ TEST_ERROR
+
+ /* Create source file if requested */
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ if((srcfile[0] = H5Fcreate(srcfilename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+ else {
+ srcfile[0] = vfile;
+ if(H5Iinc_ref(srcfile[0]) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Create source datasets */
+ if((srcdset[0] = H5Dcreate2(srcfile[0], "src_dset1", H5T_NATIVE_INT, srcspace[0], H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if((srcdset[1] = H5Dcreate2(srcfile[0], "src_dset2", H5T_NATIVE_INT, srcspace[0], H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Create virtual dataset */
+ if((vdset = H5Dcreate2(vfile, "v_dset", H5T_NATIVE_INT, vspace[0], H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Populate write buffer */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ buf[i][j] = (i * (int)(sizeof(buf[0]) / sizeof(buf[0][0]))) + j;
+
+ /* Write data directly to source datasets */
+ /* Write first dataset */
+ if(H5Dwrite(srcdset[0], H5T_NATIVE_INT, memspace, srcspace[0], dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+
+ /* Update erbuf */
+ for(i = 0; i < 10; i += 2)
+ for(j = 0; j < 26; j++)
+ erbuf[i][j] = buf[i][j];
+
+ /* Adjust write buffer */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ buf[i][j] += (int)(sizeof(buf) / sizeof(buf[0][0]));
+
+ /* Write second dataset */
+ if(H5Dwrite(srcdset[1], H5T_NATIVE_INT, memspace, srcspace[0], dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+
+ /* Update erbuf */
+ for(i = 1; i < 10; i += 2)
+ for(j = 0; j < 26; j++)
+ erbuf[i][j] = buf[i][j];
+
+ /* Close srcdsets and srcfile if config option specified */
+ if(config & TEST_IO_CLOSE_SRC) {
+ if(H5Dclose(srcdset[0]) < 0)
+ TEST_ERROR
+ srcdset[0] = -1;
+ if(H5Dclose(srcdset[1]) < 0)
+ TEST_ERROR
+ srcdset[1] = -1;
+
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ if(H5Fclose(srcfile[0]) < 0)
+ TEST_ERROR
+ srcfile[0] = -1;
+ } /* end if */
+ } /* end if */
+
+ /* Reopen virtual dataset and file if config option specified */
+ if(config & TEST_IO_REOPEN_VIRT) {
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ vdset = -1;
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if((vfile = H5Fopen(vfilename, H5F_ACC_RDWR, fapl)) < 0)
+ TEST_ERROR
+ if((vdset = H5Dopen2(vfile, "v_dset", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Read data through virtual dataset by hyperslab */
+ /* Reset rbuf */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+
+ /* Read first stripe pattern */
+ if(H5Dread(vdset, H5T_NATIVE_INT, memspace, srcspace[0], dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+
+ /* Read second stripe pattern */
+ if(H5Dread(vdset, H5T_NATIVE_INT, memspace, srcspace[1], dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Update erbuf */
+ for(i = 0; i < 10; i += 2)
+ for(j = 0; j < 26; j++) {
+ erbuf[i][j] += (int)(sizeof(buf) / sizeof(buf[0][0]));
+ erbuf[i + 1][j] -= (int)(sizeof(buf) / sizeof(buf[0][0]));
+ } /* end for */
+
+ /* Verify read data */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+
+ /* Adjust write buffer */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ buf[i][j] += (int)(sizeof(buf) / sizeof(buf[0][0]));
+
+ /* Write data through virtual dataset */
+ /* Write first slice */
+ if(H5Dwrite(vdset, H5T_NATIVE_INT, memspace, srcspace[0], dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+
+ /* Update erbuf */
+ for(i = 0; i < 10; i += 2)
+ for(j = 0; j < 26; j++)
+ erbuf[i][j] = buf[i][j];
+
+ /* Adjust write buffer */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ buf[i][j] += (int)(sizeof(buf) / sizeof(buf[0][0]));
+
+ /* Write second slice */
+ if(H5Dwrite(vdset, H5T_NATIVE_INT, memspace, srcspace[1], dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+
+ /* Update erbuf */
+ for(i = 1; i < 10; i += 2)
+ for(j = 0; j < 26; j++)
+ erbuf[i][j] = buf[i][j];
+
+ /* Reopen srcdsets and srcfile if config option specified */
+ if(config & TEST_IO_CLOSE_SRC) {
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ /* Flush virtual file. This is necessary since the parallel VDS
+ * implementation currently always opens source files independently
+ * with the sec2 driver, so HDF5 does not "match" the two and cannot
+ * share cached data. */
+ if(H5Fflush(vfile, H5F_SCOPE_GLOBAL) < 0)
+ TEST_ERROR
+
+ if((srcfile[0] = H5Fopen(srcfilename, H5F_ACC_RDONLY, fapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+ if((srcdset[0] = H5Dopen2(srcfile[0], "src_dset1", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if((srcdset[1] = H5Dopen2(srcfile[0], "src_dset2", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Read data directly from source datasets */
+ /* Reset rbuf */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+
+ /* Read first dataset */
+ if(H5Dread(srcdset[0], H5T_NATIVE_INT, memspace, srcspace[0], dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+
+ /* Update erbuf */
+ for(i = 0; i < 10; i += 2)
+ for(j = 0; j < 26; j++) {
+ erbuf[i][j] += (int)(sizeof(buf) / sizeof(buf[0][0]));
+ erbuf[i + 1][j] -= (int)(sizeof(buf) / sizeof(buf[0][0]));
+ } /* end for */
+
+ /* Read second dataset */
+ if(H5Dread(srcdset[1], H5T_NATIVE_INT, memspace, srcspace[0], dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+
+ /* Close */
+ if(H5Dclose(srcdset[0]) < 0)
+ TEST_ERROR
+ srcdset[0] = -1;
+ if(H5Dclose(srcdset[1]) < 0)
+ TEST_ERROR
+ srcdset[1] = -1;
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ vdset = -1;
+ if(H5Fclose(srcfile[0]) < 0)
+ TEST_ERROR
+ srcfile[0] = -1;
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if(H5Sclose(srcspace[0]) < 0)
+ TEST_ERROR
+ srcspace[0] = -1;
+ if(H5Sclose(srcspace[1]) < 0)
+ TEST_ERROR
+ srcspace[1] = -1;
+ if(H5Sclose(vspace[0]) < 0)
+ TEST_ERROR
+ vspace[0] = -1;
+ if(H5Sclose(vspace[1]) < 0)
+ TEST_ERROR
+ vspace[1] = -1;
+ if(H5Sclose(memspace) < 0)
+ TEST_ERROR
+ memspace = -1;
+
+
+ /*
+ * Test 7: 1 Source dataset, two mappings, 4 dimensional virtual dataset
+ * and 3 dimensional source dataset
+ */
+ /* Clear virtual layout in DCPL */
+ if(H5Pset_layout(dcpl, H5D_VIRTUAL) < 0)
+ TEST_ERROR
+
+ /* Create memory dataspace */
+ if((memspace = H5Screate_simple(2, dims, NULL)) < 0)
+ TEST_ERROR
+
+ /* Create virtual dataspaces */
+ dims[0] = 3;
+ dims[1] = 3;
+ dims[2] = 3;
+ dims[3] = 3;
+ if((vspace[0] = H5Screate_simple(4, dims, NULL)) < 0)
+ TEST_ERROR
+ if((vspace[1] = H5Screate_simple(4, dims, NULL)) < 0)
+ TEST_ERROR
+
+ /* Create source dataspaces */
+ dims[0] = 2;
+ dims[1] = 4;
+ dims[2] = 4;
+ if((srcspace[0] = H5Screate_simple(3, dims, NULL)) < 0)
+ TEST_ERROR
+ if((srcspace[1] = H5Screate_simple(3, dims, NULL)) < 0)
+ TEST_ERROR
+
+ /* Reset dims */
+ dims[0] = 10;
+ dims[1] = 26;
+
+ /* Select hyperslabs (stripes) in source spaces */
+ start[0] = 0;
+ start[1] = 0;
+ start[2] = 0;
+ stride[0] = 1;
+ stride[1] = 2;
+ stride[2] = 1;
+ count[0] = 1;
+ count[1] = 2;
+ count[2] = 1;
+ block[0] = 2;
+ block[1] = 1;
+ block[2] = 4;
+ if(H5Sselect_hyperslab(srcspace[0], H5S_SELECT_SET, start, stride, count, block) < 0)
+ TEST_ERROR
+ start[1] = 1;
+ if(H5Sselect_hyperslab(srcspace[1], H5S_SELECT_SET, start, stride, count, block) < 0)
+ TEST_ERROR
+
+ /* Select hyperslabs (corners) in first virtual space */
+ start[0] = 0;
+ start[1] = 0;
+ start[2] = 0;
+ start[3] = 0;
+ stride[0] = 2;
+ stride[1] = 2;
+ stride[2] = 2;
+ stride[3] = 2;
+ count[0] = 2;
+ count[1] = 2;
+ count[2] = 2;
+ count[3] = 2;
+ block[0] = 1;
+ block[1] = 1;
+ block[2] = 1;
+ block[3] = 1;
+ if(H5Sselect_hyperslab(vspace[0], H5S_SELECT_SET, start, stride, count, block) < 0)
+ TEST_ERROR
+
+ /* Select hyperslabs ("+" pattern) in second virtual space */
+ start[0] = 1;
+ start[1] = 1;
+ start[2] = 0;
+ start[3] = 0;
+ stride[0] = 2;
+ stride[1] = 2;
+ stride[2] = 2;
+ stride[3] = 2;
+ count[0] = 1;
+ count[1] = 1;
+ count[2] = 2;
+ count[3] = 2;
+ block[0] = 1;
+ block[1] = 1;
+ block[2] = 1;
+ block[3] = 1;
+ if(H5Sselect_hyperslab(vspace[1], H5S_SELECT_SET, start, stride, count, block) < 0)
+ TEST_ERROR
+ start[1] = 0;
+ start[2] = 1;
+ count[1] = 2;
+ count[2] = 1;
+ if(H5Sselect_hyperslab(vspace[1], H5S_SELECT_OR, start, stride, count, block) < 0)
+ TEST_ERROR
+ start[0] = 0;
+ start[1] = 1;
+ count[0] = 2;
+ count[1] = 1;
+ if(H5Sselect_hyperslab(vspace[1], H5S_SELECT_OR, start, stride, count, block) < 0)
+ TEST_ERROR
+ start[0] = 1;
+ count[0] = 1;
+ if(H5Sselect_hyperslab(vspace[1], H5S_SELECT_OR, start, stride, count, block) < 0)
+ TEST_ERROR
+ start[1] = 0;
+ start[3] = 1;
+ count[1] = 2;
+ count[3] = 1;
+ if(H5Sselect_hyperslab(vspace[1], H5S_SELECT_OR, start, stride, count, block) < 0)
+ TEST_ERROR
+
+ /* Add virtual layout mappings */
+ if(H5Pset_virtual(dcpl, vspace[0], config & TEST_IO_DIFFERENT_FILE ? srcfilename_map : ".", "src_dset1", srcspace[0]) < 0)
+ TEST_ERROR
+ if(H5Pset_virtual(dcpl, vspace[1], config & TEST_IO_DIFFERENT_FILE ? srcfilename_map : ".", "src_dset1", srcspace[1]) < 0)
+ TEST_ERROR
+
+ /* Create virtual file */
+ if((vfile = H5Fcreate(vfilename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ TEST_ERROR
+
+ /* Create source file if requested */
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ if((srcfile[0] = H5Fcreate(srcfilename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+ else {
+ srcfile[0] = vfile;
+ if(H5Iinc_ref(srcfile[0]) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Create source dataset */
+ if((srcdset[0] = H5Dcreate2(srcfile[0], "src_dset1", H5T_NATIVE_INT, srcspace[0], H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Create virtual dataset */
+ if((vdset = H5Dcreate2(vfile, "v_dset", H5T_NATIVE_INT, vspace[0], H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Populate write buffer */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ buf[i][j] = (i * (int)(sizeof(buf[0]) / sizeof(buf[0][0]))) + j;
+
+ /* Select hyperslab in memory space */
+ start[0] = 0;
+ start[1] = 0;
+ count[0] = 2;
+ count[1] = 16;
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL ,count, NULL) < 0)
+ TEST_ERROR
+
+ /* Write data directly to source dataset */
+ if(H5Dwrite(srcdset[0], H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+
+ /* Close srcdset and srcfile if config option specified */
+ if(config & TEST_IO_CLOSE_SRC) {
+ if(H5Dclose(srcdset[0]) < 0)
+ TEST_ERROR
+ srcdset[0] = -1;
+
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ if(H5Fclose(srcfile[0]) < 0)
+ TEST_ERROR
+ srcfile[0] = -1;
+ } /* end if */
+ } /* end if */
+
+ /* Reopen virtual dataset and file if config option specified */
+ if(config & TEST_IO_REOPEN_VIRT) {
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ vdset = -1;
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if((vfile = H5Fopen(vfilename, H5F_ACC_RDWR, fapl)) < 0)
+ TEST_ERROR
+ if((vdset = H5Dopen2(vfile, "v_dset", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Read data through virtual dataset */
+ /* Reset rbuf */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+
+ /* Select hyperslab in memory space */
+ start[0] = 0;
+ start[1] = 0;
+ count[0] = 9;
+ count[1] = 3;
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL ,count, NULL) < 0)
+ TEST_ERROR
+
+ /* Read data through virtual dataset by hyperslab */
+ /* Reset rbuf */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+
+ /* Select stripe */
+ start[0] = 0;
+ start[1] = 0;
+ start[2] = 0;
+ start[3] = 0;
+ count[0] = 3;
+ count[1] = 3;
+ count[2] = 1;
+ count[3] = 3;
+ if(H5Sselect_hyperslab(vspace[0], H5S_SELECT_SET, start, NULL ,count, NULL) < 0)
+ TEST_ERROR
+
+ /* Read first stripe pattern */
+ if(H5Dread(vdset, H5T_NATIVE_INT, memspace, vspace[0], dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Update erbuf */
+ HDmemset(erbuf, 0, sizeof(erbuf));
+ for(i = 0; i < 9; i++)
+ for(j = 0; j < 3; j++)
+ erbuf[i][j] = fill;
+ erbuf[0][0] = buf[0][0];
+ erbuf[0][2] = buf[0][1];
+ erbuf[2][0] = buf[0][8];
+ erbuf[2][2] = buf[0][9];
+ erbuf[6][0] = buf[1][0];
+ erbuf[6][2] = buf[1][1];
+ erbuf[8][0] = buf[1][8];
+ erbuf[8][2] = buf[1][9];
+ erbuf[4][0] = buf[0][13];
+ erbuf[4][2] = buf[0][14];
+
+ /* Verify read data */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+
+ /* Reset rbuf */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+
+ /* Select stripe */
+ start[0] = 0;
+ start[1] = 0;
+ start[2] = 1;
+ start[3] = 0;
+ count[0] = 3;
+ count[1] = 3;
+ count[2] = 1;
+ count[3] = 3;
+ if(H5Sselect_hyperslab(vspace[0], H5S_SELECT_SET, start, NULL ,count, NULL) < 0)
+ TEST_ERROR
+
+ /* Select hyperslab in memory space */
+ start[0] = 0;
+ start[1] = 3;
+ count[0] = 9;
+ count[1] = 3;
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL ,count, NULL) < 0)
+ TEST_ERROR
+
+ /* Read second stripe pattern */
+ if(H5Dread(vdset, H5T_NATIVE_INT, memspace, vspace[0], dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Update erbuf */
+ for(i = 0; i < 9; i++)
+ for(j = 3; j < 6; j++)
+ erbuf[i][j] = fill;
+ erbuf[1][3] = buf[0][4];
+ erbuf[1][5] = buf[0][5];
+ erbuf[3][3] = buf[0][6];
+ erbuf[3][4] = buf[0][7];
+ erbuf[3][5] = buf[0][12];
+ erbuf[4][3] = buf[0][15];
+ erbuf[4][5] = buf[1][4];
+ erbuf[5][3] = buf[1][7];
+ erbuf[5][4] = buf[1][12];
+ erbuf[5][5] = buf[1][13];
+ erbuf[7][3] = buf[1][14];
+ erbuf[7][5] = buf[1][15];
+
+ /* Verify read data */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ if((j >= 3) && (j < 6)) {
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+ } /* end if */
+ else
+ if(rbuf[i][j] != 0)
+ TEST_ERROR
+
+ /* Reset rbuf */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+
+ /* Select stripe */
+ start[0] = 0;
+ start[1] = 0;
+ start[2] = 2;
+ start[3] = 0;
+ count[0] = 3;
+ count[1] = 3;
+ count[2] = 1;
+ count[3] = 3;
+ if(H5Sselect_hyperslab(vspace[0], H5S_SELECT_SET, start, NULL ,count, NULL) < 0)
+ TEST_ERROR
+
+ /* Select hyperslab in memory space */
+ start[0] = 0;
+ start[1] = 6;
+ count[0] = 9;
+ count[1] = 3;
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL ,count, NULL) < 0)
+ TEST_ERROR
+
+ /* Read third stripe pattern */
+ if(H5Dread(vdset, H5T_NATIVE_INT, memspace, vspace[0], dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Update erbuf */
+ for(i = 0; i < 9; i++)
+ for(j = 6; j < 9; j++)
+ erbuf[i][j] = fill;
+ erbuf[0][6] = buf[0][2];
+ erbuf[0][8] = buf[0][3];
+ erbuf[2][6] = buf[0][10];
+ erbuf[2][8] = buf[0][11];
+ erbuf[6][6] = buf[1][2];
+ erbuf[6][8] = buf[1][3];
+ erbuf[8][6] = buf[1][10];
+ erbuf[8][8] = buf[1][11];
+ erbuf[4][6] = buf[1][5];
+ erbuf[4][8] = buf[1][6];
+
+ /* Verify read data */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ if((j >= 6) && (j < 9)) {
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+ } /* end if */
+ else
+ if(rbuf[i][j] != 0)
+ TEST_ERROR
+
+ /* Now read entire VDS */
+ /* Set memory space extent to 9x9, select all in order to reach part of the
+ * code in H5S_select_subtract() */
+ dims[0] = 9;
+ dims[1] = 9;
+ if(H5Sset_extent_simple(memspace, 2, dims, NULL) < 0)
+ TEST_ERROR
+ if(H5Sselect_all(memspace) < 0)
+ TEST_ERROR
+
+ /* Read third stripe pattern */
+ if(H5Dread(vdset, H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, rbuf99[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)(sizeof(rbuf99) / sizeof(rbuf99[0])); i++)
+ for(j = 0; j < (int)(sizeof(rbuf99[0]) / sizeof(rbuf99[0][0])); j++)
+ if(rbuf99[i][j] != erbuf[i][j])
+ TEST_ERROR
+
+ /* Adjust write buffer */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ buf[i][j] += (int)(sizeof(buf) / sizeof(buf[0][0]));
+
+ /* Write data through virtual dataset by hyperslab */
+ /* Select stripe (only select mapped elements) */
+ start[0] = 0;
+ start[1] = 0;
+ start[2] = 0;
+ start[3] = 0;
+ stride[0] = 2;
+ stride[1] = 2;
+ stride[2] = 1;
+ stride[3] = 2;
+ count[0] = 2;
+ count[1] = 2;
+ count[2] = 1;
+ count[3] = 2;
+ if(H5Sselect_hyperslab(vspace[0], H5S_SELECT_SET, start, stride ,count, NULL) < 0)
+ TEST_ERROR
+ start[0] = 1;
+ start[1] = 1;
+ start[2] = 0;
+ start[3] = 0;
+ stride[0] = 1;
+ stride[1] = 1;
+ stride[2] = 1;
+ stride[3] = 2;
+ count[0] = 1;
+ count[1] = 1;
+ count[2] = 1;
+ count[3] = 2;
+ if(H5Sselect_hyperslab(vspace[0], H5S_SELECT_OR, start, stride ,count, NULL) < 0)
+ TEST_ERROR
+
+ /* Reset extent of memspace, select hyperslab */
+ dims[0] = 10;
+ dims[1] = 26;
+ if(H5Sset_extent_simple(memspace, 2, dims, NULL) < 0)
+ TEST_ERROR
+ start[0] = 0;
+ start[1] = 0;
+ count[0] = 1;
+ count[1] = 10;
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL ,count, NULL) < 0)
+ TEST_ERROR
+
+ /* Write data through virtual dataset by hyperslab */
+ /* Write first stripe pattern */
+ if(H5Dwrite(vdset, H5T_NATIVE_INT, memspace, vspace[0], dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+
+ /* Update erbuf */
+ HDmemset(erbuf, 0, sizeof(erbuf));
+ erbuf[0][0] = buf[0][0];
+ erbuf[0][1] = buf[0][1];
+ erbuf[0][8] = buf[0][2];
+ erbuf[0][9] = buf[0][3];
+ erbuf[1][0] = buf[0][6];
+ erbuf[1][1] = buf[0][7];
+ erbuf[1][8] = buf[0][8];
+ erbuf[1][9] = buf[0][9];
+ erbuf[0][13] = buf[0][4];
+ erbuf[0][14] = buf[0][5];
+
+ /* Adjust write buffer */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ buf[i][j] += (int)(sizeof(buf) / sizeof(buf[0][0]));
+
+ /* Select stripe (only select mapped elements) */
+ start[0] = 0;
+ start[1] = 1;
+ start[2] = 1;
+ start[3] = 0;
+ stride[0] = 1;
+ stride[1] = 1;
+ stride[2] = 1;
+ stride[3] = 2;
+ count[0] = 3;
+ count[1] = 1;
+ count[2] = 1;
+ count[3] = 2;
+ if(H5Sselect_hyperslab(vspace[0], H5S_SELECT_SET, start, stride ,count, NULL) < 0)
+ TEST_ERROR
+ start[0] = 1;
+ start[1] = 0;
+ start[2] = 1;
+ start[3] = 0;
+ stride[0] = 1;
+ stride[1] = 2;
+ stride[2] = 1;
+ stride[3] = 1;
+ count[0] = 1;
+ count[1] = 2;
+ count[2] = 1;
+ count[3] = 3;
+ if(H5Sselect_hyperslab(vspace[0], H5S_SELECT_OR, start, stride ,count, NULL) < 0)
+ TEST_ERROR
+
+ /* Select hyperslab in memory space */
+ start[0] = 0;
+ start[1] = 0;
+ count[0] = 1;
+ count[1] = 12;
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL ,count, NULL) < 0)
+ TEST_ERROR
+
+ /* Write second slice */
+ if(H5Dwrite(vdset, H5T_NATIVE_INT, memspace, vspace[0], dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+
+ /* Update erbuf */
+ erbuf[0][4] = buf[0][0];
+ erbuf[0][5] = buf[0][1];
+ erbuf[0][6] = buf[0][2];
+ erbuf[0][7] = buf[0][3];
+ erbuf[0][12] = buf[0][4];
+ erbuf[0][15] = buf[0][5];
+ erbuf[1][4] = buf[0][6];
+ erbuf[1][7] = buf[0][7];
+ erbuf[1][12] = buf[0][8];
+ erbuf[1][13] = buf[0][9];
+ erbuf[1][14] = buf[0][10];
+ erbuf[1][15] = buf[0][11];
+
+ /* Adjust write buffer */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ buf[i][j] += (int)(sizeof(buf) / sizeof(buf[0][0]));
+
+ /* Select stripe (only select mapped elements) */
+ start[0] = 0;
+ start[1] = 0;
+ start[2] = 2;
+ start[3] = 0;
+ stride[0] = 2;
+ stride[1] = 2;
+ stride[2] = 1;
+ stride[3] = 2;
+ count[0] = 2;
+ count[1] = 2;
+ count[2] = 1;
+ count[3] = 2;
+ if(H5Sselect_hyperslab(vspace[0], H5S_SELECT_SET, start, stride ,count, NULL) < 0)
+ TEST_ERROR
+ start[0] = 1;
+ start[1] = 1;
+ start[2] = 2;
+ start[3] = 0;
+ stride[0] = 1;
+ stride[1] = 1;
+ stride[2] = 1;
+ stride[3] = 2;
+ count[0] = 1;
+ count[1] = 1;
+ count[2] = 1;
+ count[3] = 2;
+ if(H5Sselect_hyperslab(vspace[0], H5S_SELECT_OR, start, stride ,count, NULL) < 0)
+ TEST_ERROR
+
+ /* Select hyperslab in memory space */
+ start[0] = 0;
+ start[1] = 0;
+ count[0] = 1;
+ count[1] = 10;
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL ,count, NULL) < 0)
+ TEST_ERROR
+
+ /* Write third slice */
+ if(H5Dwrite(vdset, H5T_NATIVE_INT, memspace, vspace[0], dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+
+ /* Update erbuf */
+ erbuf[0][2] = buf[0][0];
+ erbuf[0][3] = buf[0][1];
+ erbuf[0][10] = buf[0][2];
+ erbuf[0][11] = buf[0][3];
+ erbuf[1][2] = buf[0][6];
+ erbuf[1][3] = buf[0][7];
+ erbuf[1][10] = buf[0][8];
+ erbuf[1][11] = buf[0][9];
+ erbuf[1][5] = buf[0][4];
+ erbuf[1][6] = buf[0][5];
+
+ /* Reopen srcdset and srcfile if config option specified */
+ if(config & TEST_IO_CLOSE_SRC) {
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ /* Flush virtual file. This is necessary since the parallel VDS
+ * implementation currently always opens source files independently
+ * with the sec2 driver, so HDF5 does not "match" the two and cannot
+ * share cached data. */
+ if(H5Fflush(vfile, H5F_SCOPE_GLOBAL) < 0)
+ TEST_ERROR
+
+ if((srcfile[0] = H5Fopen(srcfilename, H5F_ACC_RDONLY, fapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+ if((srcdset[0] = H5Dopen2(srcfile[0], "src_dset1", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Read data directly from source dataset */
+ /* Select hyperslab in memory space */
+ start[0] = 0;
+ start[1] = 0;
+ count[0] = 2;
+ count[1] = 16;
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL ,count, NULL) < 0)
+ TEST_ERROR
+
+ /* Reset rbuf */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+
+ /* Read dataset */
+ if(H5Dread(srcdset[0], H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++)
+ for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++)
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+
+ /* Now try writing to whole VDS (should fail due to unmapped elements) */
+ count[0] = 9;
+ count[1] = 9;
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+ H5E_BEGIN_TRY {
+ ret = H5Dwrite(vdset, H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, buf[0]);
+ } H5E_END_TRY
+ if(ret >= 0)
+ TEST_ERROR
+
+ /* Close */
+ if(H5Dclose(srcdset[0]) < 0)
+ TEST_ERROR
+ srcdset[0] = -1;
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ vdset = -1;
+ if(H5Fclose(srcfile[0]) < 0)
+ TEST_ERROR
+ srcfile[0] = -1;
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if(H5Sclose(srcspace[0]) < 0)
+ TEST_ERROR
+ srcspace[0] = -1;
+ if(H5Sclose(srcspace[1]) < 0)
+ TEST_ERROR
+ srcspace[1] = -1;
+ if(H5Sclose(vspace[0]) < 0)
+ TEST_ERROR
+ vspace[0] = -1;
+ if(H5Sclose(vspace[1]) < 0)
+ TEST_ERROR
+ vspace[1] = -1;
+ if(H5Sclose(memspace) < 0)
+ TEST_ERROR
+ memspace = -1;
+
+
+ /* Close */
+ if(H5Pclose(dcpl) < 0)
+ TEST_ERROR
+ dcpl = -1;
+
+ if(H5Pclose(dxpl_id) < 0)
+ TEST_ERROR
+ dxpl_id = -1;
+
+ if (mpi_rank == 0)
+ PASSED();
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ for(i = 0; i < (int)(sizeof(srcdset) / sizeof(srcdset[0])); i++) {
+ if(srcdset[i] >= 0)
+ (void)H5Dclose(srcdset[i]);
+ } /* end for */
+ if(vdset >= 0)
+ (void)H5Dclose(vdset);
+ for(i = 0; i < (int)(sizeof(srcfile) / sizeof(srcfile[0])); i++) {
+ if(srcfile[i] >= 0)
+ (void)H5Fclose(srcfile[i]);
+ } /* end for */
+ if(vfile >= 0)
+ (void)H5Fclose(vfile);
+ if(vfile2 >= 0)
+ (void)H5Fclose(vfile2);
+ for(i = 0; i < (int)(sizeof(srcspace) / sizeof(srcspace[0])); i++) {
+ if(srcspace[i] >= 0)
+ (void)H5Sclose(srcspace[i]);
+ } /* end for */
+ for(i = 0; i < (int)(sizeof(vspace) / sizeof(vspace[0])); i++) {
+ if(vspace[i] >= 0)
+ (void)H5Sclose(vspace[i]);
+ } /* end for */
+ if(memspace >= 0)
+ (void)H5Sclose(memspace);
+ if(dcpl >= 0)
+ (void)H5Pclose(dcpl);
+ if(dxpl_id >= 0)
+ (void)H5Pclose(dxpl_id);
+ } H5E_END_TRY;
+
+ return 1;
+} /* end test_basic_io() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_unlim
+ *
+ * Purpose: Tests VDS with unlimited selections
+ *
+ * Return: Success: 0
+ *
+ * Failure: number of errors
+ *
+ * Programmer: Neil Fortner
+ * Thursday, April 30, 2015
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_unlim(unsigned config, hid_t fapl)
+{
+ char srcfilename[FILENAME_BUF_SIZE];
+ char srcfilename_map[FILENAME_BUF_SIZE];
+ char vfilename[FILENAME_BUF_SIZE];
+ hid_t srcfile[4] = {-1, -1, -1, -1}; /* Files with source dsets */
+ hid_t vfile = -1; /* File with virtual dset */
+ hid_t dcpl = -1; /* Dataset creation property list */
+ hid_t srcdcpl = -1; /* DCPL for source dset */
+ hid_t dapl = -1; /* Dataset access property list */
+ hid_t srcspace[4] = {-1, -1, -1, -1}; /* Source dataspaces */
+ hid_t vspace[4] = {-1, -1, -1, -1}; /* Virtual dset dataspaces */
+ hid_t memspace = -1; /* Memory dataspace */
+ hid_t filespace = -1; /* File dataspace */
+ hid_t srcdset[4] = {-1, -1, -1, -1}; /* Source datsets */
+ hid_t vdset = -1; /* Virtual dataset */
+ hid_t dxpl_id = -1; /* Dataset Transfer property */
+
+ hsize_t dims[2] = {10, 10}; /* Data space current size */
+ hsize_t mdims[2] = {10, 20}; /* Data space maximum size */
+ hsize_t cdims[2] = {4, 4}; /* Chunk dimensions */
+ hsize_t start[4]; /* Hyperslab start */
+ hsize_t stride[4]; /* Hyperslab stride */
+ hsize_t count[4]; /* Hyperslab count */
+ hsize_t block[4]; /* Hyperslab block */
+ int buf[10][20]; /* Write and expected read buffer */
+ int rbuf[10][20]; /* Read buffer */
+ int erbuf[10][20]; /* Expected read buffer */
+ int ndims; /* Number of dimensions */
+ int fill = -1; /* Fill value */
+ H5D_vds_view_t virtual_view; /* Virtual view property */
+ int i, j;
+
+ if (mpi_rank == 0)
+ TESTING("virtual dataset I/O with unlimited selections")
+
+ h5_fixname(FILENAME[0], fapl, vfilename, sizeof vfilename);
+ h5_fixname(FILENAME[2], fapl, srcfilename, sizeof srcfilename);
+ h5_fixname_printf(FILENAME[2], fapl, srcfilename_map, sizeof srcfilename_map);
+
+ if((dxpl_id = H5Pcreate(H5P_DATASET_XFER)) < 0 )
+ TEST_ERROR
+
+ if((H5Pset_dxpl_mpio(dxpl_id, H5FD_MPIO_COLLECTIVE)) < 0 )
+ TEST_ERROR
+
+
+ /* Create DCPLs */
+ if((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0)
+ TEST_ERROR
+ if((srcdcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0)
+ TEST_ERROR
+
+ /* Set fill value */
+ if(H5Pset_fill_value(dcpl, H5T_NATIVE_INT, &fill) < 0)
+ TEST_ERROR
+
+ /* Set chunk dimensions */
+ if(H5Pset_chunk(srcdcpl, 2, cdims) < 0)
+ TEST_ERROR
+
+ /* Create DAPL */
+ if((dapl = H5Pcreate(H5P_DATASET_ACCESS)) < 0)
+ TEST_ERROR
+
+ /* Create memory space */
+ if((memspace = H5Screate_simple(2, mdims, NULL)) < 0)
+ TEST_ERROR
+
+
+ /*
+ * Test 1: 2 Source datasets, single unlimited hyperslab virtual mappings
+ */
+ /* Clear virtual layout in DCPL */
+ if(H5Pset_layout(dcpl, H5D_VIRTUAL) < 0)
+ TEST_ERROR
+
+ /* Create virtual dataspaces */
+ if((vspace[0] = H5Screate_simple(2, dims, mdims)) < 0)
+ TEST_ERROR
+ if((vspace[1] = H5Screate_simple(2, dims, mdims)) < 0)
+ TEST_ERROR
+
+ /* Create source dataspace */
+ dims[0] = 5;
+ mdims[0] = 5;
+ if((srcspace[0] = H5Screate_simple(2, dims, mdims)) < 0)
+ TEST_ERROR
+ mdims[0] = 10;
+
+ /* Select hyperslab in source space */
+ start[0] = 0;
+ start[1] = 0;
+ count[0] = 5;
+ count[1] = H5S_UNLIMITED;
+ if(H5Sselect_hyperslab(srcspace[0], H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+
+ /* Select hyperslabs in virtual spaces */
+ if(H5Sselect_hyperslab(vspace[0], H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+ start[0] = 5;
+ if(H5Sselect_hyperslab(vspace[1], H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+
+ /* Add virtual layout mappings */
+ if(H5Pset_virtual(dcpl, vspace[0], config & TEST_IO_DIFFERENT_FILE ? srcfilename_map : ".", "src_dset1", srcspace[0]) < 0)
+ TEST_ERROR
+ if(H5Pset_virtual(dcpl, vspace[1], config & TEST_IO_DIFFERENT_FILE ? srcfilename_map : ".", "src_dset2", srcspace[0]) < 0)
+ TEST_ERROR
+
+ /* Create virtual file */
+ if((vfile = H5Fcreate(vfilename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ TEST_ERROR
+
+ /* Create source file if requested */
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ if((srcfile[0] = H5Fcreate(srcfilename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+ else {
+ srcfile[0] = vfile;
+ if(H5Iinc_ref(srcfile[0]) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Create source datasets */
+ if((srcdset[0] = H5Dcreate2(srcfile[0], "src_dset1", H5T_NATIVE_INT, srcspace[0], H5P_DEFAULT, srcdcpl, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if((srcdset[1] = H5Dcreate2(srcfile[0], "src_dset2", H5T_NATIVE_INT, srcspace[0], H5P_DEFAULT, srcdcpl, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Create virtual dataset */
+ if((vdset = H5Dcreate2(vfile, "v_dset", H5T_NATIVE_INT, vspace[0], H5P_DEFAULT, dcpl, dapl)) < 0)
+ TEST_ERROR
+
+ /* Populate write buffer */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++)
+ buf[i][j] = (i * (int)mdims[1]) + j;
+
+ /* Initialize erbuf */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++)
+ erbuf[i][j] = fill;
+
+ /* Write data directly to source datasets */
+ /* Select hyperslab in memory */
+ start[0] = 0;
+ count[1] = 10;
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+
+ /* Write first dataset */
+ if(H5Dwrite(srcdset[0], H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+
+ /* Update erbuf */
+ for(i = 0; i < 5; i++)
+ for(j = 0; j < 10; j++)
+ erbuf[i][j] = buf[i][j];
+
+ /* Adjust write buffer */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++)
+ buf[i][j] += (int)mdims[0] * (int)mdims[1];
+
+ /* Write second dataset */
+ if(H5Dwrite(srcdset[1], H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+
+ /* Update erbuf */
+ for(i = 0; i < 5; i++)
+ for(j = 0; j < 10; j++)
+ erbuf[i + 5][j] = buf[i][j];
+
+ /* Close srcdsets and srcfile if config option specified */
+ if(config & TEST_IO_CLOSE_SRC) {
+ if(H5Dclose(srcdset[0]) < 0)
+ TEST_ERROR
+ srcdset[0] = -1;
+ if(H5Dclose(srcdset[1]) < 0)
+ TEST_ERROR
+ srcdset[1] = -1;
+
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ if(H5Fclose(srcfile[0]) < 0)
+ TEST_ERROR
+ srcfile[0] = -1;
+ } /* end if */
+ } /* end if */
+
+#ifdef H5_HAVE_PARALLEL
+ /* Don't allow test processes to read the current dataset while others
+ * might still be doing the previous WRITE
+ */
+ MPI_Barrier(MPI_COMM_WORLD);
+#endif
+
+ /* Reopen virtual dataset and file if config option specified. Also do this
+ * if we're using a separate source file to switch to read only. */
+ if((config & TEST_IO_REOPEN_VIRT) || (config & TEST_IO_DIFFERENT_FILE)) {
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ vdset = -1;
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if((vfile = H5Fopen(vfilename, H5F_ACC_RDONLY, fapl)) < 0)
+ TEST_ERROR
+ if((vdset = H5Dopen2(vfile, "v_dset", dapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Get VDS space */
+ if((filespace = H5Dget_space(vdset)) < 0)
+ TEST_ERROR
+ /* Get VDS space dimensions */
+ if((ndims = H5Sget_simple_extent_ndims(filespace)) < 0)
+ TEST_ERROR
+ if(ndims != 2)
+ TEST_ERROR
+ if(H5Sget_simple_extent_dims(filespace, dims, mdims) < 0)
+ TEST_ERROR
+ if(dims[0] != 10)
+ TEST_ERROR
+ if(dims[1] != 10)
+ TEST_ERROR
+ if(mdims[0] != 10)
+ TEST_ERROR
+ if(mdims[1] != 20)
+ TEST_ERROR
+
+ /* Close filespace */
+ if(H5Sclose(filespace) < 0)
+ TEST_ERROR
+
+ /* Read data through virtual dataset */
+ /* Reset rbuf */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+
+ /* Select hyperslab in memory space */
+ start[0] = 0;
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, dims, NULL) < 0)
+ TEST_ERROR
+
+ /* Read data */
+ if(H5Dread(vdset, H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++) {
+ if(j >= (int)dims[1]) {
+ if(rbuf[i][j] != 0)
+ TEST_ERROR
+ } /* end if */
+ else
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+ } /* end for */
+
+ /* Test H5Pget_virtual_view() */
+ if(H5Pget_virtual_view(dapl, &virtual_view) < 0)
+ TEST_ERROR
+ if(virtual_view != H5D_VDS_LAST_AVAILABLE)
+ TEST_ERROR
+
+ /* Close VDS and reopen with view set to H5D_VDS_FIRST_MISSING, reopen file
+ * as well if config option specified */
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ if(H5Pset_virtual_view(dapl, H5D_VDS_FIRST_MISSING) < 0)
+ TEST_ERROR
+ if(config & TEST_IO_REOPEN_VIRT) {
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if((vfile = H5Fopen(vfilename, H5F_ACC_RDONLY, fapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+ if((vdset = H5Dopen2(vfile, "v_dset", dapl)) < 0)
+ TEST_ERROR
+
+ /* Test H5Pget_virtual_view() */
+ if(H5Pget_virtual_view(dapl, &virtual_view) < 0)
+ TEST_ERROR
+ if(virtual_view != H5D_VDS_FIRST_MISSING)
+ TEST_ERROR
+
+ /* Get VDS space */
+ if((filespace = H5Dget_space(vdset)) < 0)
+ TEST_ERROR
+ /* Get VDS space dimensions */
+ if((ndims = H5Sget_simple_extent_ndims(filespace)) < 0)
+ TEST_ERROR
+ if(ndims != 2)
+ TEST_ERROR
+ if(H5Sget_simple_extent_dims(filespace, dims, mdims) < 0)
+ TEST_ERROR
+ if(dims[0] != 10)
+ TEST_ERROR
+ if(dims[1] != 10)
+ TEST_ERROR
+ if(mdims[0] != 10)
+ TEST_ERROR
+ if(mdims[1] != 20)
+ TEST_ERROR
+
+ /* Close filespace */
+ if(H5Sclose(filespace) < 0)
+ TEST_ERROR
+
+ /* Read data through virtual dataset */
+ /* Reset rbuf */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+
+ /* Read data */
+ if(H5Dread(vdset, H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++) {
+ if(j >= (int)dims[1]) {
+ if(rbuf[i][j] != 0)
+ TEST_ERROR
+ } /* end if */
+ else
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+ } /* end for */
+
+ /* Reopen srcdset[0] and srcfile if config option specified */
+ if(config & TEST_IO_CLOSE_SRC) {
+ if(config & TEST_IO_DIFFERENT_FILE)
+ if((srcfile[0] = H5Fopen(srcfilename, H5F_ACC_RDWR, fapl)) < 0)
+ TEST_ERROR
+ if((srcdset[0] = H5Dopen2(srcfile[0], "src_dset1", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Extend srcdset[0] */
+ dims[0] = 5;
+ dims[1] = 15;
+ if(H5Dset_extent(srcdset[0], dims) < 0)
+ TEST_ERROR
+
+ /* Adjust write buffer */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++)
+ buf[i][j] += (int)mdims[0] * (int)mdims[1];
+
+ /* Write to new area of srcdset */
+ count[1] = 5;
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+ if((filespace = H5Dget_space(srcdset[0])) < 0)
+ TEST_ERROR
+
+ start[1] = 10;
+ if(H5Sselect_hyperslab(filespace, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+ if(H5Dwrite(srcdset[0], H5T_NATIVE_INT, memspace, filespace, dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+ if(H5Sclose(filespace) < 0)
+ TEST_ERROR
+
+ /* Close srcdset[0] and srcfile if config option specified */
+ if(config & TEST_IO_CLOSE_SRC) {
+ if(H5Dclose(srcdset[0]) < 0)
+ TEST_ERROR
+ srcdset[0] = -1;
+
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ if(H5Fclose(srcfile[0]) < 0)
+ TEST_ERROR
+ srcfile[0] = -1;
+ } /* end if */
+ } /* end if */
+
+ /* Reopen virtual dataset and file if config option specified. Always
+ * reopen if using a different file so the VDS gets an updated view of the
+ * source datasets. */
+ if((config & TEST_IO_REOPEN_VIRT) || (config & TEST_IO_DIFFERENT_FILE)) {
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ vdset = -1;
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if((vfile = H5Fopen(vfilename, H5F_ACC_RDONLY, fapl)) < 0)
+ TEST_ERROR
+ if((vdset = H5Dopen2(vfile, "v_dset", dapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Get VDS space */
+ if((filespace = H5Dget_space(vdset)) < 0)
+ TEST_ERROR
+ /* Get VDS space dimensions. Note that since we are using
+ * H5D_VDS_FIRST_MISSING and we only extended one source dataset the
+ * dimensions will not have changed. */
+ if((ndims = H5Sget_simple_extent_ndims(filespace)) < 0)
+ TEST_ERROR
+ if(ndims != 2)
+ TEST_ERROR
+ if(H5Sget_simple_extent_dims(filespace, dims, mdims) < 0)
+ TEST_ERROR
+ if(dims[0] != 10)
+ TEST_ERROR
+ if(dims[1] != 10)
+ TEST_ERROR
+ if(mdims[0] != 10)
+ TEST_ERROR
+ if(mdims[1] != 20)
+ TEST_ERROR
+
+ /* Close filespace */
+ if(H5Sclose(filespace) < 0)
+ TEST_ERROR
+
+ /* Read data through virtual dataset */
+ /* Reset rbuf */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+
+ /* Select hyperslab in memory space */
+ start[1] = 0;
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, dims, NULL) < 0)
+ TEST_ERROR
+
+ /* Read data */
+ if(H5Dread(vdset, H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++) {
+ if(j >= (int)dims[1]) {
+ if(rbuf[i][j] != 0)
+ TEST_ERROR
+ } /* end if */
+ else
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+ } /* end for */
+
+ /* Close VDS and reopen with view set to H5D_VDS_LAST_AVAILABLE, reopen file
+ * as well if config option specified. */
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ if(H5Pset_virtual_view(dapl, H5D_VDS_LAST_AVAILABLE) < 0)
+ TEST_ERROR
+ if(config & TEST_IO_REOPEN_VIRT) {
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if((vfile = H5Fopen(vfilename, H5F_ACC_RDONLY, fapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+ if((vdset = H5Dopen2(vfile, "v_dset", dapl)) < 0)
+ TEST_ERROR
+
+ /* Update erbuf to reflect new data that is now visible due to the change to
+ * H5D_VDS_LAST_AVAILABLE */
+ for(i = 0; i < 5; i++)
+ for(j = 0; j < 5; j++)
+ erbuf[i][j + 10] = buf[i][j];
+
+ /* Get VDS space */
+ if((filespace = H5Dget_space(vdset)) < 0)
+ TEST_ERROR
+
+ /* Get VDS space dimensions */
+ if((ndims = H5Sget_simple_extent_ndims(filespace)) < 0)
+ TEST_ERROR
+ if(ndims != 2)
+ TEST_ERROR
+ if(H5Sget_simple_extent_dims(filespace, dims, mdims) < 0)
+ TEST_ERROR
+ if(dims[0] != 10)
+ TEST_ERROR
+ if(dims[1] != 15)
+ TEST_ERROR
+ if(mdims[0] != 10)
+ TEST_ERROR
+ if(mdims[1] != 20)
+ TEST_ERROR
+
+ /* Close filespace */
+ if(H5Sclose(filespace) < 0)
+ TEST_ERROR
+
+ /* Read data through virtual dataset */
+ /* Reset rbuf */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+
+ /* Select hyperslab in memory space */
+ start[1] = 0;
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, dims, NULL) < 0)
+ TEST_ERROR
+
+ /* Read data */
+ if(H5Dread(vdset, H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++) {
+ if(j >= (int)dims[1]) {
+ if(rbuf[i][j] != 0)
+ TEST_ERROR
+ } /* end if */
+ else
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+ } /* end for */
+
+ /* Reopen srcdset[1] and srcfile if config option specified */
+ if(config & TEST_IO_CLOSE_SRC) {
+ if(config & TEST_IO_DIFFERENT_FILE)
+ if((srcfile[0] = H5Fopen(srcfilename, H5F_ACC_RDWR, fapl)) < 0)
+ TEST_ERROR
+ if((srcdset[1] = H5Dopen2(srcfile[0], "src_dset2", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Extend srcdset[1] */
+ dims[0] = 5;
+ dims[1] = 20;
+ if(H5Dset_extent(srcdset[1], dims) < 0)
+ TEST_ERROR
+
+ /* Adjust write buffer */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++)
+ buf[i][j] += (int)mdims[0] * (int)mdims[1];
+
+ /* Write to new area of srcdset */
+ count[1] = 10;
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+ if((filespace = H5Dget_space(srcdset[1])) < 0)
+ TEST_ERROR
+ start[1] = 10;
+ if(H5Sselect_hyperslab(filespace, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+ if(H5Dwrite(srcdset[1], H5T_NATIVE_INT, memspace, filespace, dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+ if(H5Sclose(filespace) < 0)
+ TEST_ERROR
+
+ /* Update erbuf */
+ for(i = 0; i < 5; i++)
+ for(j = 0; j < 10; j++)
+ erbuf[i + 5][j + 10] = buf[i][j];
+
+ /* Close srcdset[1] and srcfile if config option specified */
+ if(config & TEST_IO_CLOSE_SRC) {
+ if(H5Dclose(srcdset[1]) < 0)
+ TEST_ERROR
+ srcdset[1] = -1;
+
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ if(H5Fclose(srcfile[0]) < 0)
+ TEST_ERROR
+ srcfile[0] = -1;
+ } /* end if */
+ } /* end if */
+
+ /* Reopen virtual dataset and file if config option specified. Switch back
+ * to RDWR here to make sure the extent gets written. Always reopen if
+ * using a different file so the VDS gets an updated view of the source
+ * datasets. */
+ if((config & TEST_IO_REOPEN_VIRT) || (config & TEST_IO_DIFFERENT_FILE)) {
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ vdset = -1;
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if((vfile = H5Fopen(vfilename, H5F_ACC_RDWR, fapl)) < 0)
+ TEST_ERROR
+ if((vdset = H5Dopen2(vfile, "v_dset", dapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Get VDS space */
+ if((filespace = H5Dget_space(vdset)) < 0)
+ TEST_ERROR
+
+ /* Get VDS space dimensions */
+ if((ndims = H5Sget_simple_extent_ndims(filespace)) < 0)
+ TEST_ERROR
+ if(ndims != 2)
+ TEST_ERROR
+ if(H5Sget_simple_extent_dims(filespace, dims, mdims) < 0)
+ TEST_ERROR
+ if(dims[0] != 10)
+ TEST_ERROR
+ if(dims[1] != 20)
+ TEST_ERROR
+ if(mdims[0] != 10)
+ TEST_ERROR
+ if(mdims[1] != 20)
+ TEST_ERROR
+
+ /* Close filespace */
+ if(H5Sclose(filespace) < 0)
+ TEST_ERROR
+
+ /* Read data through virtual dataset */
+ /* Reset rbuf */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+
+ /* Select hyperslab in memory space */
+ start[1] = 0;
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, dims, NULL) < 0)
+ TEST_ERROR
+
+ /* Read data */
+ if(H5Dread(vdset, H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++)
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+
+ /* Now just read middle 2 rows */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+ start[0] = 4;
+ count[0] = 2;
+ count[1] = 20;
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+ if(H5Dread(vdset, H5T_NATIVE_INT, memspace, memspace, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data - algorithmically check for only 2 middle rows being
+ * read so we don't have to wipe out erbuf and then restore it afterwards */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++)
+ if((i == 4) || (i == 5)) {
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+ } /* end if */
+ else
+ if(rbuf[i][j] != 0)
+ TEST_ERROR
+
+ /* Now test reopening virtual dataset without calling H5Dget_space, if
+ * REOPEN_VIRT flag set */
+ if(config & TEST_IO_REOPEN_VIRT) {
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ vdset = -1;
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if((vfile = H5Fopen(vfilename, H5F_ACC_RDWR, fapl)) < 0)
+ TEST_ERROR
+ if((vdset = H5Dopen2(vfile, "v_dset", dapl)) < 0)
+ TEST_ERROR
+
+ /* Read data through virtual dataset */
+ /* Reset rbuf */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+
+ /* Select hyperslab in memory space */
+ start[0] = 0;
+ start[1] = 0;
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, dims, NULL) < 0)
+ TEST_ERROR
+
+ /* Read data */
+ if(H5Dread(vdset, H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++)
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+
+ /* Now try setting extent manually */
+ /* Shrink to 18 */
+ dims[1] = 18;
+ if(H5Dset_extent(vdset, dims) < 0)
+ TEST_ERROR
+
+ /* Read data through virtual dataset */
+ /* Reset rbuf */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+
+ /* Select hyperslab in memory space */
+ start[0] = 0;
+ start[1] = 0;
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, dims, NULL) < 0)
+ TEST_ERROR
+
+ /* Read data */
+ if(H5Dread(vdset, H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++) {
+ if(j >= (int)dims[1]) {
+ if(rbuf[i][j] != 0)
+ TEST_ERROR
+ } /* end if */
+ else
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+ } /* end for */
+
+ /* Shrink to 15 */
+ dims[1] = 15;
+ if(H5Dset_extent(vdset, dims) < 0)
+ TEST_ERROR
+
+ /* Read data through virtual dataset */
+ /* Reset rbuf */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+
+ /* Select hyperslab in memory space */
+ start[0] = 0;
+ start[1] = 0;
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, dims, NULL) < 0)
+ TEST_ERROR
+
+ /* Read data */
+ if(H5Dread(vdset, H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++) {
+ if(j >= (int)dims[1]) {
+ if(rbuf[i][j] != 0)
+ TEST_ERROR
+ } /* end if */
+ else
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+ } /* end for */
+ } /* end if */
+
+ /* Close VDS and reopen with view set to H5D_VDS_FIRST_MISSING, reopen file
+ * as well if config option specified */
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ if(H5Pset_virtual_view(dapl, H5D_VDS_FIRST_MISSING) < 0)
+ TEST_ERROR
+ if(config & TEST_IO_REOPEN_VIRT) {
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if((vfile = H5Fopen(vfilename, H5F_ACC_RDONLY, fapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+ if((vdset = H5Dopen2(vfile, "v_dset", dapl)) < 0)
+ TEST_ERROR
+
+ /* Get VDS space */
+ if((filespace = H5Dget_space(vdset)) < 0)
+ TEST_ERROR
+ /* Get VDS space dimensions */
+ if((ndims = H5Sget_simple_extent_ndims(filespace)) < 0)
+ TEST_ERROR
+ if(ndims != 2)
+ TEST_ERROR
+ if(H5Sget_simple_extent_dims(filespace, dims, mdims) < 0)
+ TEST_ERROR
+ if(dims[0] != 10)
+ TEST_ERROR
+ if(dims[1] != 15)
+ TEST_ERROR
+ if(mdims[0] != 10)
+ TEST_ERROR
+ if(mdims[1] != 20)
+ TEST_ERROR
+
+ /* Close filespace */
+ if(H5Sclose(filespace) < 0)
+ TEST_ERROR
+
+ /* Read data through virtual dataset */
+ /* Reset rbuf */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+
+ /* Select hyperslab in memory space */
+ start[0] = 0;
+ start[1] = 0;
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, dims, NULL) < 0)
+ TEST_ERROR
+
+ /* Read data */
+ if(H5Dread(vdset, H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++) {
+ if(j >= (int)dims[1]) {
+ if(rbuf[i][j] != 0)
+ TEST_ERROR
+ } /* end if */
+ else
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+ } /* end for */
+
+ /* Now test reopening virtual dataset without calling H5Dget_space, if
+ * REOPEN_VIRT flag set */
+ if(config & TEST_IO_REOPEN_VIRT) {
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ vdset = -1;
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if((vfile = H5Fopen(vfilename, H5F_ACC_RDWR, fapl)) < 0)
+ TEST_ERROR
+ if((vdset = H5Dopen2(vfile, "v_dset", dapl)) < 0)
+ TEST_ERROR
+
+ /* Read data through virtual dataset */
+ /* Reset rbuf */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+
+ /* Select hyperslab in memory space */
+ start[1] = 0;
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, dims, NULL) < 0)
+ TEST_ERROR
+
+ /* Read data */
+ if(H5Dread(vdset, H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++) {
+ if(j >= (int)dims[1]) {
+ if(rbuf[i][j] != 0)
+ TEST_ERROR
+ } /* end if */
+ else
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+ } /* end for */
+
+ /* Now try setting extent manually */
+ /* Grow to 18 */
+ dims[1] = 18;
+ if(H5Dset_extent(vdset, dims) < 0)
+ TEST_ERROR
+
+ /* Read data through virtual dataset */
+ /* Reset rbuf */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+
+ /* Select hyperslab in memory space */
+ start[0] = 0;
+ start[1] = 0;
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, dims, NULL) < 0)
+ TEST_ERROR
+
+ /* Read data */
+ if(H5Dread(vdset, H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++) {
+ if(j >= (int)dims[1]) {
+ if(rbuf[i][j] != 0)
+ TEST_ERROR
+ } /* end if */
+ else
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+ } /* end for */
+
+ /* Grow to 20 */
+ dims[1] = 20;
+ if(H5Dset_extent(vdset, dims) < 0)
+ TEST_ERROR
+
+ /* Read data through virtual dataset */
+ /* Reset rbuf */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+
+ /* Select hyperslab in memory space */
+ start[0] = 0;
+ start[1] = 0;
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, dims, NULL) < 0)
+ TEST_ERROR
+
+ /* Read data */
+ if(H5Dread(vdset, H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++)
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+ } /* end if */
+
+ /* Close */
+ if(!(config & TEST_IO_CLOSE_SRC)) {
+ if(H5Dclose(srcdset[0]) < 0)
+ TEST_ERROR
+ srcdset[0] = -1;
+ if(H5Dclose(srcdset[1]) < 0)
+ TEST_ERROR
+ srcdset[1] = -1;
+ if(H5Fclose(srcfile[0]) < 0)
+ TEST_ERROR
+ srcfile[0] = -1;
+ } /* end if */
+ else if(!(config & TEST_IO_DIFFERENT_FILE)) {
+ if(H5Fclose(srcfile[0]) < 0)
+ TEST_ERROR
+ srcfile[0] = -1;
+ } /* end if */
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ vdset = -1;
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if(H5Sclose(srcspace[0]) < 0)
+ TEST_ERROR
+ srcspace[0] = -1;
+ if(H5Sclose(vspace[0]) < 0)
+ TEST_ERROR
+ vspace[0] = -1;
+ if(H5Sclose(vspace[1]) < 0)
+ TEST_ERROR
+ vspace[1] = -1;
+
+
+ /*
+ * Test 2: 2 Source datasets, interleaved slices, single element wide
+ */
+ /* Clear virtual layout in DCPL */
+ if(H5Pset_layout(dcpl, H5D_VIRTUAL) < 0)
+ TEST_ERROR
+
+ /* Create virtual dataspaces */
+ dims[0] = 10;
+ dims[1] = 10;
+ if((vspace[0] = H5Screate_simple(2, dims, mdims)) < 0)
+ TEST_ERROR
+ if((vspace[1] = H5Screate_simple(2, dims, mdims)) < 0)
+ TEST_ERROR
+
+ /* Create source dataspace */
+ dims[1] = 5;
+ mdims[1] = 10;
+ if((srcspace[0] = H5Screate_simple(2, dims, mdims)) < 0)
+ TEST_ERROR
+ mdims[1] = 20;
+
+ /* Select hyperslab in source space */
+ start[0] = 0;
+ start[1] = 0;
+ count[0] = 10;
+ count[1] = H5S_UNLIMITED;
+ if(H5Sselect_hyperslab(srcspace[0], H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+
+ /* Select hyperslabs in virtual spaces */
+ stride[0] = 1;
+ stride[1] = 2;
+ count[0] = 1;
+ count[1] = H5S_UNLIMITED;
+ block[0] = 10;
+ block[1] = 1;
+ if(H5Sselect_hyperslab(vspace[0], H5S_SELECT_SET, start, stride, count, block) < 0)
+ TEST_ERROR
+ start[1] = 1;
+ if(H5Sselect_hyperslab(vspace[1], H5S_SELECT_SET, start, stride, count, block) < 0)
+ TEST_ERROR
+ start[1] = 0;
+
+ /* Add virtual layout mappings */
+ if(H5Pset_virtual(dcpl, vspace[0], config & TEST_IO_DIFFERENT_FILE ? srcfilename_map : ".", "src_dset1", srcspace[0]) < 0)
+ TEST_ERROR
+ if(H5Pset_virtual(dcpl, vspace[1], config & TEST_IO_DIFFERENT_FILE ? srcfilename_map : ".", "src_dset2", srcspace[0]) < 0)
+ TEST_ERROR
+
+ /* Create virtual file */
+ if((vfile = H5Fcreate(vfilename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ TEST_ERROR
+
+ /* Create source file if requested */
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ if((srcfile[0] = H5Fcreate(srcfilename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+ else {
+ srcfile[0] = vfile;
+ if(H5Iinc_ref(srcfile[0]) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Create source datasets */
+ if((srcdset[0] = H5Dcreate2(srcfile[0], "src_dset1", H5T_NATIVE_INT, srcspace[0], H5P_DEFAULT, srcdcpl, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if((srcdset[1] = H5Dcreate2(srcfile[0], "src_dset2", H5T_NATIVE_INT, srcspace[0], H5P_DEFAULT, srcdcpl, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Create virtual dataset */
+ if((vdset = H5Dcreate2(vfile, "v_dset", H5T_NATIVE_INT, vspace[0], H5P_DEFAULT, dcpl, dapl)) < 0)
+ TEST_ERROR
+
+ /* Populate write buffer */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++)
+ buf[i][j] = (i * (int)mdims[1]) + j;
+
+ /* Initialize erbuf */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++)
+ erbuf[i][j] = fill;
+
+ /* Write data directly to source datasets */
+ /* Select hyperslab in memory */
+ count[0] = 10;
+ count[1] = 5;
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+
+ /* Write first dataset */
+ if(H5Dwrite(srcdset[0], H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+
+ /* Update erbuf */
+ for(i = 0; i < 10; i++)
+ for(j = 0; j < 5; j++)
+ erbuf[i][2 * j] = buf[i][j];
+
+ /* Adjust write buffer */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++)
+ buf[i][j] += (int)mdims[0] * (int)mdims[1];
+
+ /* Write second dataset */
+ if(H5Dwrite(srcdset[1], H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+
+ /* Update erbuf */
+ for(i = 0; i < 10; i++)
+ for(j = 0; j < 5; j++)
+ erbuf[i][(2 * j) + 1] = buf[i][j];
+
+ /* Close srcdsets and srcfile if config option specified */
+ if(config & TEST_IO_CLOSE_SRC) {
+ if(H5Dclose(srcdset[0]) < 0)
+ TEST_ERROR
+ srcdset[0] = -1;
+ if(H5Dclose(srcdset[1]) < 0)
+ TEST_ERROR
+ srcdset[1] = -1;
+
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ if(H5Fclose(srcfile[0]) < 0)
+ TEST_ERROR
+ srcfile[0] = -1;
+ } /* end if */
+ } /* end if */
+
+ /* Reopen virtual dataset and file if config option specified. Also do this
+ * if we're using a separate source file to switch to read only. */
+ if((config & TEST_IO_REOPEN_VIRT) || (config & TEST_IO_DIFFERENT_FILE)) {
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ vdset = -1;
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if((vfile = H5Fopen(vfilename, H5F_ACC_RDONLY, fapl)) < 0)
+ TEST_ERROR
+ if((vdset = H5Dopen2(vfile, "v_dset", dapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Get VDS space */
+ if((filespace = H5Dget_space(vdset)) < 0)
+ TEST_ERROR
+
+ /* Get VDS space dimensions */
+ if((ndims = H5Sget_simple_extent_ndims(filespace)) < 0)
+ TEST_ERROR
+ if(ndims != 2)
+ TEST_ERROR
+ if(H5Sget_simple_extent_dims(filespace, dims, mdims) < 0)
+ TEST_ERROR
+ if(dims[0] != 10)
+ TEST_ERROR
+ if(dims[1] != 10)
+ TEST_ERROR
+ if(mdims[0] != 10)
+ TEST_ERROR
+ if(mdims[1] != 20)
+ TEST_ERROR
+
+ /* Close filespace */
+ if(H5Sclose(filespace) < 0)
+ TEST_ERROR
+
+ /* Read data through virtual dataset */
+ /* Reset rbuf */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+
+ /* Select hyperslab in memory space */
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, dims, NULL) < 0)
+ TEST_ERROR
+
+ /* Read data */
+ if(H5Dread(vdset, H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++) {
+ if(j >= (int)dims[1]) {
+ if(rbuf[i][j] != 0)
+ TEST_ERROR
+ } /* end if */
+ else
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+ } /* end for */
+
+ /* Close VDS and reopen with view set to H5D_VDS_FIRST_MISSING, reopen file
+ * as well if config option specified */
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ if(H5Pset_virtual_view(dapl, H5D_VDS_FIRST_MISSING) < 0)
+ TEST_ERROR
+ if(config & TEST_IO_REOPEN_VIRT) {
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if((vfile = H5Fopen(vfilename, H5F_ACC_RDONLY, fapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+ if((vdset = H5Dopen2(vfile, "v_dset", dapl)) < 0)
+ TEST_ERROR
+
+ /* Get VDS space */
+ if((filespace = H5Dget_space(vdset)) < 0)
+ TEST_ERROR
+
+ /* Get VDS space dimensions */
+ if((ndims = H5Sget_simple_extent_ndims(filespace)) < 0)
+ TEST_ERROR
+ if(ndims != 2)
+ TEST_ERROR
+ if(H5Sget_simple_extent_dims(filespace, dims, mdims) < 0)
+ TEST_ERROR
+ if(dims[0] != 10)
+ TEST_ERROR
+ if(dims[1] != 10)
+ TEST_ERROR
+ if(mdims[0] != 10)
+ TEST_ERROR
+ if(mdims[1] != 20)
+ TEST_ERROR
+
+ /* Close filespace */
+ if(H5Sclose(filespace) < 0)
+ TEST_ERROR
+
+ /* Read data through virtual dataset */
+ /* Reset rbuf */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+
+ /* Read data */
+ if(H5Dread(vdset, H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++) {
+ if(j >= (int)dims[1]) {
+ if(rbuf[i][j] != 0)
+ TEST_ERROR
+ } /* end if */
+ else
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+ } /* end for */
+
+ /* Reopen srcdset[0] and srcfile if config option specified */
+ if(config & TEST_IO_CLOSE_SRC) {
+ if(config & TEST_IO_DIFFERENT_FILE)
+ if((srcfile[0] = H5Fopen(srcfilename, H5F_ACC_RDWR, fapl)) < 0)
+ TEST_ERROR
+ if((srcdset[0] = H5Dopen2(srcfile[0], "src_dset1", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Extend srcdset[0] */
+ dims[1] = 7;
+ if(H5Dset_extent(srcdset[0], dims) < 0)
+ TEST_ERROR
+
+ /* Adjust write buffer */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++)
+ buf[i][j] += (int)mdims[0] * (int)mdims[1];
+
+ /* Write to new area of srcdset */
+ count[1] = 2;
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+ if((filespace = H5Dget_space(srcdset[0])) < 0)
+ TEST_ERROR
+ start[1] = 5;
+ if(H5Sselect_hyperslab(filespace, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+ start[1] = 0;
+ if(H5Dwrite(srcdset[0], H5T_NATIVE_INT, memspace, filespace, dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+ if(H5Sclose(filespace) < 0)
+ TEST_ERROR
+
+ /* Update erbuf to reflect only new data that is now visible under
+ * H5D_VDS_FIRST_MISSING (first slice) */
+ for(i = 0; i < 10; i++)
+ erbuf[i][10] = buf[i][0];
+
+ /* Close srcdset[0] and srcfile if config option specified */
+ if(config & TEST_IO_CLOSE_SRC) {
+ if(H5Dclose(srcdset[0]) < 0)
+ TEST_ERROR
+ srcdset[0] = -1;
+
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ if(H5Fclose(srcfile[0]) < 0)
+ TEST_ERROR
+ srcfile[0] = -1;
+ } /* end if */
+ } /* end if */
+
+ /* Reopen virtual dataset and file if config option specified. Always
+ * reopen if using a different file so the VDS gets an updated view of the
+ * source datasets. */
+ if((config & TEST_IO_REOPEN_VIRT) || (config & TEST_IO_DIFFERENT_FILE)) {
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ vdset = -1;
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if((vfile = H5Fopen(vfilename, H5F_ACC_RDONLY, fapl)) < 0)
+ TEST_ERROR
+ if((vdset = H5Dopen2(vfile, "v_dset", dapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Get VDS space */
+ if((filespace = H5Dget_space(vdset)) < 0)
+ TEST_ERROR
+
+ /* Get VDS space dimensions. Note that since we are using
+ * H5D_VDS_FIRST_MISSING and we only extended one source dataset the
+ * dimension will only have changed to add one more slice. */
+ if((ndims = H5Sget_simple_extent_ndims(filespace)) < 0)
+ TEST_ERROR
+ if(ndims != 2)
+ TEST_ERROR
+ if(H5Sget_simple_extent_dims(filespace, dims, mdims) < 0)
+ TEST_ERROR
+ if(dims[0] != 10)
+ TEST_ERROR
+ if(dims[1] != 11)
+ TEST_ERROR
+ if(mdims[0] != 10)
+ TEST_ERROR
+ if(mdims[1] != 20)
+ TEST_ERROR
+
+ /* Close filespace */
+ if(H5Sclose(filespace) < 0)
+ TEST_ERROR
+
+ /* Read data through virtual dataset */
+ /* Reset rbuf */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+
+ /* Select hyperslab in memory space */
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, dims, NULL) < 0)
+ TEST_ERROR
+
+ /* Read data */
+ if(H5Dread(vdset, H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++) {
+ if(j >= (int)dims[1]) {
+ if(rbuf[i][j] != 0)
+ TEST_ERROR
+ } /* end if */
+ else
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+ } /* end for */
+
+ /* Close VDS and reopen with view set to H5D_VDS_LAST_AVAILABLE, reopen file
+ * as well if config option specified */
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ if(H5Pset_virtual_view(dapl, H5D_VDS_LAST_AVAILABLE) < 0)
+ TEST_ERROR
+ if(config & TEST_IO_REOPEN_VIRT) {
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if((vfile = H5Fopen(vfilename, H5F_ACC_RDONLY, fapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+ if((vdset = H5Dopen2(vfile, "v_dset", dapl)) < 0)
+ TEST_ERROR
+
+ /* Update erbuf to reflect new data that is now visible due to the change to
+ * H5D_VDS_LAST_AVAILABLE (second new slice) */
+ for(i = 0; i < 10; i++)
+ erbuf[i][12] = buf[i][1];
+
+ /* Get VDS space */
+ if((filespace = H5Dget_space(vdset)) < 0)
+ TEST_ERROR
+
+ /* Get VDS space dimensions */
+ if((ndims = H5Sget_simple_extent_ndims(filespace)) < 0)
+ TEST_ERROR
+ if(ndims != 2)
+ TEST_ERROR
+ if(H5Sget_simple_extent_dims(filespace, dims, mdims) < 0)
+ TEST_ERROR
+ if(dims[0] != 10)
+ TEST_ERROR
+ if(dims[1] != 13)
+ TEST_ERROR
+ if(mdims[0] != 10)
+ TEST_ERROR
+ if(mdims[1] != 20)
+ TEST_ERROR
+
+ /* Close filespace */
+ if(H5Sclose(filespace) < 0)
+ TEST_ERROR
+
+ /* Read data through virtual dataset */
+ /* Reset rbuf */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+
+ /* Select hyperslab in memory space */
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, dims, NULL) < 0)
+ TEST_ERROR
+
+ /* Read data */
+ if(H5Dread(vdset, H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++) {
+ if(j >= (int)dims[1]) {
+ if(rbuf[i][j] != 0)
+ TEST_ERROR
+ } /* end if */
+ else
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+ } /* end for */
+
+ /* Reopen srcdset[1] and srcfile if config option specified */
+ if(config & TEST_IO_CLOSE_SRC) {
+ if(config & TEST_IO_DIFFERENT_FILE)
+ if((srcfile[0] = H5Fopen(srcfilename, H5F_ACC_RDWR, fapl)) < 0)
+ TEST_ERROR
+ if((srcdset[1] = H5Dopen2(srcfile[0], "src_dset2", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Extend srcdset[1] */
+ dims[1] = 10;
+ if(H5Dset_extent(srcdset[1], dims) < 0)
+ TEST_ERROR
+
+ /* Adjust write buffer */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++)
+ buf[i][j] += (int)mdims[0] * (int)mdims[1];
+
+ /* Write to new area of srcdset */
+ count[1] = 5;
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+ if((filespace = H5Dget_space(srcdset[1])) < 0)
+ TEST_ERROR
+ start[1] = 5;
+ if(H5Sselect_hyperslab(filespace, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+ start[1] = 0;
+ if(H5Dwrite(srcdset[1], H5T_NATIVE_INT, memspace, filespace, dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+ if(H5Sclose(filespace) < 0)
+ TEST_ERROR
+
+ /* Update erbuf */
+ for(i = 0; i < 10; i++)
+ for(j = 0; j < 5; j++)
+ erbuf[i][(2 * j) + 11] = buf[i][j];
+
+ /* Close srcdset[1] and srcfile if config option specified */
+ if(config & TEST_IO_CLOSE_SRC) {
+ if(H5Dclose(srcdset[1]) < 0)
+ TEST_ERROR
+ srcdset[1] = -1;
+
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ if(H5Fclose(srcfile[0]) < 0)
+ TEST_ERROR
+ srcfile[0] = -1;
+ } /* end if */
+ } /* end if */
+
+ /* Reopen virtual dataset and file if config option specified. Always
+ * reopen if using a different file so the VDS gets an updated view of the
+ * source datasets. */
+ if((config & TEST_IO_REOPEN_VIRT) || (config & TEST_IO_DIFFERENT_FILE)) {
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ vdset = -1;
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if((vfile = H5Fopen(vfilename, H5F_ACC_RDONLY, fapl)) < 0)
+ TEST_ERROR
+ if((vdset = H5Dopen2(vfile, "v_dset", dapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Get VDS space */
+ if((filespace = H5Dget_space(vdset)) < 0)
+ TEST_ERROR
+
+ /* Get VDS space dimensions */
+ if((ndims = H5Sget_simple_extent_ndims(filespace)) < 0)
+ TEST_ERROR
+ if(ndims != 2)
+ TEST_ERROR
+ if(H5Sget_simple_extent_dims(filespace, dims, mdims) < 0)
+ TEST_ERROR
+ if(dims[0] != 10)
+ TEST_ERROR
+ if(dims[1] != 20)
+ TEST_ERROR
+ if(mdims[0] != 10)
+ TEST_ERROR
+ if(mdims[1] != 20)
+ TEST_ERROR
+
+ /* Close filespace */
+ if(H5Sclose(filespace) < 0)
+ TEST_ERROR
+
+ /* Read data through virtual dataset */
+ /* Reset rbuf */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+
+ /* Select hyperslab in memory space */
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, dims, NULL) < 0)
+ TEST_ERROR
+
+ /* Read data */
+ if(H5Dread(vdset, H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++)
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+
+ /* Now just read middle 2 rows */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+ start[0] = 4;
+ count[0] = 2;
+ count[1] = 20;
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+ start[0] = 0;
+ if(H5Dread(vdset, H5T_NATIVE_INT, memspace, memspace, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data - algorithmically check for only 2 middle rows being
+ * read so we don't have to wipe out erbuf and then restore it afterwards */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++)
+ if((i == 4) || (i == 5)) {
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+ } /* end if */
+ else
+ if(rbuf[i][j] != 0)
+ TEST_ERROR
+
+ /* Close VDS and reopen with view set to H5D_VDS_FIRST_MISSING, reopen file
+ * as well if config option specified */
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ if(H5Pset_virtual_view(dapl, H5D_VDS_FIRST_MISSING) < 0)
+ TEST_ERROR
+ if(config & TEST_IO_REOPEN_VIRT) {
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if((vfile = H5Fopen(vfilename, H5F_ACC_RDONLY, fapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+ if((vdset = H5Dopen2(vfile, "v_dset", dapl)) < 0)
+ TEST_ERROR
+
+ /* Update erbuf to reflect new data that is no longer visible due to the
+ * change to H5D_VDS_FIRST_MISSING */
+ for(i = 0; i < 10; i++)
+ for(j = 15; j < 20; j += 2)
+ erbuf[i][j] = fill;
+
+ /* Get VDS space */
+ if((filespace = H5Dget_space(vdset)) < 0)
+ TEST_ERROR
+
+ /* Get VDS space dimensions */
+ if((ndims = H5Sget_simple_extent_ndims(filespace)) < 0)
+ TEST_ERROR
+ if(ndims != 2)
+ TEST_ERROR
+ if(H5Sget_simple_extent_dims(filespace, dims, mdims) < 0)
+ TEST_ERROR
+ if(dims[0] != 10)
+ TEST_ERROR
+ if(dims[1] != 14)
+ TEST_ERROR
+ if(mdims[0] != 10)
+ TEST_ERROR
+ if(mdims[1] != 20)
+ TEST_ERROR
+
+ /* Close filespace */
+ if(H5Sclose(filespace) < 0)
+ TEST_ERROR
+
+ /* Read data through virtual dataset */
+ /* Reset rbuf */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+
+ /* Select hyperslab in memory space */
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, dims, NULL) < 0)
+ TEST_ERROR
+
+ /* Read data */
+ if(H5Dread(vdset, H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++) {
+ if(j >= (int)dims[1]) {
+ if(rbuf[i][j] != 0)
+ TEST_ERROR
+ } /* end if */
+ else
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+ } /* end for */
+
+ /* Close */
+ if(!(config & TEST_IO_CLOSE_SRC)) {
+ if(H5Dclose(srcdset[0]) < 0)
+ TEST_ERROR
+ srcdset[0] = -1;
+ if(H5Dclose(srcdset[1]) < 0)
+ TEST_ERROR
+ srcdset[1] = -1;
+ if(H5Fclose(srcfile[0]) < 0)
+ TEST_ERROR
+ srcfile[0] = -1;
+ } /* end if */
+ else if(!(config & TEST_IO_DIFFERENT_FILE)) {
+ if(H5Fclose(srcfile[0]) < 0)
+ TEST_ERROR
+ srcfile[0] = -1;
+ } /* end if */
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ vdset = -1;
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if(H5Sclose(srcspace[0]) < 0)
+ TEST_ERROR
+ srcspace[0] = -1;
+ if(H5Sclose(vspace[0]) < 0)
+ TEST_ERROR
+ vspace[0] = -1;
+ if(H5Sclose(vspace[1]) < 0)
+ TEST_ERROR
+ vspace[1] = -1;
+
+
+ /*
+ * Test 3: 3 Source datasets, interleaved slices, two elements wide
+ */
+ /* Clear virtual layout in DCPL */
+ if(H5Pset_layout(dcpl, H5D_VIRTUAL) < 0)
+ TEST_ERROR
+
+ /* Create virtual dataspaces */
+ dims[0] = 10;
+ dims[1] = 10;
+ if((vspace[0] = H5Screate_simple(2, dims, mdims)) < 0)
+ TEST_ERROR
+ if((vspace[1] = H5Screate_simple(2, dims, mdims)) < 0)
+ TEST_ERROR
+ if((vspace[2] = H5Screate_simple(2, dims, mdims)) < 0)
+ TEST_ERROR
+
+ /* Create source dataspaces */
+ dims[1] = 4;
+ mdims[1] = 8;
+ if((srcspace[0] = H5Screate_simple(2, dims, mdims)) < 0)
+ TEST_ERROR
+ dims[1] = 4;
+ mdims[1] = 6;
+ if((srcspace[1] = H5Screate_simple(2, dims, mdims)) < 0)
+ TEST_ERROR
+ dims[1] = 2;
+ mdims[1] = 6;
+ if((srcspace[2] = H5Screate_simple(2, dims, mdims)) < 0)
+ TEST_ERROR
+ mdims[1] = 20;
+
+ /* Select hyperslab in source spaces */
+ start[0] = 0;
+ start[1] = 0;
+ count[0] = 10;
+ count[1] = H5S_UNLIMITED;
+ if(H5Sselect_hyperslab(srcspace[0], H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+ if(H5Sselect_hyperslab(srcspace[1], H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+ if(H5Sselect_hyperslab(srcspace[2], H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+
+ /* Select hyperslabs in virtual spaces */
+ stride[0] = 1;
+ stride[1] = 6;
+ count[0] = 1;
+ count[1] = H5S_UNLIMITED;
+ block[0] = 10;
+ block[1] = 2;
+ if(H5Sselect_hyperslab(vspace[0], H5S_SELECT_SET, start, stride, count, block) < 0)
+ TEST_ERROR
+ start[1] = 2;
+ if(H5Sselect_hyperslab(vspace[1], H5S_SELECT_SET, start, stride, count, block) < 0)
+ TEST_ERROR
+ start[1] = 4;
+ if(H5Sselect_hyperslab(vspace[2], H5S_SELECT_SET, start, stride, count, block) < 0)
+ TEST_ERROR
+ start[1] = 0;
+
+ /* Add virtual layout mappings */
+ if(H5Pset_virtual(dcpl, vspace[0], config & TEST_IO_DIFFERENT_FILE ? srcfilename_map : ".", "src_dset1", srcspace[0]) < 0)
+ TEST_ERROR
+ if(H5Pset_virtual(dcpl, vspace[1], config & TEST_IO_DIFFERENT_FILE ? srcfilename_map : ".", "src_dset2", srcspace[1]) < 0)
+ TEST_ERROR
+ if(H5Pset_virtual(dcpl, vspace[2], config & TEST_IO_DIFFERENT_FILE ? srcfilename_map : ".", "src_dset3", srcspace[2]) < 0)
+ TEST_ERROR
+
+ /* Create virtual file */
+ if((vfile = H5Fcreate(vfilename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ TEST_ERROR
+
+ /* Create source file if requested */
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ if((srcfile[0] = H5Fcreate(srcfilename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+ else {
+ srcfile[0] = vfile;
+ if(H5Iinc_ref(srcfile[0]) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Create source datasets */
+ if((srcdset[0] = H5Dcreate2(srcfile[0], "src_dset1", H5T_NATIVE_INT, srcspace[0], H5P_DEFAULT, srcdcpl, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if((srcdset[1] = H5Dcreate2(srcfile[0], "src_dset2", H5T_NATIVE_INT, srcspace[1], H5P_DEFAULT, srcdcpl, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if((srcdset[2] = H5Dcreate2(srcfile[0], "src_dset3", H5T_NATIVE_INT, srcspace[2], H5P_DEFAULT, srcdcpl, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Create virtual dataset */
+ if((vdset = H5Dcreate2(vfile, "v_dset", H5T_NATIVE_INT, vspace[0], H5P_DEFAULT, dcpl, dapl)) < 0)
+ TEST_ERROR
+
+ /* Populate write buffer */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++)
+ buf[i][j] = (i * (int)mdims[1]) + j;
+
+ /* Initialize erbuf */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++)
+ erbuf[i][j] = fill;
+
+ /* Write data directly to source datasets */
+ /* Select hyperslab in memory */
+ count[0] = 10;
+ count[1] = 4;
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+
+ /* Write first dataset */
+ if(H5Dwrite(srcdset[0], H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+
+ /* Update erbuf */
+ for(i = 0; i < 10; i++)
+ for(j = 0; j < 2; j++) {
+ erbuf[i][6 * j] = buf[i][2 * j];
+ erbuf[i][(6 * j) + 1] = buf[i][(2 * j) + 1];
+ } /* end for */
+
+ /* Adjust write buffer */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++)
+ buf[i][j] += (int)mdims[0] * (int)mdims[1];
+
+ /* Write second dataset */
+ if(H5Dwrite(srcdset[1], H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+
+ /* Update erbuf */
+ for(i = 0; i < 10; i++)
+ for(j = 0; j < 2; j++) {
+ erbuf[i][(6 * j) + 2] = buf[i][2 * j];
+ erbuf[i][(6 * j) + 3] = buf[i][(2 * j) + 1];
+ } /* end for */
+
+ /* Adjust write buffer */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++)
+ buf[i][j] += (int)mdims[0] * (int)mdims[1];
+
+ /* Select hyperslab in memory */
+ count[0] = 10;
+ count[1] = 2;
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+
+ /* Write third dataset */
+ if(H5Dwrite(srcdset[2], H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+
+ /* Update erbuf */
+ for(i = 0; i < 10; i++) {
+ erbuf[i][4] = buf[i][0];
+ erbuf[i][5] = buf[i][1];
+ } /* end for */
+
+ /* Close srcdsets and srcfile if config option specified */
+ if(config & TEST_IO_CLOSE_SRC) {
+ if(H5Dclose(srcdset[0]) < 0)
+ TEST_ERROR
+ srcdset[0] = -1;
+ if(H5Dclose(srcdset[1]) < 0)
+ TEST_ERROR
+ srcdset[1] = -1;
+ if(H5Dclose(srcdset[2]) < 0)
+ TEST_ERROR
+ srcdset[2] = -1;
+
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ if(H5Fclose(srcfile[0]) < 0)
+ TEST_ERROR
+ srcfile[0] = -1;
+ } /* end if */
+ } /* end if */
+
+ /* Reopen virtual dataset and file if config option specified. Also do this
+ * if we're using a separate source file to switch to read only. */
+ if((config & TEST_IO_REOPEN_VIRT) || (config & TEST_IO_DIFFERENT_FILE)) {
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ vdset = -1;
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if((vfile = H5Fopen(vfilename, H5F_ACC_RDONLY, fapl)) < 0)
+ TEST_ERROR
+ if((vdset = H5Dopen2(vfile, "v_dset", dapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Get VDS space */
+ if((filespace = H5Dget_space(vdset)) < 0)
+ TEST_ERROR
+
+ /* Get VDS space dimensions */
+ if((ndims = H5Sget_simple_extent_ndims(filespace)) < 0)
+ TEST_ERROR
+ if(ndims != 2)
+ TEST_ERROR
+ if(H5Sget_simple_extent_dims(filespace, dims, mdims) < 0)
+ TEST_ERROR
+ if(dims[0] != 10)
+ TEST_ERROR
+ if(dims[1] != 10)
+ TEST_ERROR
+ if(mdims[0] != 10)
+ TEST_ERROR
+ if(mdims[1] != 20)
+ TEST_ERROR
+
+ /* Close filespace */
+ if(H5Sclose(filespace) < 0)
+ TEST_ERROR
+
+ /* Read data through virtual dataset */
+ /* Reset rbuf */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+
+ /* Select hyperslab in memory space */
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, dims, NULL) < 0)
+ TEST_ERROR
+
+ /* Read data */
+ if(H5Dread(vdset, H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++) {
+ if(j >= (int)dims[1]) {
+ if(rbuf[i][j] != 0)
+ TEST_ERROR
+ } /* end if */
+ else
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+ } /* end for */
+
+ /* Close VDS and reopen with view set to H5D_VDS_FIRST_MISSING, reopen file
+ * as well if config option specified */
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ if(H5Pset_virtual_view(dapl, H5D_VDS_FIRST_MISSING) < 0)
+ TEST_ERROR
+ if(config & TEST_IO_REOPEN_VIRT) {
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if((vfile = H5Fopen(vfilename, H5F_ACC_RDONLY, fapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+ if((vdset = H5Dopen2(vfile, "v_dset", dapl)) < 0)
+ TEST_ERROR
+
+ /* Get VDS space */
+ if((filespace = H5Dget_space(vdset)) < 0)
+ TEST_ERROR
+
+ /* Get VDS space dimensions */
+ if((ndims = H5Sget_simple_extent_ndims(filespace)) < 0)
+ TEST_ERROR
+ if(ndims != 2)
+ TEST_ERROR
+ if(H5Sget_simple_extent_dims(filespace, dims, mdims) < 0)
+ TEST_ERROR
+ if(dims[0] != 10)
+ TEST_ERROR
+ if(dims[1] != 10)
+ TEST_ERROR
+ if(mdims[0] != 10)
+ TEST_ERROR
+ if(mdims[1] != 20)
+ TEST_ERROR
+
+ /* Close filespace */
+ if(H5Sclose(filespace) < 0)
+ TEST_ERROR
+
+ /* Read data through virtual dataset */
+ /* Reset rbuf */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+
+ /* Read data */
+ if(H5Dread(vdset, H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++) {
+ if(j >= (int)dims[1]) {
+ if(rbuf[i][j] != 0)
+ TEST_ERROR
+ } /* end if */
+ else
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+ } /* end for */
+
+ /* Reopen srcdset[0] and srcfile if config option specified */
+ if(config & TEST_IO_CLOSE_SRC) {
+ if(config & TEST_IO_DIFFERENT_FILE)
+ if((srcfile[0] = H5Fopen(srcfilename, H5F_ACC_RDWR, fapl)) < 0)
+ TEST_ERROR
+ if((srcdset[0] = H5Dopen2(srcfile[0], "src_dset1", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Extend srcdset[0] */
+ dims[1] = 7;
+ if(H5Dset_extent(srcdset[0], dims) < 0)
+ TEST_ERROR
+
+ /* Adjust write buffer */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++)
+ buf[i][j] += (int)mdims[0] * (int)mdims[1];
+
+ /* Write to new area of srcdset */
+ count[1] = 3;
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+ if((filespace = H5Dget_space(srcdset[0])) < 0)
+ TEST_ERROR
+ start[1] = 4;
+ if(H5Sselect_hyperslab(filespace, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+ start[1] = 0;
+ if(H5Dwrite(srcdset[0], H5T_NATIVE_INT, memspace, filespace, dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+ if(H5Sclose(filespace) < 0)
+ TEST_ERROR
+
+ /* Close srcdset[0] and srcfile if config option specified */
+ if(config & TEST_IO_CLOSE_SRC) {
+ if(H5Dclose(srcdset[0]) < 0)
+ TEST_ERROR
+ srcdset[0] = -1;
+
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ if(H5Fclose(srcfile[0]) < 0)
+ TEST_ERROR
+ srcfile[0] = -1;
+ } /* end if */
+ } /* end if */
+
+ /* Reopen virtual dataset and file if config option specified. Always
+ * reopen if using a different file so the VDS gets an updated view of the
+ * source datasets. */
+ if((config & TEST_IO_REOPEN_VIRT) || (config & TEST_IO_DIFFERENT_FILE)) {
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ vdset = -1;
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if((vfile = H5Fopen(vfilename, H5F_ACC_RDONLY, fapl)) < 0)
+ TEST_ERROR
+ if((vdset = H5Dopen2(vfile, "v_dset", dapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Get VDS space */
+ if((filespace = H5Dget_space(vdset)) < 0)
+ TEST_ERROR
+
+ /* Get VDS space dimensions. Note that since we are using
+ * H5D_VDS_FIRST_MISSING the size will not have changed. */
+ if((ndims = H5Sget_simple_extent_ndims(filespace)) < 0)
+ TEST_ERROR
+ if(ndims != 2)
+ TEST_ERROR
+ if(H5Sget_simple_extent_dims(filespace, dims, mdims) < 0)
+ TEST_ERROR
+ if(dims[0] != 10)
+ TEST_ERROR
+ if(dims[1] != 10)
+ TEST_ERROR
+ if(mdims[0] != 10)
+ TEST_ERROR
+ if(mdims[1] != 20)
+ TEST_ERROR
+
+ /* Close filespace */
+ if(H5Sclose(filespace) < 0)
+ TEST_ERROR
+
+ /* Read data through virtual dataset */
+ /* Reset rbuf */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+
+ /* Select hyperslab in memory space */
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, dims, NULL) < 0)
+ TEST_ERROR
+
+ /* Read data */
+ if(H5Dread(vdset, H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++) {
+ if(j >= (int)dims[1]) {
+ if(rbuf[i][j] != 0)
+ TEST_ERROR
+ } /* end if */
+ else
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+ } /* end for */
+
+ /* Close VDS and reopen with view set to H5D_VDS_LAST_AVAILABLE, reopen file
+ * as well if config option specified */
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ if(H5Pset_virtual_view(dapl, H5D_VDS_LAST_AVAILABLE) < 0)
+ TEST_ERROR
+ if(config & TEST_IO_REOPEN_VIRT) {
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if((vfile = H5Fopen(vfilename, H5F_ACC_RDONLY, fapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+ if((vdset = H5Dopen2(vfile, "v_dset", dapl)) < 0)
+ TEST_ERROR
+
+ /* Update erbuf to reflect new data that is now visible due to the change to
+ * H5D_VDS_LAST_AVAILABLE */
+ for(i = 0; i < 10; i++) {
+ erbuf[i][12] = buf[i][0];
+ erbuf[i][13] = buf[i][1];
+ erbuf[i][18] = buf[i][2];
+ } /* end for */
+
+ /* Get VDS space */
+ if((filespace = H5Dget_space(vdset)) < 0)
+ TEST_ERROR
+
+ /* Get VDS space dimensions */
+ if((ndims = H5Sget_simple_extent_ndims(filespace)) < 0)
+ TEST_ERROR
+ if(ndims != 2)
+ TEST_ERROR
+ if(H5Sget_simple_extent_dims(filespace, dims, mdims) < 0)
+ TEST_ERROR
+ if(dims[0] != 10)
+ TEST_ERROR
+ if(dims[1] != 19)
+ TEST_ERROR
+ if(mdims[0] != 10)
+ TEST_ERROR
+ if(mdims[1] != 20)
+ TEST_ERROR
+
+ /* Close filespace */
+ if(H5Sclose(filespace) < 0)
+ TEST_ERROR
+
+ /* Read data through virtual dataset */
+ /* Reset rbuf */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+
+ /* Select hyperslab in memory space */
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, dims, NULL) < 0)
+ TEST_ERROR
+
+ /* Read data */
+ if(H5Dread(vdset, H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++) {
+ if(j >= (int)dims[1]) {
+ if(rbuf[i][j] != 0)
+ TEST_ERROR
+ } /* end if */
+ else
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+ } /* end for */
+
+ /* Reopen srcdset[2] and srcfile if config option specified */
+ if(config & TEST_IO_CLOSE_SRC) {
+ if(config & TEST_IO_DIFFERENT_FILE)
+ if((srcfile[0] = H5Fopen(srcfilename, H5F_ACC_RDWR, fapl)) < 0)
+ TEST_ERROR
+ if((srcdset[2] = H5Dopen2(srcfile[0], "src_dset3", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Extend srcdset[2] */
+ dims[1] = 5;
+ if(H5Dset_extent(srcdset[2], dims) < 0)
+ TEST_ERROR
+
+ /* Adjust write buffer */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++)
+ buf[i][j] += (int)mdims[0] * (int)mdims[1];
+
+ /* Write to new area of srcdset */
+ count[1] = 3;
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+ if((filespace = H5Dget_space(srcdset[2])) < 0)
+ TEST_ERROR
+ start[1] = 2;
+ if(H5Sselect_hyperslab(filespace, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+ start[1] = 0;
+ if(H5Dwrite(srcdset[2], H5T_NATIVE_INT, memspace, filespace, dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+ if(H5Sclose(filespace) < 0)
+ TEST_ERROR
+
+ /* Update erbuf */
+ for(i = 0; i < 10; i++) {
+ erbuf[i][10] = buf[i][0];
+ erbuf[i][11] = buf[i][1];
+ erbuf[i][16] = buf[i][2];
+ } /* end for */
+
+ /* Close srcdset[2] and srcfile if config option specified */
+ if(config & TEST_IO_CLOSE_SRC) {
+ if(H5Dclose(srcdset[2]) < 0)
+ TEST_ERROR
+ srcdset[2] = -1;
+
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ if(H5Fclose(srcfile[0]) < 0)
+ TEST_ERROR
+ srcfile[0] = -1;
+ } /* end if */
+ } /* end if */
+
+ /* Reopen virtual dataset and file if config option specified. Always
+ * reopen if using a different file so the VDS gets an updated view of the
+ * source datasets. */
+ if((config & TEST_IO_REOPEN_VIRT) || (config & TEST_IO_DIFFERENT_FILE)) {
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ vdset = -1;
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if((vfile = H5Fopen(vfilename, H5F_ACC_RDONLY, fapl)) < 0)
+ TEST_ERROR
+ if((vdset = H5Dopen2(vfile, "v_dset", dapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Get VDS space */
+ if((filespace = H5Dget_space(vdset)) < 0)
+ TEST_ERROR
+
+ /* Get VDS space dimensions. Note that the dimensions will not have
+ * changed. */
+ if((ndims = H5Sget_simple_extent_ndims(filespace)) < 0)
+ TEST_ERROR
+ if(ndims != 2)
+ TEST_ERROR
+ if(H5Sget_simple_extent_dims(filespace, dims, mdims) < 0)
+ TEST_ERROR
+ if(dims[0] != 10)
+ TEST_ERROR
+ if(dims[1] != 19)
+ TEST_ERROR
+ if(mdims[0] != 10)
+ TEST_ERROR
+ if(mdims[1] != 20)
+ TEST_ERROR
+
+ /* Close filespace */
+ if(H5Sclose(filespace) < 0)
+ TEST_ERROR
+
+ /* Read data through virtual dataset */
+ /* Reset rbuf */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+
+ /* Select hyperslab in memory space */
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, dims, NULL) < 0)
+ TEST_ERROR
+
+ /* Read data */
+ if(H5Dread(vdset, H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++) {
+ if(j >= (int)dims[1]) {
+ if(rbuf[i][j] != 0)
+ TEST_ERROR
+ } /* end if */
+ else
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+ } /* end for */
+
+ /* Close VDS and reopen with view set to H5D_VDS_FIRST_MISSING, reopen file
+ * as well if config option specified */
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ if(H5Pset_virtual_view(dapl, H5D_VDS_FIRST_MISSING) < 0)
+ TEST_ERROR
+ if(config & TEST_IO_REOPEN_VIRT) {
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if((vfile = H5Fopen(vfilename, H5F_ACC_RDONLY, fapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+ if((vdset = H5Dopen2(vfile, "v_dset", dapl)) < 0)
+ TEST_ERROR
+
+ /* Get VDS space */
+ if((filespace = H5Dget_space(vdset)) < 0)
+ TEST_ERROR
+
+ /* Get VDS space dimensions */
+ if((ndims = H5Sget_simple_extent_ndims(filespace)) < 0)
+ TEST_ERROR
+ if(ndims != 2)
+ TEST_ERROR
+ if(H5Sget_simple_extent_dims(filespace, dims, mdims) < 0)
+ TEST_ERROR
+ if(dims[0] != 10)
+ TEST_ERROR
+ if(dims[1] != 14)
+ TEST_ERROR
+ if(mdims[0] != 10)
+ TEST_ERROR
+ if(mdims[1] != 20)
+ TEST_ERROR
+
+ /* Close filespace */
+ if(H5Sclose(filespace) < 0)
+ TEST_ERROR
+
+ /* Read data through virtual dataset */
+ /* Reset rbuf */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+
+ /* Select hyperslab in memory space */
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, dims, NULL) < 0)
+ TEST_ERROR
+
+ /* Read data */
+ if(H5Dread(vdset, H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++) {
+ if(j >= (int)dims[1]) {
+ if(rbuf[i][j] != 0)
+ TEST_ERROR
+ } /* end if */
+ else
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+ } /* end for */
+
+ /* Reopen srcdset[1] and srcfile if config option specified */
+ if(config & TEST_IO_CLOSE_SRC) {
+ if(config & TEST_IO_DIFFERENT_FILE)
+ if((srcfile[0] = H5Fopen(srcfilename, H5F_ACC_RDWR, fapl)) < 0)
+ TEST_ERROR
+ if((srcdset[1] = H5Dopen2(srcfile[0], "src_dset2", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Extend srcdset[1] */
+ dims[1] = 6;
+ if(H5Dset_extent(srcdset[1], dims) < 0)
+ TEST_ERROR
+
+ /* Adjust write buffer */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++)
+ buf[i][j] += (int)mdims[0] * (int)mdims[1];
+
+ /* Write to new area of srcdset */
+ count[1] = 2;
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+ if((filespace = H5Dget_space(srcdset[1])) < 0)
+ TEST_ERROR
+ start[1] = 4;
+ if(H5Sselect_hyperslab(filespace, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+ start[1] = 0;
+ if(H5Dwrite(srcdset[1], H5T_NATIVE_INT, memspace, filespace, dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+ if(H5Sclose(filespace) < 0)
+ TEST_ERROR
+
+ /* Update erbuf */
+ for(i = 0; i < 10; i++) {
+ erbuf[i][14] = buf[i][0];
+ erbuf[i][15] = buf[i][1];
+ } /* end for */
+
+ /* Close srcdset[1] and srcfile if config option specified */
+ if(config & TEST_IO_CLOSE_SRC) {
+ if(H5Dclose(srcdset[1]) < 0)
+ TEST_ERROR
+ srcdset[1] = -1;
+
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ if(H5Fclose(srcfile[0]) < 0)
+ TEST_ERROR
+ srcfile[0] = -1;
+ } /* end if */
+ } /* end if */
+
+ /* Reopen virtual dataset and file if config option specified. Always
+ * reopen if using a different file so the VDS gets an updated view of the
+ * source datasets. */
+ if((config & TEST_IO_REOPEN_VIRT) || (config & TEST_IO_DIFFERENT_FILE)) {
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ vdset = -1;
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if((vfile = H5Fopen(vfilename, H5F_ACC_RDONLY, fapl)) < 0)
+ TEST_ERROR
+ if((vdset = H5Dopen2(vfile, "v_dset", dapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Get VDS space */
+ if((filespace = H5Dget_space(vdset)) < 0)
+ TEST_ERROR
+
+ /* Get VDS space dimensions */
+ if((ndims = H5Sget_simple_extent_ndims(filespace)) < 0)
+ TEST_ERROR
+ if(ndims != 2)
+ TEST_ERROR
+ if(H5Sget_simple_extent_dims(filespace, dims, mdims) < 0)
+ TEST_ERROR
+ if(dims[0] != 10)
+ TEST_ERROR
+ if(dims[1] != 17)
+ TEST_ERROR
+ if(mdims[0] != 10)
+ TEST_ERROR
+ if(mdims[1] != 20)
+ TEST_ERROR
+
+ /* Close filespace */
+ if(H5Sclose(filespace) < 0)
+ TEST_ERROR
+
+ /* Read data through virtual dataset */
+ /* Reset rbuf */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+
+ /* Select hyperslab in memory space */
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, dims, NULL) < 0)
+ TEST_ERROR
+
+ /* Read data */
+ if(H5Dread(vdset, H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++) {
+ if(j >= (int)dims[1]) {
+ if(rbuf[i][j] != 0)
+ TEST_ERROR
+ } /* end if */
+ else
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+ } /* end for */
+
+ /* Close VDS and reopen with view set to H5D_VDS_LAST_AVAILABLE, reopen file
+ * as well if config option specified */
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ if(H5Pset_virtual_view(dapl, H5D_VDS_LAST_AVAILABLE) < 0)
+ TEST_ERROR
+ if(config & TEST_IO_REOPEN_VIRT) {
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if((vfile = H5Fopen(vfilename, H5F_ACC_RDONLY, fapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+ if((vdset = H5Dopen2(vfile, "v_dset", dapl)) < 0)
+ TEST_ERROR
+
+ /* Get VDS space */
+ if((filespace = H5Dget_space(vdset)) < 0)
+ TEST_ERROR
+
+ /* Get VDS space dimensions */
+ if((ndims = H5Sget_simple_extent_ndims(filespace)) < 0)
+ TEST_ERROR
+ if(ndims != 2)
+ TEST_ERROR
+ if(H5Sget_simple_extent_dims(filespace, dims, mdims) < 0)
+ TEST_ERROR
+ if(dims[0] != 10)
+ TEST_ERROR
+ if(dims[1] != 19)
+ TEST_ERROR
+ if(mdims[0] != 10)
+ TEST_ERROR
+ if(mdims[1] != 20)
+ TEST_ERROR
+
+ /* Read data through virtual dataset */
+ /* Reset rbuf */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+
+ /* Select hyperslab in memory space */
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, dims, NULL) < 0)
+ TEST_ERROR
+
+ /* Read data */
+ if(H5Dread(vdset, H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++) {
+ if(j >= (int)dims[1]) {
+ if(rbuf[i][j] != 0)
+ TEST_ERROR
+ } /* end if */
+ else
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+ } /* end for */
+
+ /* Now just read middle 2 rows */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+ start[0] = 4;
+ count[0] = 2;
+ count[1] = 19;
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+ if(H5Sselect_hyperslab(filespace, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+ start[0] = 0;
+ if(H5Dread(vdset, H5T_NATIVE_INT, memspace, filespace, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Close filespace */
+ if(H5Sclose(filespace) < 0)
+ TEST_ERROR
+
+ /* Verify read data - algorithmically check for only 2 middle rows being
+ * read */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++)
+ if(j >= (int)dims[1]) {
+ if(rbuf[i][j] != 0)
+ TEST_ERROR
+ } /* end if */
+ else if((i == 4) || (i == 5)) {
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+ } /* end if */
+ else
+ if(rbuf[i][j] != 0)
+ TEST_ERROR
+
+ /* Close */
+ if(!(config & TEST_IO_CLOSE_SRC)) {
+ if(H5Dclose(srcdset[0]) < 0)
+ TEST_ERROR
+ srcdset[0] = -1;
+ if(H5Dclose(srcdset[1]) < 0)
+ TEST_ERROR
+ srcdset[1] = -1;
+ if(H5Dclose(srcdset[2]) < 0)
+ TEST_ERROR
+ srcdset[2] = -1;
+ if(H5Fclose(srcfile[0]) < 0)
+ TEST_ERROR
+ srcfile[0] = -1;
+ } /* end if */
+ else if(!(config & TEST_IO_DIFFERENT_FILE)) {
+ if(H5Fclose(srcfile[0]) < 0)
+ TEST_ERROR
+ srcfile[0] = -1;
+ } /* end if */
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ vdset = -1;
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if(H5Sclose(srcspace[0]) < 0)
+ TEST_ERROR
+ srcspace[0] = -1;
+ if(H5Sclose(srcspace[1]) < 0)
+ TEST_ERROR
+ srcspace[1] = -1;
+ if(H5Sclose(srcspace[2]) < 0)
+ TEST_ERROR
+ srcspace[2] = -1;
+ if(H5Sclose(vspace[0]) < 0)
+ TEST_ERROR
+ vspace[0] = -1;
+ if(H5Sclose(vspace[1]) < 0)
+ TEST_ERROR
+ vspace[1] = -1;
+
+
+ /*
+ * Test 4: 2 Source datasets, offset starts
+ */
+ /* Clear virtual layout in DCPL */
+ if(H5Pset_layout(dcpl, H5D_VIRTUAL) < 0)
+ TEST_ERROR
+
+ /* Create virtual dataspaces */
+ if((vspace[0] = H5Screate_simple(2, dims, mdims)) < 0)
+ TEST_ERROR
+ if((vspace[1] = H5Screate_simple(2, dims, mdims)) < 0)
+ TEST_ERROR
+
+ /* Create source dataspaces */
+ dims[0] = 5;
+ dims[1] = 0;
+ mdims[0] = 5;
+ if((srcspace[0] = H5Screate_simple(2, dims, mdims)) < 0)
+ TEST_ERROR
+ dims[1] = 5;
+ if((srcspace[1] = H5Screate_simple(2, dims, mdims)) < 0)
+ TEST_ERROR
+ mdims[0] = 10;
+
+ /* Select hyperslab in source spaces */
+ start[0] = 0;
+ start[1] = 0;
+ count[0] = 5;
+ count[1] = H5S_UNLIMITED;
+ if(H5Sselect_hyperslab(srcspace[0], H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+ if(H5Sselect_hyperslab(srcspace[1], H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+
+ /* Select hyperslabs in virtual spaces */
+ start[1] = 10;
+ if(H5Sselect_hyperslab(vspace[0], H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+ start[0] = 5;
+ start[1] = 0;
+ if(H5Sselect_hyperslab(vspace[1], H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+
+ /* Add virtual layout mappings */
+ if(H5Pset_virtual(dcpl, vspace[0], config & TEST_IO_DIFFERENT_FILE ? srcfilename_map : ".", "src_dset1", srcspace[0]) < 0)
+ TEST_ERROR
+ if(H5Pset_virtual(dcpl, vspace[1], config & TEST_IO_DIFFERENT_FILE ? srcfilename_map : ".", "src_dset2", srcspace[1]) < 0)
+ TEST_ERROR
+
+ /* Create virtual file */
+ if((vfile = H5Fcreate(vfilename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ TEST_ERROR
+
+ /* Create source file if requested */
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ if((srcfile[0] = H5Fcreate(srcfilename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+ else {
+ srcfile[0] = vfile;
+ if(H5Iinc_ref(srcfile[0]) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Create source datasets */
+ if((srcdset[0] = H5Dcreate2(srcfile[0], "src_dset1", H5T_NATIVE_INT, srcspace[0], H5P_DEFAULT, srcdcpl, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if((srcdset[1] = H5Dcreate2(srcfile[0], "src_dset2", H5T_NATIVE_INT, srcspace[1], H5P_DEFAULT, srcdcpl, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Create virtual dataset */
+ if((vdset = H5Dcreate2(vfile, "v_dset", H5T_NATIVE_INT, vspace[0], H5P_DEFAULT, dcpl, dapl)) < 0)
+ TEST_ERROR
+
+ /* Populate write buffer */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++)
+ buf[i][j] = (i * (int)mdims[1]) + j;
+
+ /* Initialize erbuf */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++)
+ erbuf[i][j] = fill;
+
+ /* Write data directly to second source dataset */
+ /* Select hyperslab in memory */
+ start[0] = 0;
+ start[1] = 0;
+ count[0] = 5;
+ count[1] = 5;
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+
+ /* Write second dataset */
+ if(H5Dwrite(srcdset[1], H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+
+ /* Update erbuf */
+ for(i = 0; i < 5; i++)
+ for(j = 0; j < 5; j++)
+ erbuf[i + 5][j] = buf[i][j];
+
+ /* Close srcdsets and srcfile if config option specified */
+ if(config & TEST_IO_CLOSE_SRC) {
+ if(H5Dclose(srcdset[0]) < 0)
+ TEST_ERROR
+ srcdset[0] = -1;
+ if(H5Dclose(srcdset[1]) < 0)
+ TEST_ERROR
+ srcdset[1] = -1;
+
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ if(H5Fclose(srcfile[0]) < 0)
+ TEST_ERROR
+ srcfile[0] = -1;
+ } /* end if */
+ } /* end if */
+
+ /* Reopen virtual dataset and file if config option specified. Also do this
+ * if we're using a separate source file to switch to read only. */
+ if((config & TEST_IO_REOPEN_VIRT) || (config & TEST_IO_DIFFERENT_FILE)) {
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ vdset = -1;
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if((vfile = H5Fopen(vfilename, H5F_ACC_RDONLY, fapl)) < 0)
+ TEST_ERROR
+ if((vdset = H5Dopen2(vfile, "v_dset", dapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Get VDS space */
+ if((filespace = H5Dget_space(vdset)) < 0)
+ TEST_ERROR
+
+ /* Get VDS space dimensions */
+ if((ndims = H5Sget_simple_extent_ndims(filespace)) < 0)
+ TEST_ERROR
+ if(ndims != 2)
+ TEST_ERROR
+ if(H5Sget_simple_extent_dims(filespace, dims, mdims) < 0)
+ TEST_ERROR
+ if(dims[0] != 10)
+ TEST_ERROR
+ if(dims[1] != 5)
+ TEST_ERROR
+ if(mdims[0] != 10)
+ TEST_ERROR
+ if(mdims[1] != 20)
+ TEST_ERROR
+
+ /* Close filespace */
+ if(H5Sclose(filespace) < 0)
+ TEST_ERROR
+
+ /* Read data through virtual dataset */
+ /* Reset rbuf */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+
+ /* Select hyperslab in memory space */
+ start[0] = 0;
+ start[1] = 0;
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, dims, NULL) < 0)
+ TEST_ERROR
+
+ /* Read data */
+ if(H5Dread(vdset, H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++) {
+ if(j >= (int)dims[1]) {
+ if(rbuf[i][j] != 0)
+ TEST_ERROR
+ } /* end if */
+ else
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+ } /* end for */
+
+ /* Close VDS and reopen with view set to H5D_VDS_FIRST_MISSING, reopen file
+ * as well if config option specified */
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ if(H5Pset_virtual_view(dapl, H5D_VDS_FIRST_MISSING) < 0)
+ TEST_ERROR
+ if(config & TEST_IO_REOPEN_VIRT) {
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if((vfile = H5Fopen(vfilename, H5F_ACC_RDONLY, fapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+ if((vdset = H5Dopen2(vfile, "v_dset", dapl)) < 0)
+ TEST_ERROR
+
+ /* Get VDS space */
+ if((filespace = H5Dget_space(vdset)) < 0)
+ TEST_ERROR
+
+ /* Get VDS space dimensions */
+ if((ndims = H5Sget_simple_extent_ndims(filespace)) < 0)
+ TEST_ERROR
+ if(ndims != 2)
+ TEST_ERROR
+ if(H5Sget_simple_extent_dims(filespace, dims, mdims) < 0)
+ TEST_ERROR
+ if(dims[0] != 10)
+ TEST_ERROR
+ if(dims[1] != 5)
+ TEST_ERROR
+ if(mdims[0] != 10)
+ TEST_ERROR
+ if(mdims[1] != 20)
+ TEST_ERROR
+
+ /* Close filespace */
+ if(H5Sclose(filespace) < 0)
+ TEST_ERROR
+
+ /* Read data through virtual dataset */
+ /* Reset rbuf */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+
+ /* Read data */
+ if(H5Dread(vdset, H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++) {
+ if(j >= (int)dims[1]) {
+ if(rbuf[i][j] != 0)
+ TEST_ERROR
+ } /* end if */
+ else
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+ } /* end for */
+
+ /* Reopen srcdset[0] and srcfile if config option specified */
+ if(config & TEST_IO_CLOSE_SRC) {
+ if(config & TEST_IO_DIFFERENT_FILE)
+ if((srcfile[0] = H5Fopen(srcfilename, H5F_ACC_RDWR, fapl)) < 0)
+ TEST_ERROR
+ if((srcdset[0] = H5Dopen2(srcfile[0], "src_dset1", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Extend srcdset[0] */
+ dims[0] = 5;
+ dims[1] = 5;
+ if(H5Dset_extent(srcdset[0], dims) < 0)
+ TEST_ERROR
+
+ /* Adjust write buffer */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++)
+ buf[i][j] += (int)mdims[0] * (int)mdims[1];
+
+ /* Write to srcdset[0] */
+ start[0] = 0;
+ start[1] = 0;
+ count[0] = 5;
+ count[1] = 5;
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
+ TEST_ERROR
+ if(H5Dwrite(srcdset[0], H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, buf[0]) < 0)
+ TEST_ERROR
+
+ /* Update erbuf */
+ for(i = 0; i < 5; i++)
+ for(j = 0; j < 5; j++)
+ erbuf[i][j + 10] = buf[i][j];
+
+ /* Close srcdset[0] and srcfile if config option specified */
+ if(config & TEST_IO_CLOSE_SRC) {
+ if(H5Dclose(srcdset[0]) < 0)
+ TEST_ERROR
+ srcdset[0] = -1;
+
+ if(config & TEST_IO_DIFFERENT_FILE) {
+ if(H5Fclose(srcfile[0]) < 0)
+ TEST_ERROR
+ srcfile[0] = -1;
+ } /* end if */
+ } /* end if */
+
+ /* Reopen virtual dataset and file if config option specified. Always
+ * reopen if using a different file so the VDS gets an updated view of the
+ * source datasets. */
+ if((config & TEST_IO_REOPEN_VIRT) || (config & TEST_IO_DIFFERENT_FILE)) {
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ vdset = -1;
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if((vfile = H5Fopen(vfilename, H5F_ACC_RDONLY, fapl)) < 0)
+ TEST_ERROR
+ if((vdset = H5Dopen2(vfile, "v_dset", dapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+
+ /* Get VDS space */
+ if((filespace = H5Dget_space(vdset)) < 0)
+ TEST_ERROR
+
+ /* Get VDS space dimensions */
+ if((ndims = H5Sget_simple_extent_ndims(filespace)) < 0)
+ TEST_ERROR
+ if(ndims != 2)
+ TEST_ERROR
+ if(H5Sget_simple_extent_dims(filespace, dims, mdims) < 0)
+ TEST_ERROR
+ if(dims[0] != 10)
+ TEST_ERROR
+ if(dims[1] != 5)
+ TEST_ERROR
+ if(mdims[0] != 10)
+ TEST_ERROR
+ if(mdims[1] != 20)
+ TEST_ERROR
+
+ /* Close filespace */
+ if(H5Sclose(filespace) < 0)
+ TEST_ERROR
+
+ /* Read data through virtual dataset */
+ /* Reset rbuf */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+
+ /* Select hyperslab in memory space */
+ start[0] = 0;
+ start[1] = 0;
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, dims, NULL) < 0)
+ TEST_ERROR
+
+ /* Read data */
+ if(H5Dread(vdset, H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++) {
+ if(j >= (int)dims[1]) {
+ if(rbuf[i][j] != 0)
+ TEST_ERROR
+ } /* end if */
+ else
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+ } /* end for */
+
+ /* Close VDS and reopen with view set to H5D_VDS_LAST_AVAILABLE, reopen file
+ * as well if config option specified */
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ if(H5Pset_virtual_view(dapl, H5D_VDS_LAST_AVAILABLE) < 0)
+ TEST_ERROR
+ if(config & TEST_IO_REOPEN_VIRT) {
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if((vfile = H5Fopen(vfilename, H5F_ACC_RDONLY, fapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+ if((vdset = H5Dopen2(vfile, "v_dset", dapl)) < 0)
+ TEST_ERROR
+
+ /* Get VDS space */
+ if((filespace = H5Dget_space(vdset)) < 0)
+ TEST_ERROR
+
+ /* Get VDS space dimensions */
+ if((ndims = H5Sget_simple_extent_ndims(filespace)) < 0)
+ TEST_ERROR
+ if(ndims != 2)
+ TEST_ERROR
+ if(H5Sget_simple_extent_dims(filespace, dims, mdims) < 0)
+ TEST_ERROR
+ if(dims[0] != 10)
+ TEST_ERROR
+ if(dims[1] != 15)
+ TEST_ERROR
+ if(mdims[0] != 10)
+ TEST_ERROR
+ if(mdims[1] != 20)
+ TEST_ERROR
+
+ /* Close filespace */
+ if(H5Sclose(filespace) < 0)
+ TEST_ERROR
+
+ /* Read data through virtual dataset */
+ /* Reset rbuf */
+ HDmemset(rbuf[0], 0, sizeof(rbuf));
+
+ /* Select hyperslab in memory space */
+ start[0] = 0;
+ start[1] = 0;
+ if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, dims, NULL) < 0)
+ TEST_ERROR
+
+ /* Read data */
+ if(H5Dread(vdset, H5T_NATIVE_INT, memspace, H5S_ALL, dxpl_id, rbuf[0]) < 0)
+ TEST_ERROR
+
+ /* Verify read data */
+ for(i = 0; i < (int)mdims[0]; i++)
+ for(j = 0; j < (int)mdims[1]; j++) {
+ if(j >= (int)dims[1]) {
+ if(rbuf[i][j] != 0)
+ TEST_ERROR
+ } /* end if */
+ else
+ if(rbuf[i][j] != erbuf[i][j])
+ TEST_ERROR
+ } /* end for */
+
+ /* Close */
+ if(!(config & TEST_IO_CLOSE_SRC)) {
+ if(H5Dclose(srcdset[0]) < 0)
+ TEST_ERROR
+ srcdset[0] = -1;
+ if(H5Dclose(srcdset[1]) < 0)
+ TEST_ERROR
+ srcdset[1] = -1;
+ if(H5Fclose(srcfile[0]) < 0)
+ TEST_ERROR
+ srcfile[0] = -1;
+ } /* end if */
+ else if(!(config & TEST_IO_DIFFERENT_FILE)) {
+ if(H5Fclose(srcfile[0]) < 0)
+ TEST_ERROR
+ srcfile[0] = -1;
+ } /* end if */
+ if(H5Dclose(vdset) < 0)
+ TEST_ERROR
+ vdset = -1;
+ if(H5Fclose(vfile) < 0)
+ TEST_ERROR
+ vfile = -1;
+ if(H5Sclose(srcspace[0]) < 0)
+ TEST_ERROR
+ srcspace[0] = -1;
+ if(H5Sclose(srcspace[1]) < 0)
+ TEST_ERROR
+ srcspace[1] = -1;
+ if(H5Sclose(vspace[0]) < 0)
+ TEST_ERROR
+ vspace[0] = -1;
+ if(H5Sclose(vspace[1]) < 0)
+ TEST_ERROR
+ vspace[1] = -1;
+
+
+ /* Close */
+ if(H5Pclose(dcpl) < 0)
+ TEST_ERROR
+ dcpl = -1;
+ if(H5Pclose(srcdcpl) < 0)
+ TEST_ERROR
+ dcpl = -1;
+ if(H5Pclose(dapl) < 0)
+ TEST_ERROR
+ dapl = -1;
+ if(H5Sclose(memspace) < 0)
+ TEST_ERROR
+ memspace = -1;
+
+ if(H5Pclose(dxpl_id) < 0)
+ TEST_ERROR
+ dxpl_id = -1;
+
+ if (mpi_rank == 0)
+ PASSED();
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ for(i = 0; i < (int)(sizeof(srcdset) / sizeof(srcdset[0])); i++) {
+ if(srcdset[i] >= 0)
+ (void)H5Dclose(srcdset[i]);
+ } /* end for */
+ if(vdset >= 0)
+ (void)H5Dclose(vdset);
+ for(i = 0; i < (int)(sizeof(srcfile) / sizeof(srcfile[0])); i++) {
+ if(srcfile[i] >= 0)
+ (void)H5Fclose(srcfile[i]);
+ } /* end for */
+ if(vfile >= 0)
+ (void)H5Fclose(vfile);
+ for(i = 0; i < (int)(sizeof(srcspace) / sizeof(srcspace[0])); i++) {
+ if(srcspace[i] >= 0)
+ (void)H5Sclose(srcspace[i]);
+ } /* end for */
+ for(i = 0; i < (int)(sizeof(vspace) / sizeof(vspace[0])); i++) {
+ if(vspace[i] >= 0)
+ (void)H5Sclose(vspace[i]);
+ } /* end for */
+ if(filespace >= 0)
+ (void)H5Sclose(filespace);
+ if(memspace >= 0)
+ (void)H5Sclose(memspace);
+ if(dcpl >= 0)
+ (void)H5Pclose(dcpl);
+ if(srcdcpl >= 0)
+ (void)H5Pclose(srcdcpl);
+ if(dapl >= 0)
+ (void)H5Pclose(dapl);
+ if(dxpl_id >=0)
+ (void)H5Pclose(dxpl_id);
+ } H5E_END_TRY;
+
+ return 1;
+} /* end test_unlim() */
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_dapl_values
+ *
+ * Purpose: Ensure that H5Dget_access_plist returns correct values.
+ *
+ * Return: Success: 0
+ * Failure: 1
+ *
+ * Programmer: Dana Robinson
+ * March 2016
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_dapl_values(hid_t fapl_id)
+{
+ hid_t fid = -1; /* file to write to */
+ hid_t dcpl_id = -1; /* dataset creation properties */
+ hid_t dapl_id1 = -1; /* dataset access properties */
+ hid_t dapl_id2 = -1; /* dataset access properties */
+ hid_t vds_sid = -1; /* vds data space */
+ hid_t src_sid = -1; /* source data space */
+ hid_t did1 = -1; /* dataset */
+ hid_t did2 = -1; /* dataset */
+ hsize_t start; /* hyperslab start */
+ hsize_t stride; /* hyperslab count */
+ hsize_t count; /* hyperslab count */
+ hsize_t block; /* hyperslab count */
+ hsize_t dims; /* dataset size */
+ hsize_t max_dims; /* dataset max size */
+ H5D_vds_view_t view; /* view from dapl */
+ hsize_t gap_size; /* gap size from dapl */
+ char filename[1024]; /* file names */
+
+ if (mpi_rank == 0)
+ TESTING("H5Dget_access_plist() returns dapl w/ correct values");
+
+ /* Create the file */
+ h5_fixname(FILENAME[5], fapl_id, filename, sizeof(filename));
+ if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Create the dcpl and set up VDS mapping */
+ if((dcpl_id = H5Pcreate(H5P_DATASET_CREATE)) < 0)
+ FAIL_STACK_ERROR
+ /* source */
+ dims = 42;
+ if((src_sid = H5Screate_simple(1, &dims, NULL)) < 0)
+ FAIL_STACK_ERROR
+ /* vds */
+ dims = 0;
+ max_dims = H5S_UNLIMITED;
+ if((vds_sid = H5Screate_simple(1, &dims, &max_dims)) < 0)
+ FAIL_STACK_ERROR
+ start = 0;
+ stride = 42;
+ count = H5S_UNLIMITED;
+ block = 42;
+ if(H5Sselect_hyperslab(vds_sid, H5S_SELECT_SET, &start, &stride, &count, &block) < 0)
+ FAIL_STACK_ERROR
+ /* map */
+ if(H5Pset_virtual(dcpl_id, vds_sid, "f-%b.h5", "/dset1", src_sid) < 0)
+ FAIL_STACK_ERROR
+
+ /* Create the dapls and set values
+ * There are two of them. The reason for this is that the only way
+ * to set the printf gap is to use the default view and using the
+ * default isn't the best way to test setting and getting the view.
+ */
+ /* dapl 1 */
+ if((dapl_id1 = H5Pcreate(H5P_DATASET_ACCESS)) < 0)
+ FAIL_STACK_ERROR
+ if(H5Pset_virtual_view(dapl_id1, H5D_VDS_FIRST_MISSING) < 0)
+ FAIL_STACK_ERROR
+ /* dapl 2 */
+ if((dapl_id2 = H5Pcreate(H5P_DATASET_ACCESS)) < 0)
+ FAIL_STACK_ERROR
+ /* default but we set it explicitly to be sure */
+ if(H5Pset_virtual_view(dapl_id2, H5D_VDS_LAST_AVAILABLE) < 0)
+ FAIL_STACK_ERROR
+ if(H5Pset_virtual_printf_gap(dapl_id2, 123) < 0)
+ FAIL_STACK_ERROR
+
+ /* Create the datasets */
+ if((did1 = H5Dcreate2(fid, "dset1", H5T_NATIVE_INT, vds_sid, H5P_DEFAULT, dcpl_id, dapl_id1)) < 0)
+ FAIL_STACK_ERROR
+ if((did2 = H5Dcreate2(fid, "dset2", H5T_NATIVE_INT, vds_sid, H5P_DEFAULT, dcpl_id, dapl_id2)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Close the dapls */
+ if(H5Pclose(dapl_id1) < 0)
+ FAIL_STACK_ERROR
+ dapl_id1 = -1;
+ if(H5Pclose(dapl_id2) < 0)
+ FAIL_STACK_ERROR
+ dapl_id2 = -1;
+
+ /* Get a data access property lists from the dataset */
+ if((dapl_id1 = H5Dget_access_plist(did1)) < 0)
+ FAIL_STACK_ERROR
+ if((dapl_id2 = H5Dget_access_plist(did2)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Check the values from the dapls */
+ /* dapl 1 */
+ if(H5Pget_virtual_view(dapl_id1, &view) < 0)
+ FAIL_STACK_ERROR
+ if(H5D_VDS_FIRST_MISSING != view)
+ TEST_ERROR
+ /* dapl 2 */
+ if(H5Pget_virtual_view(dapl_id2, &view) < 0)
+ FAIL_STACK_ERROR
+ if(H5D_VDS_LAST_AVAILABLE != view)
+ TEST_ERROR
+ if(H5Pget_virtual_printf_gap(dapl_id2, &gap_size) < 0)
+ FAIL_STACK_ERROR
+ if(gap_size != 123)
+ TEST_ERROR
+
+ /* Close everything */
+ if(H5Sclose(vds_sid) < 0) FAIL_STACK_ERROR
+ if(H5Sclose(src_sid) < 0) FAIL_STACK_ERROR
+ if(H5Dclose(did1) < 0) FAIL_STACK_ERROR
+ if(H5Dclose(did2) < 0) FAIL_STACK_ERROR
+ if(H5Pclose(dapl_id1) < 0) FAIL_STACK_ERROR
+ if(H5Pclose(dapl_id2) < 0) FAIL_STACK_ERROR
+ if(H5Pclose(dcpl_id) < 0) FAIL_STACK_ERROR
+ if(H5Fclose(fid) < 0) FAIL_STACK_ERROR
+
+ if (mpi_rank == 0)
+ PASSED();
+ return 0;
+
+ error:
+ H5E_BEGIN_TRY {
+ H5Dclose(did1);
+ H5Dclose(did2);
+ H5Pclose(dapl_id1);
+ H5Pclose(dapl_id2);
+ H5Pclose(dcpl_id);
+ H5Sclose(vds_sid);
+ H5Sclose(src_sid);
+ H5Fclose(fid);
+ } H5E_END_TRY;
+ return 1;
+} /* end test_dapl_values() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: main
+ *
+ * Purpose: Tests datasets with virtual layout
+ *
+ * Return: EXIT_SUCCESS/EXIT_FAILURE
+ *
+ * Programmer: Neil Fortner
+ * Tuesday, February 17, 2015
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+main(int argc, char **argv)
+{
+ char filename[FILENAME_BUF_SIZE];
+ hid_t fapl = -1;
+ int nerrors = 0;
+ int test_api_config;
+ unsigned bit_config;
+
+ if ( (MPI_Init(&argc, &argv)) != MPI_SUCCESS) {
+ HDfprintf(stderr, "FATAL: Unable to initialize MPI\n");
+ HDexit(EXIT_FAILURE);
+ }
+
+ if ( (MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank)) != MPI_SUCCESS) {
+ HDfprintf(stderr, "FATAL: MPI_Comm_rank returned an error\n");
+ HDexit(EXIT_FAILURE);
+ }
+
+ if ( (MPI_Comm_size(MPI_COMM_WORLD, &mpi_size)) != MPI_SUCCESS) {
+ HDfprintf(stderr, "FATAL: MPI_Comm_size returned an error\n");
+ HDexit(EXIT_FAILURE);
+ }
+
+ H5open();
+
+ /* Testing setup */
+ h5_reset();
+
+#ifdef H5_HAVE_PARALLEL
+ if ( (fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0 ) {
+ HDfprintf(stderr, "H5Pcreate(H5P_FILE_ACCESS) returned an error\n");
+ goto error;
+ }
+ if ( (H5Pset_fapl_mpio(fapl, MPI_COMM_WORLD, MPI_INFO_NULL)) < 0 ) {
+ HDfprintf(stderr, "H5Pset_fapl_mpio() returned an error\n");
+ goto error;
+ }
+#else
+ fapl = h5_fileaccess();
+#endif
+
+ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename));
+
+ for(test_api_config = (int)TEST_API_BASIC; test_api_config < (int)TEST_API_NTESTS; test_api_config++)
+ nerrors += test_api((test_api_config_t)test_api_config, fapl);
+
+ for(bit_config = 0; bit_config < TEST_IO_NTESTS; bit_config++) {
+ /* Check for configurations currently unsupported by VDS */
+ if((bit_config & TEST_IO_DIFFERENT_FILE) && !((bit_config & TEST_IO_CLOSE_SRC)/* && (bit_config & TEST_IO_REOPEN_VIRT)*/))
+ continue;
+
+ if ( mpi_rank == 0 ) {
+ HDprintf("Config: %s%s%s\n",
+ bit_config & TEST_IO_CLOSE_SRC ? "closed source dataset, "
+ : "",
+ bit_config & TEST_IO_DIFFERENT_FILE ? "different source file"
+ : "same source file",
+ bit_config & TEST_IO_REOPEN_VIRT ? ", reopen virtual file"
+ : "");
+ }
+ nerrors += test_basic_io(bit_config, fapl);
+ nerrors += test_unlim(bit_config, fapl);
+ } /* end for */
+
+ nerrors += test_dapl_values(fapl);
+
+ /* Verify symbol table messages are cached */
+ nerrors += (h5_verify_cached_stabs(FILENAME, fapl) < 0 ? 1 : 0);
+
+error:
+ h5_cleanup(FILENAME, fapl);
+
+ if ( mpi_rank == 0 ) {
+ if (nerrors == 0)
+ HDprintf("All virtual dataset tests passed.\n");
+ else
+ HDprintf("virtual dataset tests failed.\n");
+ }
+
+ MPI_Barrier(MPI_COMM_WORLD);
+
+ if (H5close() != SUCCEED) {
+ HDfprintf(stdout, "H5close() failed. (Ignoring)\n");
+ }
+ return((nerrors > 0) ? EXIT_FAILURE : EXIT_SUCCESS );
+
+} /* end main() */
+