summaryrefslogtreecommitdiffstats
path: root/perform/pio_engine.c
diff options
context:
space:
mode:
Diffstat (limited to 'perform/pio_engine.c')
-rw-r--r--perform/pio_engine.c800
1 files changed, 158 insertions, 642 deletions
diff --git a/perform/pio_engine.c b/perform/pio_engine.c
index d34fe38..82d1bb8 100644
--- a/perform/pio_engine.c
+++ b/perform/pio_engine.c
@@ -37,10 +37,6 @@
# include <mpio.h>
#endif /* !MPI_FILE_NULL */
-#ifdef H5_HAVE_GPFS
-# include <gpfs_fcntl.h>
-#endif /* H5_HAVE_GPFS */
-
#include "pio_perf.h"
#include "pio_timer.h"
@@ -135,19 +131,6 @@ static herr_t do_fopen(parameters *param, char *fname, file_descr *fd /*out*/,
static herr_t do_fclose(iotype iot, file_descr *fd);
static void do_cleanupfile(iotype iot, char *fname);
-/* GPFS-specific functions */
-#ifdef H5_HAVE_GPFS
-static void gpfs_access_range(int handle, off_t start, off_t length, int is_write);
-static void gpfs_free_range(int handle, off_t start, off_t length);
-static void gpfs_clear_file_cache(int handle);
-static void gpfs_cancel_hints(int handle);
-static void gpfs_start_data_shipping(int handle, int num_insts);
-static void gpfs_start_data_ship_map(int handle, int partition_size,
- int agent_count, int *agent_node_num);
-static void gpfs_stop_data_shipping(int handle);
-static void gpfs_invalidate_file_cache(const char *filename);
-#endif /* H5_HAVE_GPFS */
-
/*
* Function: do_pio
* Purpose: PIO Engine where Parallel IO are executed.
@@ -189,22 +172,22 @@ do_pio(parameters param)
iot = param.io_type;
switch (iot) {
- case MPIO:
- fd.mpifd = MPI_FILE_NULL;
- res.timers = pio_time_new(MPI_TIMER);
- break;
- case POSIXIO:
- fd.posixfd = -1;
- res.timers = pio_time_new(MPI_TIMER);
- break;
- case PHDF5:
- fd.h5fd = -1;
- res.timers = pio_time_new(MPI_TIMER);
- break;
- default:
- /* unknown request */
- fprintf(stderr, "Unknown IO type request (%d)\n", iot);
- GOTOERROR(FAIL);
+ case MPIO:
+ fd.mpifd = MPI_FILE_NULL;
+ res.timers = pio_time_new(MPI_TIMER);
+ break;
+ case POSIXIO:
+ fd.posixfd = -1;
+ res.timers = pio_time_new(MPI_TIMER);
+ break;
+ case PHDF5:
+ fd.h5fd = -1;
+ res.timers = pio_time_new(MPI_TIMER);
+ break;
+ default:
+ /* unknown request */
+ fprintf(stderr, "Unknown IO type request (%d)\n", iot);
+ GOTOERROR(FAIL);
}
ndsets = param.num_dsets; /* number of datasets per file */
@@ -379,18 +362,18 @@ done:
/* close any opened files */
/* no remove(fname) because that should have happened normally. */
switch (iot) {
- case POSIXIO:
- if (fd.posixfd != -1)
- hrc = do_fclose(iot, &fd);
- break;
- case MPIO:
- if (fd.mpifd != MPI_FILE_NULL)
- hrc = do_fclose(iot, &fd);
- break;
- case PHDF5:
- if (fd.h5fd != -1)
- hrc = do_fclose(iot, &fd);
- break;
+ case POSIXIO:
+ if (fd.posixfd != -1)
+ hrc = do_fclose(iot, &fd);
+ break;
+ case MPIO:
+ if (fd.mpifd != MPI_FILE_NULL)
+ hrc = do_fclose(iot, &fd);
+ break;
+ case PHDF5:
+ if (fd.h5fd != -1)
+ hrc = do_fclose(iot, &fd);
+ break;
}
/* release generic resources */
@@ -423,15 +406,15 @@ pio_create_filename(iotype iot, const char *base_name, char *fullname, size_t si
HDmemset(fullname, 0, size);
switch (iot) {
- case POSIXIO:
- suffix = ".posix";
- break;
- case MPIO:
- suffix = ".mpio";
- break;
- case PHDF5:
- suffix = ".h5";
- break;
+ case POSIXIO:
+ suffix = ".posix";
+ break;
+ case MPIO:
+ suffix = ".mpio";
+ break;
+ case PHDF5:
+ suffix = ".h5";
+ break;
}
/* First use the environment variable and then try the constant */
@@ -886,60 +869,59 @@ do_write(results *res, file_descr *fd, parameters *parms, long ndsets,
switch (parms->io_type) {
case POSIXIO:
case MPIO:
- /* both posix and mpi io just need dataset offset in file*/
- dset_offset = (ndset - 1) * nbytes;
- break;
+ /* both posix and mpi io just need dataset offset in file*/
+ dset_offset = (ndset - 1) * nbytes;
+ break;
case PHDF5:
- h5dcpl = H5Pcreate(H5P_DATASET_CREATE);
- if (h5dcpl < 0) {
- fprintf(stderr, "HDF5 Property List Create failed\n");
- GOTOERROR(FAIL);
- }
- /* 1D dataspace */
- if (!parms->dim2d){
- /* Make the dataset chunked if asked */
- if(parms->h5_use_chunks) {
- /* Set the chunk size to be the same as the buffer size */
- h5dims[0] = blk_size;
- hrc = H5Pset_chunk(h5dcpl, 1, h5dims);
- if (hrc < 0) {
- fprintf(stderr, "HDF5 Property List Set failed\n");
- GOTOERROR(FAIL);
- } /* end if */
- } /* end if */
- }/* end if */
- else{
- /* 2D dataspace */
- if(parms->h5_use_chunks) {
- /* Set the chunk size to be the same as the block size */
- h5dims[0] = blk_size;
- h5dims[1] = blk_size;
- hrc = H5Pset_chunk(h5dcpl, 2, h5dims);
- if (hrc < 0) {
- fprintf(stderr, "HDF5 Property List Set failed\n");
+ h5dcpl = H5Pcreate(H5P_DATASET_CREATE);
+ if (h5dcpl < 0) {
+ fprintf(stderr, "HDF5 Property List Create failed\n");
GOTOERROR(FAIL);
- } /* end if */
- } /* end if */
- }/* end else */
-
- sprintf(dname, "Dataset_%ld", ndset);
- h5ds_id = H5DCREATE(fd->h5fd, dname, ELMT_H5_TYPE,
- h5dset_space_id, h5dcpl);
+ }
+ /* 1D dataspace */
+ if (!parms->dim2d){
+ /* Make the dataset chunked if asked */
+ if(parms->h5_use_chunks) {
+ /* Set the chunk size to be the same as the buffer size */
+ h5dims[0] = blk_size;
+ hrc = H5Pset_chunk(h5dcpl, 1, h5dims);
+ if (hrc < 0) {
+ fprintf(stderr, "HDF5 Property List Set failed\n");
+ GOTOERROR(FAIL);
+ } /* end if */
+ } /* end if */
+ }/* end if */
+ else{
+ /* 2D dataspace */
+ if(parms->h5_use_chunks) {
+ /* Set the chunk size to be the same as the block size */
+ h5dims[0] = blk_size;
+ h5dims[1] = blk_size;
+ hrc = H5Pset_chunk(h5dcpl, 2, h5dims);
+ if (hrc < 0) {
+ fprintf(stderr, "HDF5 Property List Set failed\n");
+ GOTOERROR(FAIL);
+ } /* end if */
+ } /* end if */
+ }/* end else */
- if (h5ds_id < 0) {
- fprintf(stderr, "HDF5 Dataset Create failed\n");
- GOTOERROR(FAIL);
- }
+ sprintf(dname, "Dataset_%ld", ndset);
+ h5ds_id = H5DCREATE(fd->h5fd, dname, ELMT_H5_TYPE,
+ h5dset_space_id, h5dcpl);
- hrc = H5Pclose(h5dcpl);
- /* verifying the close of the dcpl */
- if (hrc < 0) {
- fprintf(stderr, "HDF5 Property List Close failed\n");
- GOTOERROR(FAIL);
- }
+ if (h5ds_id < 0) {
+ fprintf(stderr, "HDF5 Dataset Create failed\n");
+ GOTOERROR(FAIL);
+ }
- break;
+ hrc = H5Pclose(h5dcpl);
+ /* verifying the close of the dcpl */
+ if (hrc < 0) {
+ fprintf(stderr, "HDF5 Property List Close failed\n");
+ GOTOERROR(FAIL);
+ }
+ break;
}
/* The task is to transfer bytes_count bytes, starting at
@@ -2462,119 +2444,96 @@ done:
do_fopen(parameters *param, char *fname, file_descr *fd /*out*/, int flags)
{
int ret_code = SUCCESS, mrc;
- herr_t hrc;
hid_t acc_tpl = -1; /* file access templates */
- hbool_t use_gpfs = FALSE; /* use GPFS hints */
switch (param->io_type) {
- case POSIXIO:
- if (flags & (PIO_CREATE | PIO_WRITE))
- fd->posixfd = POSIXCREATE(fname);
- else
- fd->posixfd = POSIXOPEN(fname, O_RDONLY);
-
- if (fd->posixfd < 0 ) {
- fprintf(stderr, "POSIX File Open failed(%s)\n", fname);
- GOTOERROR(FAIL);
- }
-
-
- /* The perils of POSIX I/O in a parallel environment. The problem is:
- *
- * - Process n opens a file with truncation and then starts
- * writing to the file.
- * - Process m also opens the file with truncation, but after
- * process n has already started to write to the file. Thus,
- * all of the stuff process n wrote is now lost.
- */
- MPI_Barrier(pio_comm_g);
-
- break;
-
- case MPIO:
- if (flags & (PIO_CREATE | PIO_WRITE)) {
- MPI_File_delete(fname, h5_io_info_g);
- mrc = MPI_File_open(pio_comm_g, fname, MPI_MODE_CREATE | MPI_MODE_RDWR,
- h5_io_info_g, &fd->mpifd);
+ case POSIXIO:
+ if (flags & (PIO_CREATE | PIO_WRITE))
+ fd->posixfd = POSIXCREATE(fname);
+ else
+ fd->posixfd = POSIXOPEN(fname, O_RDONLY);
- if (mrc != MPI_SUCCESS) {
- fprintf(stderr, "MPI File Open failed(%s)\n", fname);
- GOTOERROR(FAIL);
- }
+ if (fd->posixfd < 0 ) {
+ fprintf(stderr, "POSIX File Open failed(%s)\n", fname);
+ GOTOERROR(FAIL);
+ }
- /*since MPI_File_open with MPI_MODE_CREATE does not truncate */
- /*filesize , set size to 0 explicitedly. */
- mrc = MPI_File_set_size(fd->mpifd, (MPI_Offset)0);
- if (mrc != MPI_SUCCESS) {
- fprintf(stderr, "MPI_File_set_size failed\n");
- GOTOERROR(FAIL);
- }
- } else {
- mrc = MPI_File_open(pio_comm_g, fname, MPI_MODE_RDONLY,
- h5_io_info_g, &fd->mpifd);
+ /* The perils of POSIX I/O in a parallel environment. The problem is:
+ *
+ * - Process n opens a file with truncation and then starts
+ * writing to the file.
+ * - Process m also opens the file with truncation, but after
+ * process n has already started to write to the file. Thus,
+ * all of the stuff process n wrote is now lost.
+ */
+ MPI_Barrier(pio_comm_g);
- if (mrc != MPI_SUCCESS) {
- fprintf(stderr, "MPI File Open failed(%s)\n", fname);
- GOTOERROR(FAIL);
- }
- }
+ break;
- break;
+ case MPIO:
+ if (flags & (PIO_CREATE | PIO_WRITE)) {
+ MPI_File_delete(fname, h5_io_info_g);
+ mrc = MPI_File_open(pio_comm_g, fname, MPI_MODE_CREATE | MPI_MODE_RDWR,
+ h5_io_info_g, &fd->mpifd);
+
+ if (mrc != MPI_SUCCESS) {
+ fprintf(stderr, "MPI File Open failed(%s)\n", fname);
+ GOTOERROR(FAIL);
+ }
- case PHDF5:
- acc_tpl = H5Pcreate(H5P_FILE_ACCESS);
- if (acc_tpl < 0) {
- fprintf(stderr, "HDF5 Property List Create failed\n");
- GOTOERROR(FAIL);
- }
+ /*since MPI_File_open with MPI_MODE_CREATE does not truncate */
+ /*filesize , set size to 0 explicitedly. */
+ mrc = MPI_File_set_size(fd->mpifd, (MPI_Offset)0);
+ if (mrc != MPI_SUCCESS) {
+ fprintf(stderr, "MPI_File_set_size failed\n");
+ GOTOERROR(FAIL);
+ }
+ } else {
+ mrc = MPI_File_open(pio_comm_g, fname, MPI_MODE_RDONLY, h5_io_info_g, &fd->mpifd);
+ if (mrc != MPI_SUCCESS) {
+ fprintf(stderr, "MPI File Open failed(%s)\n", fname);
+ GOTOERROR(FAIL);
+ }
+ }
- /* Use the appropriate VFL driver */
- if(param->h5_use_mpi_posix) {
- /* Set the file driver to the MPI-posix driver */
- hrc = H5Pset_fapl_mpiposix(acc_tpl, pio_comm_g, use_gpfs);
- if (hrc < 0) {
- fprintf(stderr, "HDF5 Property List Set failed\n");
- GOTOERROR(FAIL);
- }
- } /* end if */
- else {
- /* Set the file driver to the MPI-I/O driver */
- hrc = H5Pset_fapl_mpio(acc_tpl, pio_comm_g, h5_io_info_g);
- if (hrc < 0) {
- fprintf(stderr, "HDF5 Property List Set failed\n");
- GOTOERROR(FAIL);
- }
- } /* end else */
+ break;
- /* Set the alignment of objects in HDF5 file */
- hrc = H5Pset_alignment(acc_tpl, param->h5_thresh, param->h5_align);
- if (hrc < 0) {
- fprintf(stderr, "HDF5 Property List Set failed\n");
- GOTOERROR(FAIL);
- }
+ case PHDF5:
+ if ((acc_tpl = H5Pcreate(H5P_FILE_ACCESS)) < 0) {
+ fprintf(stderr, "HDF5 Property List Create failed\n");
+ GOTOERROR(FAIL);
+ }
- /* create the parallel file */
- if (flags & (PIO_CREATE | PIO_WRITE)) {
- fd->h5fd = H5Fcreate(fname, H5F_ACC_TRUNC, H5P_DEFAULT, acc_tpl);
- } else {
- fd->h5fd = H5Fopen(fname, H5F_ACC_RDONLY, acc_tpl);
- }
+ /* Set the file driver to the MPI-IO driver */
+ if (H5Pset_fapl_mpio(acc_tpl, pio_comm_g, h5_io_info_g) < 0) {
+ fprintf(stderr, "HDF5 Property List Set failed\n");
+ GOTOERROR(FAIL);
+ }
- hrc = H5Pclose(acc_tpl);
+ /* Set the alignment of objects in HDF5 file */
+ if (H5Pset_alignment(acc_tpl, param->h5_thresh, param->h5_align) < 0) {
+ fprintf(stderr, "HDF5 Property List Set failed\n");
+ GOTOERROR(FAIL);
+ }
- if (fd->h5fd < 0) {
- fprintf(stderr, "HDF5 File Create failed(%s)\n", fname);
- GOTOERROR(FAIL);
- }
+ /* create the parallel file */
+ if (flags & (PIO_CREATE | PIO_WRITE))
+ fd->h5fd = H5Fcreate(fname, H5F_ACC_TRUNC, H5P_DEFAULT, acc_tpl);
+ else
+ fd->h5fd = H5Fopen(fname, H5F_ACC_RDONLY, acc_tpl);
+ if (fd->h5fd < 0) {
+ fprintf(stderr, "HDF5 File Create failed(%s)\n", fname);
+ GOTOERROR(FAIL);
+ }
- /* verifying the close of the acc_tpl */
- if (hrc < 0) {
- fprintf(stderr, "HDF5 Property List Close failed\n");
- GOTOERROR(FAIL);
- }
+ /* verifying the close of the acc_tpl */
+ if (H5Pclose(acc_tpl) < 0) {
+ fprintf(stderr, "HDF5 Property List Close failed\n");
+ GOTOERROR(FAIL);
+ }
- break;
+ break;
}
done:
@@ -2665,449 +2624,6 @@ do_cleanupfile(iotype iot, char *fname)
}
}
-#ifdef H5_HAVE_GPFS
-
-/* Descriptions here come from the IBM GPFS Manual */
-
-/*
- * Function: gpfs_access_range
- * Purpose: Declares an access range within a file for an
- * application.
- *
- * The application will access file offsets within the given
- * range, and will not access offsets outside the range.
- * Violating this hint may produce worse performance than if
- * no hint was specified.
- *
- * This hint is useful in situations where a file is
- * partitioned coarsely among several nodes. If the ranges
- * do not overlap, each node can specify which range of the
- * file it will access, with a performance improvement in
- * some cases, such as for sequential writing within a
- * range.
- *
- * Subsequent GPFS_ACCESS_RANGE hints will replace a hint
- * passed earlier.
- *
- * START - The start of the access range offset, in
- * bytes, from the beginning of the file
- * LENGTH - Length of the access range. 0 indicates to
- * the end of the file
- * IS_WRITE - 0 indicates READ access, 1 indicates WRITE access
- * Return: Nothing
- * Programmer: Bill Wendling, 03. June 2002
- * Modifications:
- */
- static void
-gpfs_access_range(int handle, off_t start, off_t length, int is_write)
-{
- struct {
- gpfsFcntlHeader_t hdr;
- gpfsAccessRange_t access;
- } access_range;
-
- access_range.hdr.totalLength = sizeof(access_range);
- access_range.hdr.fcntlVersion = GPFS_FCNTL_CURRENT_VERSION;
- access_range.hdr.fcntlReserved = 0;
- access_range.access.structLen = sizeof(gpfsAccessRange_t);
- access_range.access.structType = GPFS_ACCESS_RANGE;
- access_range.access.start = start;
- access_range.access.length = length;
- access_range.access.isWrite = is_write;
-
- if (gpfs_fcntl(handle, &access_range) != 0) {
- fprintf(stderr,
- "gpfs_fcntl DS start directive failed. errno=%d errorOffset=%d\n",
- errno, access_range.hdr.errorOffset);
- exit(EXIT_FAILURE);
- }
-}
-
-/*
- * Function: gpfs_free_range
- * Purpose: Undeclares an access range within a file for an
- * application.
- *
- * The application will no longer access file offsets within
- * the given range. GPFS flushes the data at the file
- * offsets and removes it from the cache.
- *
- * Multi-node applications that have finished one phase of
- * their computation may wish to use this hint before the
- * file is accessed in a conflicting mode from another node
- * in a later phase. The potential performance benefit is
- * that GPFS can avoid later synchronous cache consistency
- * operations.
- *
- * START - The start of the access range offset, in
- * bytes from the beginning of the file.
- * LENGTH - Length of the access range. 0 indicates to
- * the end of the file.
- * Return: Nothing
- * Programmer: Bill Wendling, 03. June 2002
- * Modifications:
- */
- static void
-gpfs_free_range(int handle, off_t start, off_t length)
-{
- struct {
- gpfsFcntlHeader_t hdr;
- gpfsFreeRange_t range;
- } free_range;
-
- /* Issue the invalidate hint */
- free_range.hdr.totalLength = sizeof(free_range);
- free_range.hdr.fcntlVersion = GPFS_FCNTL_CURRENT_VERSION;
- free_range.hdr.fcntlReserved = 0;
- free_range.range.structLen = sizeof(gpfsFreeRange_t);
- free_range.range.structType = GPFS_FREE_RANGE;
- free_range.range.start = start;
- free_range.range.length = length;
-
- if (gpfs_fcntl(handle, &free_range) != 0) {
- fprintf(stderr,
- "gpfs_fcntl free range failed for range %d:%d. errno=%d errorOffset=%d\n",
- start, length, errno, free_range.hdr.errorOffset);
- exit(EXIT_FAILURE);
- }
-}
-
-/*
- * Function: gpfs_clear_file_cache
- * Purpose: Indicates file access in the near future is not expected.
- *
- * The application does not expect to make any further
- * accesses to the file in the near future, so GPFS removes
- * any data or metadata pertaining to the file from its
- * cache.
- *
- * Multi-node applications that have finished one phase of
- * their computation may wish to use this hint before the
- * file is accessed in a conflicting mode from another node
- * in a later phase. The potential performance benefit is
- * that GPFS can avoid later synchronous cache consistency
- * operations.
- * Return: Nothing
- * Programmer: Bill Wendling, 03. June 2002
- * Modifications:
- */
- static void
-gpfs_clear_file_cache(int handle)
-{
- struct {
- gpfsFcntlHeader_t hdr;
- gpfsClearFileCache_t clear;
- } clear_cache;
-
- clear_cache.hdr.totalLength = sizeof(clear_cache);
- clear_cache.hdr.fcntlVersion = GPFS_FCNTL_CURRENT_VERSION;
- clear_cache.hdr.fcntlReserved = 0;
- clear_cache.clear.structLen = sizeof(gpfsClearFileCache_t);
- clear_cache.clear.structType = GPFS_CLEAR_FILE_CACHE;
-
- if (gpfs_fcntl(handle, &clear_cache) != 0) {
- fprintf(stderr,
- "gpfs_fcntl clear file cache directive failed. errno=%d errorOffset=%d\n",
- errno, clear_cache.hdr.errorOffset);
- exit(EXIT_FAILURE);
- }
-}
-
-/*
- * Function: gpfs_cancel_hints
- * Purpose: Indicates to remove any hints against the open file
- * handle.
- *
- * GPFS removes any hints that may have been issued against
- * this open file handle:
- *
- * - The hint status of the file is restored ot what it
- * would have been immediately after being opened, but
- * does not affect the contents of the GPFS file
- * cache. Cancelling an earlier hint that resulted in
- * data being removed from the GPFS file cache does
- * not bring that data back int othe cache; data
- * re-enters the cache only pon access by the
- * application or by user-driven or automatic
- * prefetching.
- * - Only the GPFS_MULTIPLE_ACCESS_RANGE hint has a
- * state that might be removed by the
- * GPFS_CANCEL_HINTS directive.
- * Return: Nothing
- * Programmer: Bill Wendling, 03. June 2002
- * Modifications:
- */
- static void
-gpfs_cancel_hints(int handle)
-{
- struct {
- gpfsFcntlHeader_t hdr;
- gpfsCancelHints_t cancel;
- } cancel_hints;
-
- cancel_hints.hdr.totalLength = sizeof(cancel_hints);
- cancel_hints.hdr.fcntlVersion = GPFS_FCNTL_CURRENT_VERSION;
- cancel_hints.hdr.fcntlReserved = 0;
- cancel_hints.cancel.structLen = sizeof(gpfsCancelHints_t);
- cancel_hints.cancel.structType = GPFS_CANCEL_HINTS;
-
- if (gpfs_fcntl(handle, &cancel_hints) != 0) {
- fprintf(stderr,
- "gpfs_fcntl cancel hints directive failed. errno=%d errorOffset=%d\n",
- errno, cancel_hints.hdr.errorOffset);
- exit(EXIT_FAILURE);
- }
-}
-
-/*
- * Function: gpfs_start_data_shipping
- * Purpose: Initiates data shipping mode.
- *
- * Once all participating threads have issued this directive
- * for a file, GPFS enters a mode where it logically
- * partitions the blocks of the file among a group of agent
- * nodes. The agents are those nodes on which one or more
- * threads have issued the GPFS_DATA_SHIP_START directive.
- * Each thread that has issued a GPFS_DATA_SHIP_START
- * directive and the associated agent nodes are referred to
- * as the data shipping collective.
- *
- * The second parameter is the total number of open
- * instances on all nodes that will be operating on the
- * file. Must be called for every such instance with the
- * same value of NUM_INSTS.
- *
- * NUM_INSTS - The number of open file instances, on all
- * nodes, collaborating to operate on the file
- * Return: Nothing
- * Programmer: Bill Wendling, 28. May 2002
- * Modifications:
- */
- static void
-gpfs_start_data_shipping(int handle, int num_insts)
-{
- struct {
- gpfsFcntlHeader_t hdr;
- gpfsDataShipStart_t start;
- } ds_start;
-
- ds_start.hdr.totalLength = sizeof(ds_start);
- ds_start.hdr.fcntlVersion = GPFS_FCNTL_CURRENT_VERSION;
- ds_start.hdr.fcntlReserved = 0;
- ds_start.start.structLen = sizeof(gpfsDataShipStart_t);
- ds_start.start.structType = GPFS_DATA_SHIP_START;
- ds_start.start.numInstances = num_insts;
- ds_start.start.reserved = 0;
-
- if (gpfs_fcntl(handle, &ds_start) != 0) {
- fprintf(stderr,
- "gpfs_fcntl DS start directive failed. errno=%d errorOffset=%d\n",
- errno, ds_start.hdr.errorOffset);
- exit(EXIT_FAILURE);
- }
-}
-
-/*
- * Function: gpfs_start_data_ship_map
- * Purpose: Indicates which agent nodes are to be used for data
- * shipping. GPFS recognizes which agent nodes to use for
- * data shipping.
- *
- * PARTITION_SIZE - The number of contiguous bytes per
- * server. This value must be a
- * multiple of the number of bytes in a
- * single file system block
- * AGENT_COUNT - The number of entries in the
- * agentNodeNumber array
- * AGENT_NODE_NUM - The data ship agent node numbers as
- * listed in the SDT or the global ODM
- *
- * Return: Nothing
- * Programmer: Bill Wendling, 10. Jul 2002
- * Modifications:
- */
- static void
-gpfs_start_data_ship_map(int handle, int partition_size, int agent_count,
- int *agent_node_num)
-{
- int i;
- struct {
- gpfsFcntlHeader_t hdr;
- gpfsDataShipMap_t map;
- } ds_map;
-
- ds_map.hdr.totalLength = sizeof(ds_map);
- ds_map.hdr.fcntlVersion = GPFS_FCNTL_CURRENT_VERSION;
- ds_map.hdr.fcntlReserved = 0;
- ds_map.map.structLen = sizeof(gpfsDataShipMap_t);
- ds_map.map.structType = GPFS_DATA_SHIP_MAP;
- ds_map.map.partitionSize = partition_size;
- ds_map.map.agentCount = agent_count;
-
- for (i = 0; i < agent_count; ++i)
- ds_map.map.agentNodeNumber[i] = agent_node_num[i];
-
- if (gpfs_fcntl(handle, &ds_map) != 0) {
- fprintf(stderr,
- "gpfs_fcntl DS map directive failed. errno=%d errorOffset=%d\n",
- errno, ds_map.hdr.errorOffset);
- exit(EXIT_FAILURE);
- }
-}
-
-/*
- * Function: gpfs_stop_data_shipping
- * Purpose: Takes a file out of the data shipping mode.
- *
- * - GPFS waits for all threads that issued the
- * GPFS_DATA_SHIP_START directive to issue this directive,
- * then flushes the dirty file data to disk.
- *
- * - While a gpfs_cntl() call is blocked for other threads,
- * the call can be interrupted by any signal. If a signal
- * is delivered to any of the waiting calls, all waiting
- * calls on every node will be interrupted and will return
- * EINTR. GPFS will not cancel data shipping mode if such
- * a signal occurs. It is the responsibility of the
- * application to mask off any signals that might normally
- * occur while waiting for another node in the data
- * shipping collective. Several libraries use SIGALRM; the
- * thread that makes the gpfs_fcntl() call should use
- * sigthreadmask to mask off delivery of this signal while
- * inside the call.
- * Return: Nothing
- * Programmer: Bill Wendling, 28. May 2002
- * Modifications:
- */
- static void
-gpfs_stop_data_shipping(int handle)
-{
- struct {
- gpfsFcntlHeader_t hdr;
- gpfsDataShipStop_t stop;
- } ds_stop;
-
- ds_stop.hdr.totalLength = sizeof(ds_stop);
- ds_stop.hdr.fcntlVersion = GPFS_FCNTL_CURRENT_VERSION;
- ds_stop.hdr.fcntlReserved = 0;
- ds_stop.stop.structLen = sizeof(ds_stop.stop);
- ds_stop.stop.structType = GPFS_DATA_SHIP_STOP;
-
- if (gpfs_fcntl(handle, &ds_stop) != 0)
- fprintf(stderr,
- "gpfs_fcntl DS stop directive failed. errno=%d errorOffset=%d\n",
- errno, ds_stop.hdr.errorOffset);
-}
-
-/*
- * Function: gpfs_invalidate_file_cache
- * Purpose: Invalidate all cached data held on behalf of a file on
- * this node.
- * Return: Nothing
- * Programmer: Bill Wendling, 03. June 2002
- * Modifications:
- */
- static void
-gpfs_invalidate_file_cache(const char *filename)
-{
- int handle;
- struct {
- gpfsFcntlHeader_t hdr;
- gpfsClearFileCache_t inv;
- } inv_cache_hint;
-
- /* Open the file. If the open fails, the file cannot be cached. */
- handle = open(filename, O_RDONLY, 0);
-
- if (handle == -1)
- return;
-
- /* Issue the invalidate hint */
- inv_cache_hint.hdr.totalLength = sizeof(inv_cache_hint);
- inv_cache_hint.hdr.fcntlVersion = GPFS_FCNTL_CURRENT_VERSION;
- inv_cache_hint.hdr.fcntlReserved = 0;
- inv_cache_hint.inv.structLen = sizeof(gpfsClearFileCache_t);
- inv_cache_hint.inv.structType = GPFS_CLEAR_FILE_CACHE;
-
- if (gpfs_fcntl(handle, &inv_cache_hint) != 0) {
- fprintf(stderr,
- "gpfs_fcntl clear cache hint failed for file '%s'.",
- filename);
- fprintf(stderr, " errno=%d errorOffset=%d\n",
- errno, inv_cache_hint.hdr.errorOffset);
- exit(EXIT_FAILURE);
- }
-
- /* Close the file */
- if (close(handle) == -1) {
- fprintf(stderr,
- "could not close file '%s' after flushing file cache, ",
- filename);
- fprintf(stderr, "errno=%d\n", errno);
- exit(EXIT_FAILURE);
- }
-}
-
-#else
-
-/* turn the stubs off since some compilers are warning they are not used */
-#if 0
-/* H5_HAVE_GPFS isn't defined...stub functions */
-
- static void
-gpfs_access_range(int UNUSED handle, off_t UNUSED start, off_t UNUSED length,
- int UNUSED is_write)
-{
- return;
-}
-
- static void
-gpfs_free_range(int UNUSED handle, off_t UNUSED start, off_t UNUSED length)
-{
- return;
-}
-
- static void
-gpfs_clear_file_cache(int UNUSED handle)
-{
- return;
-}
-
- static void
-gpfs_cancel_hints(int UNUSED handle)
-{
- return;
-}
-
- static void
-gpfs_start_data_shipping(int UNUSED handle, int UNUSED num_insts)
-{
- return;
-}
-
- static void
-gpfs_stop_data_shipping(int UNUSED handle)
-{
- return;
-}
-
- static void
-gpfs_start_data_ship_map(int UNUSED handle, int UNUSED partition_size,
- int UNUSED agent_count, int UNUSED *agent_node_num)
-{
- return;
-}
-
- static void
-gpfs_invalidate_file_cache(const char UNUSED *filename)
-{
- return;
-}
-
-#endif /* 0 */
-
-#endif /* H5_HAVE_GPFS */
-
#ifdef TIME_MPI
/* instrument the MPI_File_wrirte_xxx and read_xxx calls to measure
* pure time spent in MPI_File code.