mirror of
https://github.com/HDFGroup/hdf5.git
synced 2025-01-30 15:32:37 +08:00
680262645f
Bug fix and File Addition Description: - Fixed when reading from the file with FPHDF5. It wasn't recording how many bytes it read. - Added Arithmetic Transformation modules. These haven't been included into the HDF5 build. I just added them here for future porposes... Solution: Added a call to "MPI_Get_count" to get the number of bytes read. Platforms tested: Linux (w/ FPHDF5) AIX (w/ and w/o FPHDF5) FPHDF5-specific fixes...No need for H5committest Misc. update:
1657 lines
59 KiB
C
1657 lines
59 KiB
C
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||
* 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://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have *
|
||
* access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. *
|
||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||
|
||
/* Pablo information */
|
||
/* (Put before include files to avoid problems with inline functions) */
|
||
#define PABLO_MASK H5FD_fphdf5_mask
|
||
|
||
#include "H5private.h" /* Generic Functions */
|
||
#include "H5ACprivate.h" /* Metadata cache */
|
||
#include "H5Dprivate.h" /* Datasets */
|
||
#include "H5Eprivate.h" /* Error handling */
|
||
#include "H5Fprivate.h" /* Files access */
|
||
#include "H5FDprivate.h" /* File drivers */
|
||
#include "H5FDfphdf5.h" /* Flexible PHDF5 file driver */
|
||
#include "H5FDmpio.h" /* MPI I/O file driver */
|
||
#include "H5Iprivate.h" /* IDs */
|
||
#include "H5MMprivate.h" /* Memory management */
|
||
#include "H5Pprivate.h" /* Property lists */
|
||
|
||
#ifdef H5_HAVE_FPHDF5
|
||
|
||
#include "H5FPprivate.h" /* Flexible PHDF5 */
|
||
|
||
/*
|
||
* The driver identification number, initialized at runtime if
|
||
* H5_HAVE_FPHDF5 is defined. This allows applications to still have
|
||
* the H5FD_FPHDF5 "constants" in their source code (it also makes this
|
||
* file strictly ANSI compliant when H5_HAVE_FPHDF5 isn't defined)
|
||
*/
|
||
static hid_t H5FD_FPHDF5_g = 0;
|
||
|
||
/*
|
||
* Prototypes
|
||
*/
|
||
static haddr_t H5FD_fphdf5_MPIOff_to_haddr(MPI_Offset mpi_off);
|
||
static herr_t H5FD_fphdf5_haddr_to_MPIOff(haddr_t addr, MPI_Offset *mpi_off);
|
||
|
||
/*
|
||
* Callbacks
|
||
*/
|
||
static void *H5FD_fphdf5_fapl_get(H5FD_t *_file);
|
||
static H5FD_t *H5FD_fphdf5_open(const char *name, unsigned flags,
|
||
hid_t fapl_id, haddr_t maxaddr);
|
||
static herr_t H5FD_fphdf5_close(H5FD_t *_file);
|
||
static herr_t H5FD_fphdf5_query(const H5FD_t *_f1, unsigned long *flags);
|
||
static haddr_t H5FD_fphdf5_get_eoa(H5FD_t *_file);
|
||
static herr_t H5FD_fphdf5_set_eoa(H5FD_t *_file, haddr_t addr);
|
||
static haddr_t H5FD_fphdf5_get_eof(H5FD_t *_file);
|
||
static herr_t H5FD_fphdf5_get_handle(H5FD_t *_file, hid_t fapl,
|
||
void **file_handle);
|
||
static herr_t H5FD_fphdf5_read(H5FD_t *_file, H5FD_mem_t mem_type, hid_t dxpl_id,
|
||
haddr_t addr, size_t size, void *buf);
|
||
static herr_t H5FD_fphdf5_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id,
|
||
haddr_t addr, size_t size, const void *buf);
|
||
static herr_t H5FD_fphdf5_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing);
|
||
|
||
/*
|
||
* FPHDF5-specific file access properties
|
||
*/
|
||
typedef struct H5FD_fphdf5_fapl_t {
|
||
MPI_Comm comm; /*communicator */
|
||
MPI_Comm barrier_comm; /*barrier communicator */
|
||
MPI_Info info; /*file information */
|
||
unsigned sap_rank; /*SAP's rank */
|
||
unsigned capt_rank; /*captain rank */
|
||
} H5FD_fphdf5_fapl_t;
|
||
|
||
/*
|
||
* The FPHDF5 file driver information
|
||
*/
|
||
const H5FD_class_t H5FD_fphdf5_g = {
|
||
"fphdf5", /*name */
|
||
HADDR_MAX, /*maxaddr */
|
||
H5F_CLOSE_SEMI, /*fc_degree */
|
||
NULL, /*sb_size */
|
||
NULL, /*sb_encode */
|
||
NULL, /*sb_decode */
|
||
sizeof(H5FD_fphdf5_fapl_t), /*fapl_size */
|
||
H5FD_fphdf5_fapl_get, /*fapl_get */
|
||
NULL, /*fapl_copy */
|
||
NULL, /*fapl_free */
|
||
0, /*dxpl_size */
|
||
NULL, /*dxpl_copy */
|
||
NULL, /*dxpl_free */
|
||
H5FD_fphdf5_open, /*open */
|
||
H5FD_fphdf5_close, /*close */
|
||
NULL, /*cmp */
|
||
H5FD_fphdf5_query, /*query */
|
||
NULL, /*alloc */
|
||
NULL, /*free */
|
||
H5FD_fphdf5_get_eoa, /*get_eoa */
|
||
H5FD_fphdf5_set_eoa, /*set_eoa */
|
||
H5FD_fphdf5_get_eof, /*get_eof */
|
||
H5FD_fphdf5_get_handle, /*get_handle */
|
||
H5FD_fphdf5_read, /*read */
|
||
H5FD_fphdf5_write, /*write */
|
||
H5FD_fphdf5_flush, /*flush */
|
||
NULL, /*lock */
|
||
NULL, /*unlock */
|
||
H5FD_FLMAP_SINGLE /*fl_map */
|
||
};
|
||
|
||
/* Interface initialization */
|
||
#define INTERFACE_INIT H5FD_fphdf5_init
|
||
static int interface_initialize_g = 0;
|
||
|
||
/*
|
||
* The view is set to this value
|
||
*/
|
||
static char H5FD_mpio_native[] = "native";
|
||
|
||
/* ======== Temporary, Local data transfer properties ======== */
|
||
/*
|
||
* Definitions for memory MPI type property
|
||
*/
|
||
#define H5FD_FPHDF5_XFER_MEM_MPI_TYPE_NAME "H5FD_fphdf5_mem_mpi_type"
|
||
#define H5FD_FPHDF5_XFER_MEM_MPI_TYPE_SIZE sizeof(MPI_Datatype)
|
||
|
||
/*
|
||
* Definitions for file MPI type property
|
||
*/
|
||
#define H5FD_FPHDF5_XFER_FILE_MPI_TYPE_NAME "H5FD_fphdf5_file_mpi_type"
|
||
#define H5FD_FPHDF5_XFER_FILE_MPI_TYPE_SIZE sizeof(MPI_Datatype)
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5FD_fphdf5_init
|
||
* Purpose: Initialize this driver by registering the driver with the
|
||
* library.
|
||
* Return: Success: The driver ID for the FPHDF5 driver.
|
||
* Failure: Doesn't fail.
|
||
* Programmer: Bill Wendling
|
||
* 30. January 2003
|
||
* Modifications:
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
hid_t
|
||
H5FD_fphdf5_init(void)
|
||
{
|
||
hid_t ret_value;
|
||
|
||
FUNC_ENTER_NOAPI(H5FD_fphdf5_init, FAIL)
|
||
|
||
if (H5Iget_type(H5FD_FPHDF5_g) != H5I_VFL)
|
||
H5FD_FPHDF5_g = H5FDregister(&H5FD_fphdf5_g);
|
||
|
||
/* Set return value */
|
||
ret_value = H5FD_FPHDF5_g;
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5Pset_fapl_fphdf5
|
||
* Purpose: Store the user supplied MPIO communicator COMM and INFO
|
||
* in the file access property list FAPL_ID which can then
|
||
* be used to create and/or open the file. This function is
|
||
* available only in the parallel HDF5 library and is not
|
||
* collective.
|
||
*
|
||
* COMM is the MPI communicator to be used for file open as
|
||
* defined in MPI_FILE_OPEN of MPI-2. This function does not
|
||
* make a duplicated communicator. Any modification to COMM
|
||
* after this function call returns may have an indeterminate
|
||
* effect on the access property list. Users should not
|
||
* modify the communicator while it is defined in a property
|
||
* list.
|
||
*
|
||
* INFO is the MPI info object to be used for file open as
|
||
* defined in MPI_FILE_OPEN of MPI-2. This function does not
|
||
* make a duplicated info. Any modification to info after
|
||
* this function call returns may have an indeterminate effect
|
||
* on the access property list. Users should not modify the
|
||
* info while it is defined in a property list.
|
||
* Return: Success: SUCCEED
|
||
* Failure: FAIL
|
||
* Programmer: Bill Wendling
|
||
* 30. January 2003
|
||
* Modifications:
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5Pset_fapl_fphdf5(hid_t fapl_id, MPI_Comm comm, MPI_Comm barrier_comm,
|
||
MPI_Info info, unsigned sap_rank)
|
||
{
|
||
H5FD_fphdf5_fapl_t fa;
|
||
H5P_genplist_t *plist;
|
||
int mrc, comm_size;
|
||
herr_t ret_value;
|
||
|
||
FUNC_ENTER_API(H5Pset_fapl_fphdf5, FAIL)
|
||
H5TRACE5("e","iMcMcMiIu",fapl_id,comm,barrier_comm,info,sap_rank);
|
||
|
||
if (fapl_id == H5P_DEFAULT)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "can't set values in default property list")
|
||
|
||
/* Check arguments */
|
||
if ((plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS)) == NULL)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a file access list")
|
||
|
||
if ((mrc = MPI_Comm_size(comm, &comm_size)) != MPI_SUCCESS)
|
||
HMPI_GOTO_ERROR(FAIL, "MPI_Comm_size failed", mrc)
|
||
|
||
/* Initialize driver specific properties */
|
||
fa.comm = comm;
|
||
fa.barrier_comm = barrier_comm;
|
||
fa.info = info;
|
||
fa.sap_rank = sap_rank;
|
||
fa.capt_rank = (sap_rank + 1) % comm_size;
|
||
|
||
ret_value = H5P_set_driver(plist, H5FD_FPHDF5, &fa);
|
||
|
||
done:
|
||
FUNC_LEAVE_API(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5Pget_fapl_fphdf5
|
||
* Purpose: If the file access property list is set to the
|
||
* H5FD_FPHDF5 driver then this function returns the MPI
|
||
* communicator and information through the COMM and INFO
|
||
* pointers.
|
||
* Return: Success: SUCCEED with the communicator and information
|
||
* returned through the COMM and INFO arguments
|
||
* if non-null. Neither piece of information is
|
||
* copied and they are therefore valid only
|
||
* until the file access property list is
|
||
* modified or closed.
|
||
* Failure: FAIL
|
||
* Programmer: Bill Wendling
|
||
* 30. January 2003
|
||
* Modifications:
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5Pget_fapl_fphdf5(hid_t fapl_id, MPI_Comm *comm, MPI_Comm *barrier_comm,
|
||
MPI_Info *info, unsigned *sap_rank, unsigned *capt_rank)
|
||
{
|
||
H5FD_fphdf5_fapl_t *fa;
|
||
H5P_genplist_t *plist;
|
||
herr_t ret_value = SUCCEED;
|
||
|
||
FUNC_ENTER_API(H5Pget_fapl_fphdf5, FAIL)
|
||
H5TRACE6("e","i*Mc*Mc*Mi*Iu*Iu",fapl_id,comm,barrier_comm,info,sap_rank,
|
||
capt_rank);
|
||
|
||
if ((plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS)) == NULL)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a file access list")
|
||
|
||
if (H5P_get_driver(plist) != H5FD_FPHDF5)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "incorrect VFL driver")
|
||
|
||
if ((fa = H5P_get_driver_info(plist)) == NULL)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "bad VFL driver info")
|
||
|
||
if (comm)
|
||
*comm = fa->comm;
|
||
|
||
if (barrier_comm)
|
||
*barrier_comm = fa->barrier_comm;
|
||
|
||
if (info)
|
||
*info = fa->info;
|
||
|
||
if (sap_rank)
|
||
*sap_rank = fa->sap_rank;
|
||
|
||
if (capt_rank)
|
||
*capt_rank = fa->capt_rank;
|
||
|
||
done:
|
||
FUNC_LEAVE_API(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5FD_fphdf5_communicator
|
||
* Purpose: Returns the MPI communicator for the file.
|
||
* Return: Success: The communicator
|
||
* Failure: NULL
|
||
* Programmer: Bill Wendling
|
||
* 30. January 2003
|
||
* Modifications:
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
MPI_Comm
|
||
H5FD_fphdf5_communicator(H5FD_t *_file)
|
||
{
|
||
H5FD_fphdf5_t *file = (H5FD_fphdf5_t*)_file;
|
||
MPI_Comm ret_value;
|
||
|
||
FUNC_ENTER_NOAPI(H5FD_fphdf5_communicator, MPI_COMM_NULL)
|
||
|
||
/* check args */
|
||
assert(file);
|
||
assert(file->pub.driver_id == H5FD_FPHDF5);
|
||
|
||
/* Set return value */
|
||
ret_value = file->comm;
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5FD_fphdf5_barrier_communicator
|
||
* Purpose: Returns the MPI communicator for the file that can be
|
||
* used in an MPI_Barrier() statement for the client
|
||
* processes.
|
||
* Return: Success: The barrier communicator
|
||
* Failure: NULL
|
||
* Programmer: Bill Wendling
|
||
* 10. February 2003
|
||
* Modifications:
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
MPI_Comm
|
||
H5FD_fphdf5_barrier_communicator(H5FD_t *_file)
|
||
{
|
||
H5FD_fphdf5_t *file = (H5FD_fphdf5_t*)_file;
|
||
MPI_Comm ret_value;
|
||
|
||
FUNC_ENTER_NOAPI(H5FD_fphdf5_communicator, MPI_COMM_NULL)
|
||
|
||
/* check args */
|
||
assert(file);
|
||
assert(file->pub.driver_id == H5FD_FPHDF5);
|
||
|
||
/* Set return value */
|
||
ret_value = file->barrier_comm;
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5FD_fphdf5_mpi_rank
|
||
* Purpose: Returns the MPI rank for a process
|
||
* Return: Success: MPI rank
|
||
* Failure: Doesn't fail
|
||
* Programmer: Bill Wendling
|
||
* 30. January 2003
|
||
* Modifications:
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
int
|
||
H5FD_fphdf5_mpi_rank(H5FD_t *_file)
|
||
{
|
||
H5FD_fphdf5_t *file = (H5FD_fphdf5_t*)_file;
|
||
int ret_value;
|
||
|
||
FUNC_ENTER_NOAPI(H5FD_fphdf5_mpi_rank, FAIL)
|
||
|
||
/* check args */
|
||
assert(file);
|
||
assert(file->pub.driver_id == H5FD_FPHDF5);
|
||
|
||
/* Set return value */
|
||
ret_value = file->mpi_rank;
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5FD_fphdf5_mpi_size
|
||
* Purpose: Returns the number of MPI processes
|
||
* Return: Success: Number of MPI processes
|
||
* Failure: Doesn't fail
|
||
* Programmer: Bill Wendling
|
||
* 30. January 2003
|
||
* Modifications:
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
int
|
||
H5FD_fphdf5_mpi_size(H5FD_t *_file)
|
||
{
|
||
H5FD_fphdf5_t *file = (H5FD_fphdf5_t*)_file;
|
||
int ret_value;
|
||
|
||
FUNC_ENTER_NOAPI(H5FD_fphdf5_mpi_size, FAIL)
|
||
|
||
/* check args */
|
||
assert(file);
|
||
assert(file->pub.driver_id == H5FD_FPHDF5);
|
||
|
||
/* Set return value */
|
||
ret_value = file->mpi_size;
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5FD_fphdf5_file_id
|
||
* Purpose: Returns the file ID for the file.
|
||
* Return: Success: File ID
|
||
* Failure: Doesn't fail
|
||
* Programmer: Bill Wendling
|
||
* 19. February 2003
|
||
* Modifications:
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
unsigned
|
||
H5FD_fphdf5_file_id(H5FD_t *_file)
|
||
{
|
||
H5FD_fphdf5_t *file = (H5FD_fphdf5_t*)_file;
|
||
unsigned ret_value;
|
||
|
||
FUNC_ENTER_NOAPI(H5FD_fphdf5_file_id, 0)
|
||
|
||
/* check args */
|
||
assert(file);
|
||
assert(file->pub.driver_id == H5FD_FPHDF5);
|
||
|
||
/* Set return value */
|
||
ret_value = file->file_id;
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5FD_fphdf5_is_sap
|
||
* Purpose: Asks the question "Is this process the SAP?".
|
||
* Return: Success: Non-zero if it is, 0 otherwise
|
||
* Failure: Doesn't fails
|
||
* Programmer: Bill Wendling
|
||
* 19. February 2003
|
||
* Modifications:
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
hbool_t
|
||
H5FD_fphdf5_is_sap(H5FD_t *_file)
|
||
{
|
||
H5FD_fphdf5_t *file = (H5FD_fphdf5_t*)_file;
|
||
hbool_t ret_value = FALSE;
|
||
|
||
FUNC_ENTER_NOAPI(H5FD_fphdf5_is_sap, FALSE)
|
||
|
||
/* check args */
|
||
assert(file);
|
||
assert(file->pub.driver_id == H5FD_FPHDF5);
|
||
|
||
/* Set return value */
|
||
ret_value = ((unsigned)file->mpi_rank == H5FP_sap_rank);
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5FD_fphdf5_is_captain
|
||
* Purpose: Asks the question "Is this process the captain?".
|
||
* Return: Success: Non-zero if it is, 0 otherwise
|
||
* Failure: Doesn't fails
|
||
* Programmer: Bill Wendling
|
||
* 19. February 2003
|
||
* Modifications:
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
hbool_t
|
||
H5FD_fphdf5_is_captain(H5FD_t *_file)
|
||
{
|
||
H5FD_fphdf5_t *file = (H5FD_fphdf5_t*)_file;
|
||
hbool_t ret_value = FALSE;
|
||
|
||
FUNC_ENTER_NOAPI(H5FD_fphdf5_is_sap, FALSE)
|
||
|
||
/* check args */
|
||
assert(file);
|
||
assert(file->pub.driver_id == H5FD_FPHDF5);
|
||
|
||
/* Set return value */
|
||
ret_value = ((unsigned)file->mpi_rank == H5FP_capt_rank);
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5FD_is_fphdf5_driver
|
||
* Purpose: Asks the question "Is this an FPHDF5 driver?".
|
||
* Return: Success: Non-zero if it is, 0 otherwise
|
||
* Failure: Doesn't fails
|
||
* Programmer: Bill Wendling
|
||
* 26. February 2003
|
||
* Modifications:
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
hbool_t
|
||
H5FD_is_fphdf5_driver(H5FD_t *_file)
|
||
{
|
||
H5FD_fphdf5_t *file = (H5FD_fphdf5_t*)_file;
|
||
hbool_t ret_value = FALSE;
|
||
|
||
FUNC_ENTER_NOAPI(H5FD_is_fphdf5_driver, FALSE)
|
||
|
||
/* check args */
|
||
assert(file);
|
||
|
||
/* Set return value */
|
||
ret_value = file->pub.driver_id == H5FD_FPHDF5;
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5FD_fphdf5_setup
|
||
* Purpose: Set the buffer type BTYPE, file type FTYPE for a data
|
||
* transfer. Also request an MPI type transfer.
|
||
* Return: Success: SUCCEED
|
||
* Failure: FAIL
|
||
* Programmer: Bill Wendling
|
||
* 30. January 2003
|
||
* Modifications:
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5FD_fphdf5_setup(hid_t dxpl_id, MPI_Datatype btype,
|
||
MPI_Datatype ftype)
|
||
{
|
||
H5P_genplist_t *plist;
|
||
herr_t ret_value = SUCCEED;
|
||
|
||
FUNC_ENTER_NOAPI(H5FD_fphdf5_setup, FAIL)
|
||
|
||
/* Check arguments */
|
||
if ((plist = H5P_object_verify(dxpl_id, H5P_DATASET_XFER)) == NULL)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a dataset transfer list")
|
||
|
||
/* Set buffer MPI type */
|
||
if (H5P_insert(plist, H5FD_FPHDF5_XFER_MEM_MPI_TYPE_NAME,
|
||
H5FD_FPHDF5_XFER_MEM_MPI_TYPE_SIZE, &btype,
|
||
NULL, NULL, NULL, NULL, NULL) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't insert MPI-I/O property")
|
||
|
||
/* Set file MPI type */
|
||
if (H5P_insert(plist, H5FD_FPHDF5_XFER_FILE_MPI_TYPE_NAME,
|
||
H5FD_FPHDF5_XFER_FILE_MPI_TYPE_SIZE, &ftype,
|
||
NULL, NULL, NULL, NULL, NULL) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't insert MPI-I/O property")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5FD_fphdf5_teardown
|
||
* Purpose: Remove the temporary MPI-I/O properties from dxpl.
|
||
* Return: Success: SUCCEED
|
||
* Failure: FAIL
|
||
* Programmer: Bill Wendling
|
||
* 30. January 2003
|
||
* Modifications:
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5FD_fphdf5_teardown(hid_t dxpl_id)
|
||
{
|
||
H5P_genplist_t *plist;
|
||
herr_t ret_value = SUCCEED;
|
||
|
||
FUNC_ENTER_NOAPI(H5FD_fphdf5_teardown, FAIL)
|
||
|
||
/* Check arguments */
|
||
if ((plist = H5P_object_verify(dxpl_id, H5P_DATASET_XFER)) == NULL)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a dataset transfer list")
|
||
|
||
/* Remove buffer MPI type */
|
||
if (H5P_remove(dxpl_id, plist, H5FD_FPHDF5_XFER_MEM_MPI_TYPE_NAME) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTDELETE, FAIL, "can't remove MPI-I/O property")
|
||
|
||
/* Remove file MPI type */
|
||
if (H5P_remove(dxpl_id, plist, H5FD_FPHDF5_XFER_FILE_MPI_TYPE_NAME) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTDELETE, FAIL, "can't remove MPI-I/O property")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5Pset_dxpl_fphdf5
|
||
* Purpose: Set the data transfer property list DXPL_ID to use
|
||
* transfer mode XFER_MODE. The property list can then be
|
||
* used to control the I/O transfer mode during data I/O
|
||
* operations. The valid transfer modes are:
|
||
*
|
||
* H5FD_MPIO_INDEPENDENT:
|
||
* Use independent I/O access (the default).
|
||
*
|
||
* H5FD_MPIO_COLLECTIVE:
|
||
* Use collective I/O access.
|
||
* Return: Success: SUCCEED
|
||
* Failure: FAIL
|
||
* Programmer: Bill Wendling
|
||
* 10. February 2003
|
||
* Modifications:
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5Pset_dxpl_fphdf5(hid_t dxpl_id, H5FD_mpio_xfer_t xfer_mode)
|
||
{
|
||
H5P_genplist_t *plist;
|
||
herr_t ret_value = SUCCEED;
|
||
|
||
FUNC_ENTER_API(H5Pset_dxpl_fphdf5, FAIL)
|
||
H5TRACE2("e","iDt",dxpl_id,xfer_mode);
|
||
|
||
if (dxpl_id == H5P_DEFAULT)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "can't set values in default property list")
|
||
|
||
/* Check arguments */
|
||
if ((plist = H5P_object_verify(dxpl_id, H5P_DATASET_XFER)) == NULL)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a dxpl")
|
||
|
||
if (xfer_mode != H5FD_MPIO_INDEPENDENT && xfer_mode != H5FD_MPIO_COLLECTIVE)
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "incorrect xfer_mode")
|
||
|
||
/* Set the transfer mode */
|
||
if (H5P_set(plist, H5D_XFER_IO_XFER_MODE_NAME, &xfer_mode) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set value")
|
||
|
||
/* Initialize driver-specific properties */
|
||
ret_value = H5P_set_driver(plist, H5FD_FPHDF5, NULL);
|
||
|
||
done:
|
||
FUNC_LEAVE_API(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5Pget_dxpl_fphdf5
|
||
* Purpose: Queries the transfer mode current set in the data
|
||
* transfer property list DXPL_ID. This is not collective.
|
||
* Return: Success: SUCCEED - with the transfer mode returned
|
||
* through the XFER_MODE argument if
|
||
* it is non-null.
|
||
* Failure: FAIL
|
||
* Programmer: Bill Wendling
|
||
* 10. February 2003
|
||
* Modifications:
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5Pget_dxpl_fphdf5(hid_t dxpl_id, H5FD_mpio_xfer_t *xfer_mode)
|
||
{
|
||
H5P_genplist_t *plist;
|
||
herr_t ret_value = SUCCEED;
|
||
|
||
FUNC_ENTER_API(H5Pget_dxpl_fphdf5, FAIL)
|
||
H5TRACE2("e","i*Dt",dxpl_id,xfer_mode);
|
||
|
||
if ((plist = H5P_object_verify(dxpl_id, H5P_DATASET_XFER)) == NULL)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a dxpl")
|
||
|
||
if (H5P_get_driver(plist) != H5FD_FPHDF5)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "incorrect VFL driver")
|
||
|
||
/* Get the transfer mode */
|
||
if (xfer_mode)
|
||
if (H5P_get(plist, H5D_XFER_IO_XFER_MODE_NAME, xfer_mode) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to get value")
|
||
|
||
done:
|
||
FUNC_LEAVE_API(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5FD_fphdf5_fapl_get
|
||
* Purpose: Returns a file access property list which could be used
|
||
* to create another file the same as this one.
|
||
* Return: Success: Ptr to new file access property list with all
|
||
* fields copied from the file pointer.
|
||
* Failure: NULL
|
||
* Programmer: Bill Wendling
|
||
* 07. February 2003
|
||
* Modifications:
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static void *
|
||
H5FD_fphdf5_fapl_get(H5FD_t *_file)
|
||
{
|
||
H5FD_fphdf5_t *file = (H5FD_fphdf5_t*)_file;
|
||
H5FD_fphdf5_fapl_t *fa = NULL;
|
||
void *ret_value;
|
||
|
||
FUNC_ENTER_NOAPI(H5FD_fphdf5_fapl_get, NULL)
|
||
|
||
/* check args */
|
||
assert(file);
|
||
assert(file->pub.driver_id == H5FD_FPHDF5);
|
||
|
||
if ((fa = H5MM_calloc(sizeof(H5FD_fphdf5_fapl_t))) == NULL)
|
||
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
|
||
|
||
/* These should both be copied. --rpm, 1999-08-13 */
|
||
fa->comm = file->comm;
|
||
fa->barrier_comm = file->barrier_comm;
|
||
fa->info = file->info;
|
||
|
||
/* Set return value */
|
||
ret_value = fa;
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5FD_fphdf5_open
|
||
* Purpose: Opens a file with name NAME. The FLAGS are a bit field with
|
||
* purpose similar to the second argument of open(2) and
|
||
* which are defined in H5Fpublic.h. The file access
|
||
* property list FAPL_ID contains the properties driver
|
||
* properties and MAXADDR is the largest address which this
|
||
* file will be expected to access. This is collective.
|
||
* Return: Success: A new file pointer.
|
||
* Failure: NULL
|
||
* Programmer: Bill Wendling
|
||
* 05. February 2003
|
||
* Modifications:
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static H5FD_t *
|
||
H5FD_fphdf5_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr)
|
||
{
|
||
H5FD_fphdf5_t *file = NULL;
|
||
MPI_File fh;
|
||
int mpi_amode;
|
||
int mpi_rank;
|
||
int mpi_size;
|
||
int mrc;
|
||
MPI_Offset size;
|
||
H5FD_fphdf5_fapl_t _fa;
|
||
const H5FD_fphdf5_fapl_t *fa = NULL;
|
||
H5P_genplist_t *plist;
|
||
unsigned long feature_flags;
|
||
hsize_t meta_block_size = 0;
|
||
hsize_t sdata_block_size = 0;
|
||
hsize_t threshold;
|
||
hsize_t alignment;
|
||
unsigned file_id;
|
||
unsigned req_id = 0;
|
||
H5FD_t *ret_value = NULL;
|
||
|
||
/* Flag to indicate that the file was successfully opened */
|
||
unsigned file_opened = FALSE;
|
||
|
||
FUNC_ENTER_NOAPI(H5FD_fphdf5_open, NULL)
|
||
|
||
/* check args */
|
||
assert(name);
|
||
|
||
/* Obtain a pointer to fphdf5-specific file access properties */
|
||
if ((plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS)) == NULL)
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list")
|
||
|
||
if (fapl_id == H5P_FILE_ACCESS_DEFAULT || H5P_get_driver(plist) != H5FD_FPHDF5) {
|
||
_fa.comm = MPI_COMM_SELF; /*default*/
|
||
_fa.barrier_comm = MPI_COMM_SELF; /*default*/
|
||
_fa.info = MPI_INFO_NULL; /*default*/
|
||
fa = &_fa;
|
||
} else {
|
||
fa = H5P_get_driver_info(plist);
|
||
assert(fa);
|
||
}
|
||
|
||
/*
|
||
* Convert HDF5 flags to MPI-IO flags. Some combinations are illegal;
|
||
* let MPI-IO figure it out
|
||
*/
|
||
mpi_amode = (flags & H5F_ACC_RDWR) ? MPI_MODE_RDWR : MPI_MODE_RDONLY;
|
||
|
||
if (flags & H5F_ACC_CREAT) mpi_amode |= MPI_MODE_CREATE;
|
||
if (flags & H5F_ACC_EXCL) mpi_amode |= MPI_MODE_EXCL;
|
||
|
||
/* OKAY: CAST DISCARDS CONST */
|
||
if ((mrc = MPI_File_open(H5FP_SAP_BARRIER_COMM, (char *)name, mpi_amode,
|
||
fa->info, &fh)) != MPI_SUCCESS)
|
||
HMPI_GOTO_ERROR(NULL, "MPI_File_open failed", mrc)
|
||
|
||
file_opened = TRUE;
|
||
|
||
if (H5P_get(plist, H5F_ACS_META_BLOCK_SIZE_NAME, &meta_block_size) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get meta data block size")
|
||
|
||
if (H5P_get(plist, H5F_ACS_SDATA_BLOCK_SIZE_NAME, &sdata_block_size) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get 'small data' block size")
|
||
|
||
if (H5P_get(plist, H5F_ACS_ALIGN_THRHD_NAME, &threshold) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get alignment threshold")
|
||
|
||
if (H5P_get(plist, H5F_ACS_ALIGN_NAME, &alignment) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get alignment")
|
||
|
||
/* Retrieve the VFL driver feature flags */
|
||
H5FD_fphdf5_query(NULL, &feature_flags); /* doesn't fail */
|
||
|
||
/* Inform the SAP that the file was opened */
|
||
if (H5FP_request_open(H5FP_OBJ_FILE, maxaddr, feature_flags,
|
||
meta_block_size, sdata_block_size, threshold,
|
||
alignment, &file_id, &req_id) == FAIL)
|
||
HGOTO_ERROR(H5E_FPHDF5, H5E_CANTOPENFILE, NULL, "can't inform SAP of file open")
|
||
|
||
/* Broadcast the file ID */
|
||
if ((mrc = MPI_Bcast(&file_id, 1, MPI_UNSIGNED,
|
||
(int)H5FP_capt_barrier_rank,
|
||
H5FP_SAP_BARRIER_COMM)) != MPI_SUCCESS)
|
||
HMPI_GOTO_ERROR(NULL, "MPI_Bcast failed", mrc)
|
||
|
||
/* Grab the rank of this process */
|
||
if ((mrc = MPI_Comm_rank(H5FP_SAP_COMM, &mpi_rank)) != MPI_SUCCESS)
|
||
HMPI_GOTO_ERROR(NULL, "MPI_Comm_rank failed", mrc)
|
||
|
||
/* The captain rank will get the filesize and broadcast it. */
|
||
if ((unsigned)mpi_rank == H5FP_capt_rank)
|
||
/* Get current file size */
|
||
if ((mrc = MPI_File_get_size(fh, &size)) != MPI_SUCCESS)
|
||
HMPI_GOTO_ERROR(NULL, "MPI_File_get_size failed", mrc)
|
||
|
||
/* Broadcast file size */
|
||
if ((mrc = MPI_Bcast(&size, sizeof(MPI_Offset), MPI_BYTE,
|
||
(int)H5FP_capt_barrier_rank,
|
||
H5FP_SAP_BARRIER_COMM)) != MPI_SUCCESS)
|
||
HMPI_GOTO_ERROR(NULL, "MPI_Bcast failed", mrc)
|
||
|
||
/* Only if size > 0, truncate the file - if requested */
|
||
if (size && (flags & H5F_ACC_TRUNC)) {
|
||
if ((mrc = MPI_File_set_size(fh, (MPI_Offset)0)) != MPI_SUCCESS)
|
||
HMPI_GOTO_ERROR(NULL, "MPI_File_set_size (file truncation) failed", mrc)
|
||
|
||
/* Don't let any proc return until all have truncated the file. */
|
||
if ((mrc = MPI_Barrier(H5FP_SAP_BARRIER_COMM)) != MPI_SUCCESS)
|
||
HMPI_GOTO_ERROR(NULL, "MPI_Barrier failed", mrc)
|
||
|
||
size = 0;
|
||
}
|
||
|
||
/* Grab the size of the communicator */
|
||
if ((mrc = MPI_Comm_size(H5FP_SAP_COMM, &mpi_size)) != MPI_SUCCESS)
|
||
HMPI_GOTO_ERROR(NULL, "MPI_Comm_size failed", mrc)
|
||
|
||
/* Build the return value and initialize it */
|
||
if ((file = H5MM_calloc(sizeof(H5FD_fphdf5_t))) == NULL)
|
||
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
|
||
|
||
file->file_id = file_id;
|
||
file->f = fh;
|
||
file->comm = fa->comm;
|
||
file->info = fa->info;
|
||
file->mpi_rank = mpi_rank;
|
||
file->mpi_size = mpi_size;
|
||
file->eof = H5FD_fphdf5_MPIOff_to_haddr(size);
|
||
|
||
/* Set return value */
|
||
ret_value = (H5FD_t *)file;
|
||
|
||
done:
|
||
if (!ret_value && file_opened)
|
||
MPI_File_close(&fh);
|
||
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5FD_fphdf5_close
|
||
* Purpose: Closes a file. This is collective.
|
||
* Return: Success: SUCCEED
|
||
* Failure: FAIL
|
||
* Programmer: Bill Wendling
|
||
* 07. February 2003
|
||
* Modifications:
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5FD_fphdf5_close(H5FD_t *_file)
|
||
{
|
||
H5FD_fphdf5_t *file = (H5FD_fphdf5_t *)_file;
|
||
unsigned req_id = 0;
|
||
H5FP_status_t status = H5FP_STATUS_OK;
|
||
int mrc;
|
||
herr_t ret_value = SUCCEED;
|
||
|
||
FUNC_ENTER_NOAPI(H5FD_fphdf5_close, FAIL)
|
||
|
||
/* check args */
|
||
assert(file);
|
||
assert(file->pub.driver_id == H5FD_FPHDF5);
|
||
|
||
/* Tell the SAP that we're closing the file... */
|
||
if (H5FP_request_close(_file, file->file_id, &req_id, &status) == FAIL)
|
||
HGOTO_ERROR(H5E_IO, H5E_CANTCLOSEFILE, FAIL, "can't inform SAP of file close")
|
||
|
||
/* MPI_File_close sets argument to MPI_FILE_NULL */
|
||
if ((mrc = MPI_File_close(&file->f)) != MPI_SUCCESS)
|
||
HMPI_GOTO_ERROR(FAIL, "MPI_File_close failed", mrc)
|
||
|
||
/* Clean up other stuff */
|
||
H5MM_xfree(file);
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5FD_fphdf5_query
|
||
* Purpose: Set the flags that this VFL driver is capable of
|
||
* supporting. (listed in H5FDpublic.h)
|
||
* Return: Success: SUCCEED
|
||
* Failure: Doesn't fail.
|
||
* Programmer: Bill Wendling
|
||
* 07. February 2003
|
||
* Modifications:
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5FD_fphdf5_query(const H5FD_t UNUSED *_file, unsigned long *flags /* out */)
|
||
{
|
||
herr_t ret_value = SUCCEED;
|
||
|
||
FUNC_ENTER_NOAPI(H5FD_fphdf5_query, FAIL)
|
||
|
||
/* Set the VFL feature flags that this driver supports */
|
||
if (flags) {
|
||
*flags = 0;
|
||
|
||
/* OK to aggregate metadata allocations */
|
||
*flags |= H5FD_FEAT_AGGREGATE_METADATA;
|
||
|
||
/*
|
||
* Distinguish between updating the metadata accumulator on
|
||
* writes and reads. This is particularly (perhaps only, even)
|
||
* important for MPI-I/O where we guarantee that writes are
|
||
* collective, but reads may not be. If we were to allow the
|
||
* metadata accumulator to be written during a read operation,
|
||
* the application would hang.
|
||
*/
|
||
|
||
#if 0
|
||
/*
|
||
* FIXME: For now, having metadata accumulate causes problems for
|
||
* the SAP when it goes to allocate data (oddly enough, an
|
||
* allocation can result in a call to H5FD_free...which can
|
||
* result in a call to H5FD_write...which needs a data xfer
|
||
* property list...but only when metadata accumulation is turned
|
||
* on...go figure). Turn it off for now. -- BW 02/19/2003
|
||
*/
|
||
|
||
/* OK to accumulate metadata for faster writes */
|
||
*flags |= H5FD_FEAT_ACCUMULATE_METADATA_WRITE;
|
||
#endif /* 0 */
|
||
|
||
/* OK to aggregate "small" raw data allocations */
|
||
*flags |= H5FD_FEAT_AGGREGATE_SMALLDATA;
|
||
}
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5FD_fphdf5_get_eoa
|
||
* Purpose: Gets the end-of-address marker for the file. The EOA
|
||
* marker is the first address past the last byte allocated
|
||
* in the format address space.
|
||
* Return: Success: The end-of-address marker.
|
||
* Failure: HADDR_UNDEF
|
||
* Programmer: Bill Wendling
|
||
* 07. February 2003
|
||
* Modifications:
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static haddr_t
|
||
H5FD_fphdf5_get_eoa(H5FD_t *_file)
|
||
{
|
||
H5FD_fphdf5_t *file = (H5FD_fphdf5_t *)_file;
|
||
unsigned req_id = 0;
|
||
H5FP_status_t status = H5FP_STATUS_OK;
|
||
haddr_t ret_value;
|
||
|
||
FUNC_ENTER_NOAPI(H5FD_fphdf5_get_eoa, HADDR_UNDEF)
|
||
|
||
/* check args */
|
||
assert(file);
|
||
assert(file->pub.driver_id == H5FD_FPHDF5);
|
||
|
||
/* The SAP's eoa field is correct */
|
||
if (!H5FD_fphdf5_is_sap(_file))
|
||
/* Retrieve the EOA information */
|
||
if (H5FP_request_get_eoa(_file, &file->eoa, &req_id, &status))
|
||
HGOTO_ERROR(H5E_FPHDF5, H5E_CANTRECV, HADDR_UNDEF, "can't retrieve eoa information")
|
||
|
||
/* Set return value */
|
||
ret_value = file->eoa;
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5FD_fphdf5_set_eoa
|
||
* Purpose: Set the end-of-address marker for the file. This function
|
||
* is called shortly after an existing HDF5 file is opened
|
||
* in order to tell the driver where the end of the HDF5
|
||
* data is located.
|
||
* Return: Success: SUCCEED
|
||
* Failure: FAIL
|
||
* Programmer: Bill Wendling
|
||
* 06. February 2003
|
||
* Modifications:
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5FD_fphdf5_set_eoa(H5FD_t *_file, haddr_t addr)
|
||
{
|
||
H5FD_fphdf5_t *file = (H5FD_fphdf5_t *)_file;
|
||
unsigned req_id = 0;
|
||
H5FP_status_t status = H5FP_STATUS_OK;
|
||
herr_t ret_value = SUCCEED;
|
||
|
||
FUNC_ENTER_NOAPI(H5FD_fphdf5_set_eoa, FAIL)
|
||
|
||
/* check args */
|
||
assert(file);
|
||
assert(file->pub.driver_id == H5FD_FPHDF5);
|
||
|
||
/* The SAP's eoa field is correct */
|
||
if (!H5FD_fphdf5_is_sap(_file))
|
||
/* Retrieve the EOA information */
|
||
if (H5FP_request_set_eoa(_file, addr, &req_id, &status))
|
||
HGOTO_ERROR(H5E_FPHDF5, H5E_CANTRECV, FAIL, "can't retrieve eoa information")
|
||
|
||
file->eoa = addr;
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5FD_fphdf5_get_eof
|
||
* Purpose: Gets the end-of-file marker for the file. The EOF marker
|
||
* is the real size of the file.
|
||
*
|
||
* The FPHDF5 driver doesn't bother keeping this field updated
|
||
* since that's a relatively expensive operation.
|
||
* Fortunately the library only needs the EOF just after the
|
||
* file is opened in order to determine whether the file is
|
||
* empty, truncated, or okay. Therefore, any MPIO I/O
|
||
* function will set its value to HADDR_UNDEF which is the
|
||
* error return value of this function.
|
||
* Return: Success: The end-of-address marker
|
||
* Failure: HADDR_UNDEF
|
||
* Programmer: Bill Wendling
|
||
* 06. February 2003
|
||
* Modifications:
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static haddr_t
|
||
H5FD_fphdf5_get_eof(H5FD_t *_file)
|
||
{
|
||
H5FD_fphdf5_t *file = (H5FD_fphdf5_t*)_file;
|
||
haddr_t ret_value;
|
||
|
||
FUNC_ENTER_NOAPI(H5FD_fphdf5_get_eof, HADDR_UNDEF)
|
||
|
||
/* check args */
|
||
assert(file);
|
||
assert(file->pub.driver_id == H5FD_FPHDF5);
|
||
|
||
/* Set return value */
|
||
ret_value = file->eof;
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5FD_fphdf5_get_handle
|
||
* Purpose: Returns the file handle of MPIO file driver.
|
||
* Returns: Success: SUCCEED
|
||
* Failure: FAIL
|
||
* Programmer: Bill Wendling
|
||
* 06. February 2003
|
||
* Modifications:
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5FD_fphdf5_get_handle(H5FD_t *_file, hid_t UNUSED fapl, void** file_handle)
|
||
{
|
||
H5FD_fphdf5_t *file = (H5FD_fphdf5_t *)_file;
|
||
herr_t ret_value = SUCCEED;
|
||
|
||
FUNC_ENTER_NOAPI(H5FD_fphdf5_get_handle, FAIL)
|
||
|
||
/* check args */
|
||
assert(file);
|
||
|
||
if (!file_handle)
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file handle not valid")
|
||
|
||
*file_handle = &file->f;
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5FD_fphdf5_read
|
||
* Purpose: Reads SIZE bytes of data from FILE beginning at address
|
||
* ADDR into buffer BUF according to data transfer
|
||
* properties in DXPL_ID using potentially complex file and
|
||
* buffer types to effect the transfer.
|
||
*
|
||
* Reading past the end of the MPI file returns zeros
|
||
* instead of failing. MPI is able to coalesce requests
|
||
* from different processes (collective or independent).
|
||
* Return: Success: SUCCEED - Result is stored in caller-supplied
|
||
* buffer BUF
|
||
* Failure: FAIL - Contents of buffer BUF are undefined
|
||
* Programmer: Bill Wendling
|
||
* 10. February 2003
|
||
* Modifications:
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5FD_fphdf5_read(H5FD_t *_file, H5FD_mem_t mem_type, hid_t dxpl_id,
|
||
haddr_t addr, size_t size, void *buf)
|
||
{
|
||
H5FD_fphdf5_t *file = (H5FD_fphdf5_t*)_file;
|
||
MPI_Offset mpi_off;
|
||
MPI_Status status;
|
||
int mrc;
|
||
MPI_Datatype buf_type;
|
||
int size_i;
|
||
int bytes_read;
|
||
int n;
|
||
unsigned use_view_this_time = 0;
|
||
herr_t ret_value = SUCCEED;
|
||
|
||
FUNC_ENTER_NOAPI(H5FD_fphdf5_read, FAIL)
|
||
|
||
/* check args */
|
||
assert(file);
|
||
assert(file->pub.driver_id == H5FD_FPHDF5);
|
||
assert(buf);
|
||
|
||
/* Make certain we have the correct type of property list */
|
||
assert(H5I_get_type(dxpl_id) == H5I_GENPROP_LST);
|
||
assert(H5P_isa_class(dxpl_id, H5P_DATASET_XFER) == TRUE);
|
||
|
||
/* Portably initialize MPI status variable */
|
||
HDmemset(&status, 0, sizeof(MPI_Status));
|
||
|
||
/* Some numeric conversions */
|
||
if (H5FD_fphdf5_haddr_to_MPIOff(addr, &mpi_off) < 0)
|
||
HGOTO_ERROR(H5E_INTERNAL, H5E_BADRANGE, FAIL, "can't convert from haddr_t to MPI offset")
|
||
|
||
size_i = (int)size;
|
||
|
||
if ((hsize_t)size_i != size)
|
||
HGOTO_ERROR(H5E_INTERNAL, H5E_BADRANGE, FAIL, "can't convert from size_t to int")
|
||
|
||
/* Only look for MPI views for raw data transfers */
|
||
if (mem_type == H5FD_MEM_DRAW) {
|
||
H5P_genplist_t *plist;
|
||
H5FD_mpio_xfer_t xfer_mode; /* I/O tranfer mode */
|
||
|
||
/* Obtain the data transfer properties */
|
||
if ((plist = H5I_object(dxpl_id)) == NULL)
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list")
|
||
|
||
xfer_mode = H5P_peek_unsigned(plist, H5D_XFER_IO_XFER_MODE_NAME);
|
||
|
||
/*
|
||
* Set up for a fancy xfer using complex types, or single byte block.
|
||
* We wouldn't need to rely on the use_view field if MPI semantics
|
||
* allowed us to test that btype == ftype == MPI_BYTE (or even
|
||
* MPI_TYPE_NULL, which could mean "use MPI_BYTE" by convention).
|
||
*/
|
||
if (xfer_mode == H5FD_MPIO_COLLECTIVE) {
|
||
MPI_Datatype file_type;
|
||
|
||
/* Remember that views are used */
|
||
use_view_this_time = TRUE;
|
||
|
||
/* Prepare for a full-blown xfer using btype, ftype, and disp */
|
||
if (H5P_get(plist, H5FD_FPHDF5_XFER_MEM_MPI_TYPE_NAME, &buf_type) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get MPI-I/O type property")
|
||
|
||
if (H5P_get(plist, H5FD_FPHDF5_XFER_FILE_MPI_TYPE_NAME, &file_type) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get MPI-I/O type property")
|
||
|
||
/* Set the file view when we are using MPI derived types */
|
||
if ((mrc = MPI_File_set_view(file->f, mpi_off, MPI_BYTE,
|
||
file_type, H5FD_mpio_native,
|
||
file->info)) != MPI_SUCCESS)
|
||
HMPI_GOTO_ERROR(FAIL, "MPI_File_set_view failed", mrc)
|
||
|
||
/*
|
||
* When using types, use the address as the displacement for
|
||
* MPI_File_set_view and reset the address for the read to zero
|
||
*/
|
||
mpi_off = 0;
|
||
|
||
/* Read the data. */
|
||
if ((mrc = MPI_File_read_at_all(file->f, mpi_off, buf, size_i,
|
||
buf_type, &status)) != MPI_SUCCESS)
|
||
HMPI_GOTO_ERROR(FAIL, "MPI_File_read_at_all failed", mrc)
|
||
} else {
|
||
/*
|
||
* Prepare for a simple xfer of a contiguous block of bytes. The
|
||
* btype, ftype, and disp fields are not used.
|
||
*/
|
||
buf_type = MPI_BYTE;
|
||
|
||
/* Read the data. */
|
||
if ((mrc = MPI_File_read_at(file->f, mpi_off, buf, size_i,
|
||
buf_type, &status)) != MPI_SUCCESS)
|
||
HMPI_GOTO_ERROR(FAIL, "MPI_File_read_at failed", mrc)
|
||
}
|
||
|
||
/*
|
||
* MPI_Get_count incorrectly returns negative count; fake a complete
|
||
* read.
|
||
*/
|
||
bytes_read = size_i;
|
||
|
||
/*
|
||
* Reset the file view when we used MPI derived types
|
||
*/
|
||
if (use_view_this_time)
|
||
if ((mrc = MPI_File_set_view(file->f, (MPI_Offset)0, MPI_BYTE, MPI_BYTE,
|
||
H5FD_mpio_native, file->info)) != MPI_SUCCESS)
|
||
HMPI_GOTO_ERROR(FAIL, "MPI_File_set_view failed", mrc)
|
||
|
||
} else {
|
||
/*
|
||
* This is metadata - we want to try to read it from the SAP
|
||
* first.
|
||
*/
|
||
unsigned req_id = 0;
|
||
H5FP_status_t sap_status = H5FP_STATUS_OK;
|
||
|
||
if (H5FP_request_read_metadata(_file, file->file_id, dxpl_id, mem_type,
|
||
addr, size, (uint8_t**)&buf,
|
||
&bytes_read, &req_id, &sap_status) != SUCCEED) {
|
||
/* FIXME: The read failed, for some reason */
|
||
HDfprintf(stderr, "%s:%d: Metadata cache read failed!\n", FUNC, __LINE__);
|
||
}
|
||
|
||
if (sap_status == H5FP_STATUS_OK) {
|
||
/* WAH-HOO! We've found it! We can leave now */
|
||
} else if (sap_status == H5FP_STATUS_MDATA_NOT_CACHED) {
|
||
/* Metadata isn't cached, so grab it from the file */
|
||
if ((mrc = MPI_File_read_at(file->f, mpi_off, buf, size_i,
|
||
MPI_BYTE, &status)) != MPI_SUCCESS)
|
||
HMPI_GOTO_ERROR(FAIL, "MPI_File_read_at failed", mrc)
|
||
|
||
if ((mrc = MPI_Get_count(&status, MPI_BYTE, &bytes_read)) != MPI_SUCCESS)
|
||
HMPI_GOTO_ERROR(FAIL, "MPI_Get_count failed", mrc)
|
||
} else {
|
||
/* FIXME: something bad happened */
|
||
HDfprintf(stderr, "%s:%d: Metadata cache read failed!\n", FUNC, __LINE__);
|
||
}
|
||
} /* end else */
|
||
|
||
/* Check for read failure */
|
||
if (bytes_read < 0 || bytes_read > size_i)
|
||
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file read failed")
|
||
|
||
/*
|
||
* This gives us zeroes beyond end of physical MPI file. What about
|
||
* reading past logical end of HDF5 file???
|
||
*/
|
||
n = size_i - bytes_read;
|
||
|
||
if (n > 0) {
|
||
if (use_view_this_time)
|
||
/*
|
||
* INCOMPLETE rky 1998-09-18
|
||
* Haven't implemented reading zeros beyond EOF. What to do???
|
||
*/
|
||
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "eof file read failed")
|
||
|
||
memset((char*)buf + bytes_read, 0, (size_t)n);
|
||
}
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5FD_fphdf5_write
|
||
* Purpose: Writes SIZE bytes of data to FILE beginning at address
|
||
* ADDR from buffer BUF according to data transfer
|
||
* properties in DXPL_ID using potentially complex file and
|
||
* buffer types to effect the transfer.
|
||
*
|
||
* MPI is able to coalesce requests from different processes
|
||
* (collective and independent).
|
||
* Return: Success: SUCCEED - USE_TYPES and OLD_USE_TYPES in the
|
||
* access params are altered.
|
||
* Failure: FAIL - USE_TYPES and OLD_USE_TYPES in the
|
||
* access params may be altered.
|
||
* Programmer: Bill Wendling
|
||
* 10. February 2003
|
||
* Modifications:
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5FD_fphdf5_write(H5FD_t *_file, H5FD_mem_t mem_type, hid_t dxpl_id,
|
||
haddr_t addr, size_t size, const void *buf)
|
||
{
|
||
H5FD_fphdf5_t *file = (H5FD_fphdf5_t*)_file;
|
||
int size_i;
|
||
unsigned dumping = 0;
|
||
H5P_genplist_t *plist;
|
||
herr_t ret_value;
|
||
|
||
FUNC_ENTER_NOAPI(H5FD_fphdf5_write, FAIL)
|
||
|
||
/* check args */
|
||
assert(file);
|
||
assert(file->pub.driver_id == H5FD_FPHDF5);
|
||
assert(buf);
|
||
|
||
/* Make certain we have the correct type of property list */
|
||
assert(H5I_get_type(dxpl_id) == H5I_GENPROP_LST);
|
||
assert(H5P_isa_class(dxpl_id, H5P_DATASET_XFER) == TRUE);
|
||
|
||
/* some numeric conversions */
|
||
size_i = (int)size;
|
||
if ((hsize_t)size_i != size)
|
||
HGOTO_ERROR(H5E_INTERNAL, H5E_BADRANGE, FAIL, "can't convert from size to size_i")
|
||
|
||
/* Obtain the data transfer properties */
|
||
if ((plist = H5I_object(dxpl_id)) == NULL)
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list")
|
||
|
||
if (H5P_exist_plist(plist, H5FD_FPHDF5_XFER_DUMPING_METADATA) > 0)
|
||
if (H5P_get(plist, H5FD_FPHDF5_XFER_DUMPING_METADATA, &dumping) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get MPI-I/O type property")
|
||
|
||
/*
|
||
* If metadata, write to the metadata cache but only if we're not
|
||
* dumping the data from the SAP...
|
||
*/
|
||
if (mem_type != H5FD_MEM_DRAW && !dumping) {
|
||
unsigned req_id = 0;
|
||
H5FP_status_t sap_status = H5FP_STATUS_OK;
|
||
|
||
if (H5FP_request_write_metadata(_file, file->file_id, dxpl_id, mem_type,
|
||
addr, size_i, buf, &req_id,
|
||
&sap_status) != SUCCEED) {
|
||
/* FIXME: Couldn't write metadata. This is bad... */
|
||
HDfprintf(stderr, "%s:%d: Couldn't write metadata to SAP (%d)\n",
|
||
FUNC, __LINE__, sap_status);
|
||
}
|
||
|
||
switch (sap_status) {
|
||
case H5FP_STATUS_OK:
|
||
/* WAH-HOO! We've written it! We can leave now */
|
||
/* Forget the EOF value (see H5FD_fphdf5_get_eof()) */
|
||
file->eof = HADDR_UNDEF;
|
||
HGOTO_DONE(SUCCEED)
|
||
case H5FP_STATUS_FILE_CLOSING:
|
||
HGOTO_DONE(SUCCEED)
|
||
case H5FP_STATUS_DUMPING_FAILED:
|
||
case H5FP_STATUS_OOM:
|
||
case H5FP_STATUS_BAD_FILE_ID:
|
||
default:
|
||
/* FIXME: Something bad happened */
|
||
HDfprintf(stderr, "%s: Couldn't write metadata to SAP (%d)\n",
|
||
FUNC, sap_status);
|
||
break;
|
||
}
|
||
}
|
||
|
||
/* FIXME: Should I check this return value or just pass it on out? */
|
||
ret_value = H5FD_fphdf5_write_real(_file, mem_type, plist, addr, size_i, buf);
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5FD_fphdf5_write_real
|
||
* Purpose: Do the actual writing to a file. Split apart from the
|
||
* H5FD_fphdf5_write call since I need to write things
|
||
* directly if the SAP is dumping data to me.
|
||
* Return: Success: SUCCEED
|
||
* Failure: FAIL
|
||
* Programmer: Bill Wendling
|
||
* 12. February 2003
|
||
* Modifications:
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5FD_fphdf5_write_real(H5FD_t *_file, H5FD_mem_t mem_type, H5P_genplist_t *plist,
|
||
haddr_t addr, int size, const void *buf)
|
||
{
|
||
H5FD_fphdf5_t *file = (H5FD_fphdf5_t*)_file;
|
||
MPI_Status status;
|
||
MPI_Datatype buf_type = MPI_BYTE;
|
||
MPI_Offset mpi_off;
|
||
int mrc;
|
||
int bytes_written;
|
||
unsigned use_view_this_time = 0;
|
||
herr_t ret_value = SUCCEED;
|
||
|
||
FUNC_ENTER_NOAPI(H5FD_fphdf5_write_real, FAIL)
|
||
|
||
/* check args */
|
||
assert(file);
|
||
assert(file->pub.driver_id == H5FD_FPHDF5);
|
||
assert(plist);
|
||
assert(buf);
|
||
|
||
/* Portably initialize MPI status variable */
|
||
HDmemset(&status, 0, sizeof(MPI_Status));
|
||
|
||
/* some numeric conversions */
|
||
if (H5FD_fphdf5_haddr_to_MPIOff(addr, &mpi_off) < 0)
|
||
HGOTO_ERROR(H5E_INTERNAL, H5E_BADRANGE, FAIL, "can't convert from haddr to MPI off")
|
||
|
||
/* Only check for fancy transfers with raw data I/O */
|
||
if (mem_type == H5FD_MEM_DRAW) {
|
||
H5FD_mpio_xfer_t xfer_mode; /* I/O tranfer mode */
|
||
|
||
/* Obtain the data transfer properties */
|
||
xfer_mode = (H5FD_mpio_xfer_t)H5P_peek_unsigned(plist, H5D_XFER_IO_XFER_MODE_NAME);
|
||
|
||
/*
|
||
* Set up for a fancy xfer using complex types, or single byte block.
|
||
* We wouldn't need to rely on the use_view field if MPI semantics
|
||
* allowed us to test that btype == ftype == MPI_BYTE (or even
|
||
* MPI_TYPE_NULL, which could mean "use MPI_BYTE" by convention).
|
||
*/
|
||
if (xfer_mode == H5FD_MPIO_COLLECTIVE) {
|
||
MPI_Datatype file_type;
|
||
|
||
/* Remember that views are used */
|
||
use_view_this_time = TRUE;
|
||
|
||
/* Prepare for a full-blown xfer using btype, ftype, and disp */
|
||
if (H5P_get(plist, H5FD_FPHDF5_XFER_MEM_MPI_TYPE_NAME, &buf_type) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get MPI-I/O type property")
|
||
|
||
if (H5P_get(plist, H5FD_FPHDF5_XFER_FILE_MPI_TYPE_NAME, &file_type) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get MPI-I/O type property")
|
||
|
||
/* Set the file view when we are using MPI derived types */
|
||
if ((mrc = MPI_File_set_view(file->f, mpi_off, MPI_BYTE,
|
||
file_type, H5FD_mpio_native,
|
||
file->info)) != MPI_SUCCESS)
|
||
HMPI_GOTO_ERROR(FAIL, "MPI_File_set_view failed", mrc)
|
||
|
||
/*
|
||
* When using types, use the address as the displacement for
|
||
* MPI_File_set_view and reset the address for the read to zero
|
||
*/
|
||
mpi_off = 0;
|
||
}
|
||
} /* end if */
|
||
|
||
/* Write the data. */
|
||
if (use_view_this_time) {
|
||
/*OKAY: CAST DISCARDS CONST QUALIFIER*/
|
||
if ((mrc = MPI_File_write_at_all(file->f, mpi_off, (void*)buf,
|
||
size, buf_type, &status)) != MPI_SUCCESS)
|
||
HMPI_GOTO_ERROR(FAIL, "MPI_File_write_at_all failed", mrc)
|
||
} else {
|
||
/*OKAY: CAST DISCARDS CONST QUALIFIER*/
|
||
if ((mrc = MPI_File_write_at(file->f, mpi_off, (void*)buf,
|
||
size, buf_type, &status)) != MPI_SUCCESS)
|
||
HMPI_GOTO_ERROR(FAIL, "MPI_File_write_at failed", mrc)
|
||
}
|
||
|
||
/* Reset the file view when we used MPI derived types */
|
||
if (use_view_this_time)
|
||
if ((mrc = MPI_File_set_view(file->f, (MPI_Offset)0, MPI_BYTE, MPI_BYTE,
|
||
H5FD_mpio_native, file->info)) != MPI_SUCCESS)
|
||
HMPI_GOTO_ERROR(FAIL, "MPI_File_set_view failed", mrc)
|
||
|
||
/*
|
||
* MPI_Get_count incorrectly returns negative count; fake a complete
|
||
* write (use size for both parameters).
|
||
*/
|
||
bytes_written = size;
|
||
|
||
/* Check for write failure */
|
||
if (bytes_written < 0 || bytes_written > size)
|
||
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file write failed")
|
||
|
||
/* Forget the EOF value (see H5FD_fphdf5_get_eof()) */
|
||
file->eof = HADDR_UNDEF;
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5FD_fphdf5_flush
|
||
* Purpose: Makes sure that all data is on disk. This is collective.
|
||
* Return: Success: SUCCEED
|
||
* Failure: FAIL
|
||
* Programmer: Bill Wendling
|
||
* 12. February 2003
|
||
* Modifications:
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5FD_fphdf5_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing)
|
||
{
|
||
H5FD_fphdf5_t *file = (H5FD_fphdf5_t*)_file;
|
||
MPI_Offset mpi_off;
|
||
int mrc;
|
||
unsigned req_id = 0;
|
||
H5FP_status_t status = H5FP_STATUS_OK;
|
||
herr_t ret_value = SUCCEED;
|
||
|
||
FUNC_ENTER_NOAPI(H5FD_fphdf5_flush, FAIL)
|
||
|
||
/* check args */
|
||
assert(file);
|
||
assert(file->pub.driver_id == H5FD_FPHDF5);
|
||
|
||
/*
|
||
* Extend the file to make sure it's large enough, then sync.
|
||
* Unfortunately, keeping track of EOF is an expensive operation, so
|
||
* we can't just check whether EOF<EOA like with other drivers.
|
||
* Therefore we'll just read the byte at EOA-1 and then write it
|
||
* back.
|
||
*/
|
||
if (file->eoa > file->last_eoa) {
|
||
if (H5FD_fphdf5_haddr_to_MPIOff(file->eoa, &mpi_off) < 0)
|
||
HGOTO_ERROR(H5E_INTERNAL, H5E_BADRANGE, FAIL, "cannot convert from haddr_t to MPI_Offset")
|
||
|
||
/* Extend the file's size */
|
||
if ((mrc = MPI_File_set_size(file->f, mpi_off)) != MPI_SUCCESS)
|
||
HMPI_GOTO_ERROR(FAIL, "MPI_File_set_size failed", mrc)
|
||
|
||
/*
|
||
* Don't let any proc return until all have extended the file.
|
||
* (Prevents race condition where some processes go ahead and
|
||
* write more data to the file before all the processes have
|
||
* finished making it the shorter length, potentially truncating
|
||
* the file and dropping the new data written)
|
||
*/
|
||
if ((mrc = MPI_Barrier(H5FP_SAP_BARRIER_COMM)) != MPI_SUCCESS)
|
||
HMPI_GOTO_ERROR(FAIL, "MPI_Barrier failed", mrc)
|
||
|
||
/* Update the 'last' eoa value */
|
||
file->last_eoa = file->eoa;
|
||
}
|
||
|
||
/* Only the captain process needs to flush the metadata. */
|
||
if (H5FD_fphdf5_is_captain(_file)) {
|
||
if (H5FP_request_flush_metadata(_file, file->file_id, dxpl_id,
|
||
&req_id, &status) != SUCCEED)
|
||
HGOTO_ERROR(H5E_FPHDF5, H5E_CANTFLUSH, FAIL, "can't flush metadata")
|
||
|
||
/* Only sync the file if we are not going to immediately close it */
|
||
if (!closing)
|
||
if ((mrc = MPI_File_sync(file->f)) != MPI_SUCCESS)
|
||
HMPI_GOTO_ERROR(FAIL, "MPI_File_sync failed", mrc)
|
||
}
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5FD_fphdf5_MPIOff_to_haddr
|
||
* Purpose: Convert an MPI_Offset value to haddr_t.
|
||
* Return: Success: The haddr_t equivalent of the MPI_OFF argument.
|
||
* Failure: HADDR_UNDEF
|
||
* Programmer: Bill Wendling
|
||
* 30. January 2003
|
||
* Modifications:
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static haddr_t
|
||
H5FD_fphdf5_MPIOff_to_haddr(MPI_Offset mpi_off)
|
||
{
|
||
haddr_t ret_value;
|
||
|
||
FUNC_ENTER_NOINIT(H5FD_fphdf5_MPIOff_to_haddr)
|
||
ret_value = (mpi_off != (MPI_Offset)(haddr_t)mpi_off ? HADDR_UNDEF : (haddr_t)mpi_off);
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5FD_fphdf5_haddr_to_MPIOff
|
||
* Purpose: Convert an haddr_t value to MPI_Offset.
|
||
* Return: Success: Non-negative, the MPI_OFF argument contains
|
||
* the converted value.
|
||
* Failure: FAIL, MPI_OFF is undefined.
|
||
* Programmer: Bill Wendling
|
||
* 30. January 2003
|
||
* Modifications:
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5FD_fphdf5_haddr_to_MPIOff(haddr_t addr, MPI_Offset *mpi_off)
|
||
{
|
||
herr_t ret_value = FAIL;
|
||
|
||
FUNC_ENTER_NOINIT(H5FD_fphdf5_haddr_to_MPIOff)
|
||
|
||
if (mpi_off)
|
||
*mpi_off = (MPI_Offset)addr;
|
||
|
||
ret_value = (addr != (haddr_t)(MPI_Offset)addr ? FAIL : SUCCEED);
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
#endif /* H5_HAVE_FPHDF5 */
|