summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/H5FDmpio.c362
1 files changed, 319 insertions, 43 deletions
diff --git a/src/H5FDmpio.c b/src/H5FDmpio.c
index 2f2f8a5..5a378aa 100644
--- a/src/H5FDmpio.c
+++ b/src/H5FDmpio.c
@@ -72,6 +72,8 @@ static herr_t H5FD_mpio_haddr_to_MPIOff(haddr_t addr, MPI_Offset *mpi_off/*out*/
/* Callbacks */
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);
static herr_t H5FD_mpio_close(H5FD_t *_file);
@@ -85,6 +87,9 @@ static herr_t H5FD_mpio_read(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, hadd
static herr_t H5FD_mpio_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_mpio_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing);
+static herr_t H5FD_mpio_comm_info_dup(MPI_Comm comm, MPI_Info info,
+ MPI_Comm *comm_new, MPI_Info *info_new);
+static herr_t H5FD_mpio_comm_info_free(MPI_Comm *comm, MPI_Info *info);
/* MPIO-specific file access properties */
typedef struct H5FD_mpio_fapl_t {
@@ -102,8 +107,8 @@ static const H5FD_class_t H5FD_mpio_g = {
NULL, /*sb_decode */
sizeof(H5FD_mpio_fapl_t), /*fapl_size */
H5FD_mpio_fapl_get, /*fapl_get */
- NULL, /*fapl_copy */
- NULL, /*fapl_free */
+ H5FD_mpio_fapl_copy, /*fapl_copy */
+ H5FD_mpio_fapl_free, /*fapl_free */
0, /*dxpl_size */
NULL, /*dxpl_copy */
NULL, /*dxpl_free */
@@ -209,24 +214,25 @@ done:
/*-------------------------------------------------------------------------
* Function: H5Pset_fapl_mpio
*
- * Purpose: Store the user supplied MPIO communicator COMM and INFO in
+ * 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 undetermined effect
- * on the access property list. Users should not modify the
- * communicator while it is defined in a property list.
+ * comm is the MPI communicator to be used for file open as
+ * defined in MPI_FILE_OPEN of MPI-2. This function makes a
+ * duplicate of comm. Any modification to comm after this function
+ * call returns has no effect on the access 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 undetermined effect on the
- * access property list. Users should not modify the info 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 makes a
+ * duplicate of info. Any modification to info after this
+ * function call returns has no effect on the access property
+ * list.
+ *
+ * If fapl_id has previously set comm and info values, they
+ * will be replaced and the old communicator and Info object
+ * are freed.
*
* Return: Success: Non-negative
*
@@ -252,11 +258,16 @@ done:
* Robb Matzke, 1999-08-06
* Modified to work with the virtual file layer.
*
- * Raymond Lu
- * Tuesday, Oct 23, 2001
+ * Raymond Lu, 2001-10-23
* Changed the file access list to the new generic property
* list.
*
+ * Albert Cheng, 2003-04-17
+ * Modified the description of the function that it now stores
+ * a duplicate of the communicator and INFO object. Free the
+ * old duplicates if previously set. (Work is actually done
+ * by H5P_set_driver.)
+ *
*-------------------------------------------------------------------------
*/
herr_t
@@ -275,10 +286,8 @@ H5Pset_fapl_mpio(hid_t fapl_id, MPI_Comm comm, MPI_Info info)
/* Check arguments */
if(NULL == (plist = H5P_object_verify(fapl_id,H5P_FILE_ACCESS)))
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a file access list");
-
-#ifdef LATER
-#warning "We need to verify that COMM and INFO contain sensible information."
-#endif
+ if (MPI_COMM_NULL == comm)
+ HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a valid communicator");
/* Initialize driver specific properties */
fa.comm = comm;
@@ -295,15 +304,18 @@ done:
* Function: H5Pget_fapl_mpio
*
* Purpose: If the file access property list is set to the H5FD_MPIO
- * driver then this function returns the MPI communicator and
- * information through the COMM and INFO pointers.
+ * driver then this function returns duplicates of the MPI
+ * communicator and Info object stored through the comm and
+ * info pointers. It is the responsibility of the application
+ * to free the returned communicator and Info object.
*
* Return: Success: Non-negative 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.
+ * Info object returned through the comm and
+ * info arguments if non-null. Since they are
+ * duplicates of the stored objects, future
+ * modifications to the access property list do
+ * not affect them and it is the responsibility
+ * of the application to free them.
*
* Failure: Negative
*
@@ -317,11 +329,13 @@ done:
* to be controlled by data transfer property list during data
* read/write calls.
*
- * Raymond Lu
- * Tuesday, Oct 23, 2001
+ * Raymond Lu, 2001-10-23
* Changed the file access list to the new generic property
* list.
*
+ * Albert Cheng, 2003-04-17
+ * Return duplicates of the stored communicator and Info object.
+ *
*-------------------------------------------------------------------------
*/
herr_t
@@ -329,7 +343,9 @@ H5Pget_fapl_mpio(hid_t fapl_id, MPI_Comm *comm/*out*/, MPI_Info *info/*out*/)
{
H5FD_mpio_fapl_t *fa;
H5P_genplist_t *plist; /* Property list pointer */
- herr_t ret_value=SUCCEED; /* Return value */
+ MPI_Comm comm_tmp=MPI_COMM_NULL;
+ int mpi_code; /* mpi return code */
+ herr_t ret_value=SUCCEED; /* Return value */
FUNC_ENTER_API(H5Pget_fapl_mpio, FAIL);
H5TRACE3("e","ixx",fapl_id,comm,info);
@@ -341,12 +357,34 @@ H5Pget_fapl_mpio(hid_t fapl_id, MPI_Comm *comm/*out*/, MPI_Info *info/*out*/)
if (NULL==(fa=H5P_get_driver_info(plist)))
HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "bad VFL driver info");
+ /* Store the duplicated communicator in a temporary variable for error */
+ /* recovery in case the INFO duplication fails. We cannot attempt to */
+ /* the value into *comm yet since if MPI_Comm_dup fails, we will end */
+ /* up freeing whatever *comm holds and that could be invalid. */
+ if (comm){
+ if (MPI_SUCCESS != (mpi_code=MPI_Comm_dup(fa->comm, &comm_tmp)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Comm_dup failed", mpi_code);
+ }
+
+ if (info){
+ if (MPI_INFO_NULL != fa->info){
+ if (MPI_SUCCESS != (mpi_code=MPI_Info_dup(fa->info, info)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Info_dup failed", mpi_code);
+ }else{
+ /* do not dup it */
+ *info = MPI_INFO_NULL;
+ }
+ }
+
if (comm)
- *comm = fa->comm;
- if (info)
- *info = fa->info;
+ *comm = comm_tmp;
done:
+ if (FAIL==ret_value){
+ /* need to free anything created here */
+ if (comm_tmp != MPI_COMM_NULL)
+ MPI_Comm_free(&comm_tmp);
+ }
FUNC_LEAVE_API(ret_value);
}
@@ -772,7 +810,9 @@ done:
* Friday, August 13, 1999
*
* Modifications:
- *
+ * Albert Cheng, 2003-04-17
+ * Duplicate the communicator and Info object so that the new
+ * property list is insulated from the old one.
*-------------------------------------------------------------------------
*/
static void *
@@ -803,6 +843,108 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5FD_mpio_fapl_copy
+ *
+ * Purpose: Copies the mpio-specific file access properties.
+ *
+ * Return: Success: Ptr to a new property list
+ *
+ * Failure: NULL
+ *
+ * Programmer: Albert Cheng
+ * Jan 8, 2003
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5FD_mpio_fapl_copy(const void *_old_fa)
+{
+ void *ret_value = NULL;
+ const H5FD_mpio_fapl_t *old_fa = (const H5FD_mpio_fapl_t*)_old_fa;
+ H5FD_mpio_fapl_t *new_fa = NULL;
+
+ FUNC_ENTER_NOAPI(H5FD_mpio_fapl_copy, NULL);
+#ifdef H5FDmpio_DEBUG
+if (H5FD_mpio_Debug[(int)'t'])
+fprintf(stderr, "enter H5FD_mpio_fapl_copy\n");
+#endif
+
+ if (NULL==(new_fa=H5MM_malloc(sizeof(H5FD_mpio_fapl_t))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
+
+ /* Copy the general information */
+ HDmemcpy(new_fa, old_fa, sizeof(H5FD_mpio_fapl_t));
+
+ /* Duplicate communicator and Info object. */
+ if (FAIL==H5FD_mpio_comm_info_dup(old_fa->comm, old_fa->info,
+ &new_fa->comm, &new_fa->info))
+ HGOTO_ERROR(H5E_INTERNAL, H5E_CANTCOPY, NULL,
+ "Communicator/Info duplicate failed");
+ ret_value = new_fa;
+
+done:
+ if (NULL == ret_value){
+ /* cleanup */
+ if (new_fa)
+ H5MM_xfree(new_fa);
+ }
+
+#ifdef H5FDmpio_DEBUG
+if (H5FD_mpio_Debug[(int)'t'])
+fprintf(stderr, "leaving H5FD_mpio_fapl_copy\n");
+#endif
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5FD_mpio_fapl_copy() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_mpio_fapl_free
+ *
+ * Purpose: Frees the mpio-specific file access properties.
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Albert Cheng
+ * Jan 8, 2003
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_mpio_fapl_free(void *_fa)
+{
+ herr_t ret_value = SUCCEED;
+ H5FD_mpio_fapl_t *fa = (H5FD_mpio_fapl_t*)_fa;
+
+ FUNC_ENTER_NOAPI(H5FD_mpio_fapl_free, FAIL);
+#ifdef H5FDmpio_DEBUG
+if (H5FD_mpio_Debug[(int)'t'])
+fprintf(stderr, "in H5FD_mpio_fapl_free\n");
+#endif
+ assert(fa);
+
+ /* Free the internal communicator and INFO object */
+ assert(MPI_COMM_NULL!=fa->comm);
+ MPI_Comm_free(&fa->comm);
+ if (MPI_INFO_NULL != fa->info)
+ MPI_Info_free(&fa->info);
+ H5MM_xfree(fa);
+
+done:
+#ifdef H5FDmpio_DEBUG
+if (H5FD_mpio_Debug[(int)'t'])
+fprintf(stderr, "leaving H5FD_mpio_fapl_free\n");
+#endif
+ FUNC_LEAVE_NOAPI(SUCCEED);
+} /* end H5FD_mpio_fapl_free() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5FD_mpio_open
*
* Purpose: Opens a file with name NAME. The FLAGS are a bit field with
@@ -859,6 +1001,9 @@ H5FD_mpio_open(const char *name, unsigned flags, hid_t fapl_id,
H5FD_mpio_fapl_t _fa;
H5P_genplist_t *plist; /* Property list pointer */
H5FD_t *ret_value; /* Return value */
+ MPI_Comm comm_dup=MPI_COMM_NULL;
+ MPI_Info info_dup=MPI_INFO_NULL;
+
FUNC_ENTER_NOAPI(H5FD_mpio_open, NULL);
@@ -881,6 +1026,11 @@ H5FD_mpio_open(const char *name, unsigned flags, hid_t fapl_id,
assert(fa);
}
+ /* Duplicate communicator and Info object for use by this file. */
+ if (FAIL==H5FD_mpio_comm_info_dup(fa->comm, fa->info, &comm_dup, &info_dup))
+ HGOTO_ERROR(H5E_INTERNAL, H5E_CANTCOPY, NULL,
+ "Communicator/Info duplicate failed");
+
/* 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;
@@ -924,15 +1074,15 @@ H5FD_mpio_open(const char *name, unsigned flags, hid_t fapl_id,
#endif
/*OKAY: CAST DISCARDS CONST*/
- if (MPI_SUCCESS != (mpi_code=MPI_File_open(fa->comm, (char*)name,
- mpi_amode, fa->info, &fh)))
+ mpi_code=MPI_File_open(comm_dup, (char*)name, mpi_amode, info_dup, &fh);
+ if (MPI_SUCCESS != mpi_code)
HMPI_GOTO_ERROR(NULL, "MPI_File_open failed", mpi_code);
file_opened=1;
/* Get the MPI rank of this process and the total number of processes */
- if (MPI_SUCCESS != (mpi_code=MPI_Comm_rank (fa->comm, &mpi_rank)))
+ if (MPI_SUCCESS != (mpi_code=MPI_Comm_rank (comm_dup, &mpi_rank)))
HMPI_GOTO_ERROR(NULL, "MPI_Comm_rank failed", mpi_code);
- if (MPI_SUCCESS != (mpi_code=MPI_Comm_size (fa->comm, &mpi_size)))
+ if (MPI_SUCCESS != (mpi_code=MPI_Comm_size (comm_dup, &mpi_size)))
HMPI_GOTO_ERROR(NULL, "MPI_Comm_size failed", mpi_code);
/* Following changes in handling file-truncation made be rkyates and ppweidhaas, sep 99 */
@@ -945,7 +1095,7 @@ H5FD_mpio_open(const char *name, unsigned flags, hid_t fapl_id,
}
/* Broadcast file-size */
- if (MPI_SUCCESS != (mpi_code=MPI_Bcast(&size, sizeof(MPI_Offset), MPI_BYTE, 0, fa->comm)))
+ if (MPI_SUCCESS != (mpi_code=MPI_Bcast(&size, sizeof(MPI_Offset), MPI_BYTE, 0, comm_dup)))
HMPI_GOTO_ERROR(NULL, "MPI_Bcast failed", mpi_code);
/* Only if size > 0, truncate the file - if requested */
@@ -954,7 +1104,7 @@ H5FD_mpio_open(const char *name, unsigned flags, hid_t fapl_id,
HMPI_GOTO_ERROR(NULL, "MPI_File_set_size failed", mpi_code);
/* Don't let any proc return until all have truncated the file. */
- if (MPI_SUCCESS!= (mpi_code=MPI_Barrier(fa->comm)))
+ if (MPI_SUCCESS!= (mpi_code=MPI_Barrier(comm_dup)))
HMPI_GOTO_ERROR(NULL, "MPI_Barrier failed", mpi_code);
size = 0;
}
@@ -964,8 +1114,8 @@ H5FD_mpio_open(const char *name, unsigned flags, hid_t fapl_id,
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
file->f = fh;
- file->comm = fa->comm;
- file->info = fa->info;
+ file->comm = comm_dup;
+ file->info = info_dup;
file->mpi_rank = mpi_rank;
file->mpi_size = mpi_size;
file->eof = H5FD_mpio_MPIOff_to_haddr(size);
@@ -977,6 +1127,12 @@ done:
if(ret_value==NULL) {
if(file_opened)
MPI_File_close(&fh);
+ if (MPI_COMM_NULL != comm_dup)
+ MPI_Comm_free(&comm_dup);
+ if (MPI_INFO_NULL != info_dup)
+ MPI_Info_free(&info_dup);
+ if (file)
+ H5MM_xfree(file);
} /* end if */
#ifdef H5FDmpio_DEBUG
@@ -1028,6 +1184,7 @@ H5FD_mpio_close(H5FD_t *_file)
HMPI_GOTO_ERROR(FAIL, "MPI_File_close failed", mpi_code);
/* Clean up other stuff */
+ H5FD_mpio_comm_info_free(&file->comm, &file->info);
H5MM_xfree(file);
done:
@@ -2011,4 +2168,123 @@ H5FD_mpio_haddr_to_MPIOff(haddr_t addr, MPI_Offset *mpi_off/*out*/)
FUNC_LEAVE_NOAPI(ret_value);
}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_mpio_comm_info_dup
+ *
+ * Purpose: Make duplicates of communicator and Info object.
+ * If the Info object is in fact MPI_INFO_NULL, no duplicate
+ * is made but the same value assigned to the new Info object
+ * handle.
+ *
+ * Return: Success: Non-negative. The new communicator and Info
+ * object handles are returned via comm_new and
+ * info_new pointers.
+ *
+ * Failure: Negative.
+ *
+ * Programmer: Albert Cheng
+ * Jan 8, 2003
+ *
+ * Modifications:
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_mpio_comm_info_dup(MPI_Comm comm, MPI_Info info, MPI_Comm *comm_new, MPI_Info *info_new)
+{
+ herr_t ret_value=SUCCEED;
+ MPI_Comm comm_dup=MPI_COMM_NULL;
+ MPI_Info info_dup=MPI_INFO_NULL;
+ int mpi_code;
+
+ FUNC_ENTER_NOAPI(H5FD_mpio_comm_info_dup, FAIL);
+
+#ifdef H5FDmpio_DEBUG
+if (H5FD_mpio_Debug[(int)'t'])
+fprintf(stderr, "In H5FD_mpio_comm_info_dup: argument comm/info = %d/%ld\n", comm, (long)info);
+#endif
+ /* Check arguments */
+ if (MPI_COMM_NULL == comm)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_BADVALUE, FAIL, "not a valid argument");
+ if (!comm_new || !info_new)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_BADVALUE, FAIL, "bad pointers");
+
+ /* Dup them. Using temporary variables for error recovery cleanup. */
+ if (MPI_SUCCESS != (mpi_code=MPI_Comm_dup(comm, &comm_dup)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Comm_dup failed", mpi_code);
+ if (MPI_INFO_NULL != info){
+ if (MPI_SUCCESS != (mpi_code=MPI_Info_dup(info, &info_dup)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Info_dup failed", mpi_code);
+ }else{
+ /* No dup, just copy it. */
+ info_dup = info;
+ }
+
+ /* copy them to the return arguments */
+ *comm_new = comm_dup;
+ *info_new = info_dup;
+
+done:
+ if (FAIL == ret_value){
+ /* need to free anything created here */
+ if (MPI_COMM_NULL != comm_dup)
+ MPI_Comm_free(&comm_dup);
+ if (MPI_INFO_NULL != info_dup)
+ MPI_Info_free(&info_dup);
+ }
+
+#ifdef H5FDmpio_DEBUG
+if (H5FD_mpio_Debug[(int)'t'])
+fprintf(stderr, "Leaving H5FD_mpio_comm_info_dup\n");
+#endif
+ FUNC_LEAVE_NOAPI(ret_value);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_mpio_comm_info_free
+ *
+ * Purpose: Free the communicator and Info object.
+ * If comm or info is in fact MPI_COMM_NULL or MPI_INFO_NULL
+ * respectively, no action occurs to it.
+ *
+ * Return: Success: Non-negative. The values the pointers refer
+ * to will be set to the corresponding NULL
+ * handles.
+ *
+ * Failure: Negative.
+ *
+ * Programmer: Albert Cheng
+ * Jan 8, 2003
+ *
+ * Modifications:
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_mpio_comm_info_free(MPI_Comm *comm, MPI_Info *info)
+{
+ herr_t ret_value=SUCCEED;
+ FUNC_ENTER_NOAPI(H5FD_mpio_comm_info_free, FAIL);
+
+#ifdef H5FDmpio_DEBUG
+if (H5FD_mpio_Debug[(int)'t'])
+fprintf(stderr, "in H5FD_mpio_comm_info_free\n");
+#endif
+ /* Check arguments */
+ if (!comm || !info)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_BADVALUE, FAIL, "not a valid argument");
+
+ if (MPI_COMM_NULL != *comm)
+ MPI_Comm_free(comm);
+ if (MPI_INFO_NULL != *info)
+ MPI_Info_free(info);
+
+done:
+#ifdef H5FDmpio_DEBUG
+if (H5FD_mpio_Debug[(int)'t'])
+fprintf(stderr, "Leaving H5FD_mpio_comm_info_free\n");
+#endif
+ FUNC_LEAVE_NOAPI(SUCCEED);
+}
#endif /* H5_HAVE_PARALLEL */