summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/H5Cdbg.c111
-rw-r--r--src/H5Cimage.c73
-rw-r--r--src/H5Cmpio.c102
-rw-r--r--src/H5Cpkg.h21
-rw-r--r--src/H5Cprivate.h5
-rw-r--r--src/H5Ctag.c47
-rw-r--r--src/H5Dchunk.c10
-rw-r--r--src/H5FDmpi.c39
-rw-r--r--src/H5FDmpio.c37
-rw-r--r--src/H5FDprivate.h2
-rw-r--r--src/H5Fmpi.c26
-rw-r--r--src/H5Fprivate.h1
-rw-r--r--src/H5L.c6
-rw-r--r--src/H5PL.c282
-rw-r--r--src/H5PLpkg.h50
-rw-r--r--src/H5PLpublic.h7
17 files changed, 736 insertions, 84 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 9321bbd..e2acd30 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -520,6 +520,7 @@ set (H5PL_SOURCES
set (H5PL_HDRS
${HDF5_SRC_DIR}/H5PLextern.h
+ ${HDF5_SRC_DIR}/H5PLpkg.h
${HDF5_SRC_DIR}/H5PLpublic.h
)
IDE_GENERATED_PROPERTIES ("H5PL" "${H5PL_HDRS}" "${H5PL_SOURCES}" )
diff --git a/src/H5Cdbg.c b/src/H5Cdbg.c
index a955eaf..85f25b3 100644
--- a/src/H5Cdbg.c
+++ b/src/H5Cdbg.c
@@ -30,12 +30,16 @@
#include "H5Cmodule.h" /* This source code file is part of the H5C module */
+#define H5AC_FRIEND
+
+
+
/***********/
/* Headers */
/***********/
#include "H5private.h" /* Generic Functions */
-#include "H5ACprivate.h" /* Metadata Cache */
+#include "H5ACpkg.h" /* Metadata Cache */
#include "H5Cpkg.h" /* Cache */
#include "H5Eprivate.h" /* Error Handling */
@@ -340,6 +344,107 @@ H5C_dump_cache_skip_list(H5C_t * cache_ptr, char * calling_fcn)
/*-------------------------------------------------------------------------
+ * Function: H5C_dump_coll_write_list
+ *
+ * Purpose: Debugging routine that prints a summary of the contents of
+ * the collective write skip list used by the metadata cache
+ * in the parallel case to maintain a list of entries to write
+ * collectively at a sync point.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: John Mainzer
+ * 4/1/17
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifdef H5_HAVE_PARALLEL
+#ifndef NDEBUG
+herr_t
+H5C_dump_coll_write_list(H5C_t * cache_ptr, char * calling_fcn)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+ int i;
+ int list_len;
+ H5AC_aux_t * aux_ptr = NULL;
+ H5C_cache_entry_t * entry_ptr = NULL;
+ H5SL_node_t * node_ptr = NULL;
+
+ FUNC_ENTER_NOAPI_NOERR
+
+ HDassert(cache_ptr != NULL);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+ HDassert(cache_ptr->aux_ptr);
+
+ aux_ptr = (H5AC_aux_t *)cache_ptr->aux_ptr;
+
+ HDassert(aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC);
+
+ HDassert(calling_fcn != NULL);
+
+ list_len = (int)H5SL_count(cache_ptr->coll_write_list);
+
+ HDfprintf(stdout, "\n\nDumping MDC coll write list from %d:%s.\n",
+ aux_ptr->mpi_rank, calling_fcn);
+ HDfprintf(stdout, " slist len = %u.\n", cache_ptr->slist_len);
+
+ if ( list_len > 0 ) {
+
+ /* scan the collective write list generating the desired output */
+ HDfprintf(stdout,
+ "Num: Addr: Len: Prot/Pind: Dirty: Type:\n");
+
+ i = 0;
+
+ node_ptr = H5SL_first(cache_ptr->coll_write_list);
+
+ if ( node_ptr != NULL )
+
+ entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr);
+
+ else
+
+ entry_ptr = NULL;
+
+ while ( entry_ptr != NULL ) {
+
+ HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+
+ HDfprintf(stdout,
+ "%s%d 0x%016llx %4lld %d/%d %d %s\n",
+ cache_ptr->prefix, i,
+ (long long)(entry_ptr->addr),
+ (long long)(entry_ptr->size),
+ (int)(entry_ptr->is_protected),
+ (int)(entry_ptr->is_pinned),
+ (int)(entry_ptr->is_dirty),
+ entry_ptr->type->name);
+
+ node_ptr = H5SL_next(node_ptr);
+
+ if ( node_ptr != NULL )
+
+ entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr);
+
+ else
+
+ entry_ptr = NULL;
+
+ i++;
+
+ } /* end while */
+ } /* end if */
+
+ HDfprintf(stdout, "\n\n");
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5C_dump_coll_write_list() */
+#endif /* NDEBUG */
+#endif /* H5_HAVE_PARALLEL */
+
+
+/*-------------------------------------------------------------------------
* Function: H5C_set_prefix
*
* Purpose: Set the values of the prefix field of H5C_t. This
@@ -738,9 +843,10 @@ H5C_stats(H5C_t * cache_ptr,
(long long)(cache_ptr->index_scan_restarts));
HDfprintf(stdout,
- "%s cache image creations/loads/size = %d / %d / %Hu\n",
+ "%s cache image creations/reads/loads/size = %d / %d /%d / %Hu\n",
cache_ptr->prefix,
cache_ptr->images_created,
+ cache_ptr->images_read,
cache_ptr->images_loaded,
cache_ptr->last_image_size);
@@ -993,6 +1099,7 @@ H5C_stats__reset(H5C_t H5_ATTR_UNUSED * cache_ptr)
cache_ptr->index_scan_restarts = 0;
cache_ptr->images_created = 0;
+ cache_ptr->images_read = 0;
cache_ptr->images_loaded = 0;
cache_ptr->last_image_size = (hsize_t)0;
diff --git a/src/H5Cimage.c b/src/H5Cimage.c
index fc58dac..d60ee05 100644
--- a/src/H5Cimage.c
+++ b/src/H5Cimage.c
@@ -122,7 +122,7 @@ static H5C_cache_entry_t *H5C__reconstruct_cache_entry(const H5F_t *f,
H5C_t *cache_ptr, const uint8_t **buf);
static herr_t H5C__write_cache_image_superblock_msg(H5F_t *f, hid_t dxpl_id,
hbool_t create);
-static herr_t H5C__read_cache_image(H5F_t * f, hid_t dxpl_id, const H5C_t *cache_ptr);
+static herr_t H5C__read_cache_image(H5F_t * f, hid_t dxpl_id, H5C_t *cache_ptr);
static herr_t H5C__write_cache_image(H5F_t *f, hid_t dxpl_id, const H5C_t *cache_ptr);
static herr_t H5C__construct_cache_image_buffer(H5F_t *f, H5C_t *cache_ptr);
static herr_t H5C__free_image_entries_array(H5C_t *cache_ptr);
@@ -1035,7 +1035,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5C__read_cache_image(H5F_t *f, hid_t dxpl_id, const H5C_t *cache_ptr)
+H5C__read_cache_image(H5F_t *f, hid_t dxpl_id, H5C_t *cache_ptr)
{
herr_t ret_value = SUCCEED; /* Return value */
@@ -1053,31 +1053,53 @@ H5C__read_cache_image(H5F_t *f, hid_t dxpl_id, const H5C_t *cache_ptr)
H5AC_aux_t *aux_ptr = (H5AC_aux_t *)cache_ptr->aux_ptr;
int mpi_result;
- if((NULL == aux_ptr) || (aux_ptr->mpi_rank == 0)) {
- HDassert((NULL == aux_ptr) || (aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC));
+ if ( ( NULL == aux_ptr ) || ( aux_ptr->mpi_rank == 0 ) ) {
+
+ HDassert((NULL == aux_ptr) ||
+ (aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC));
#endif /* H5_HAVE_PARALLEL */
/* Read the buffer (if serial access, or rank 0 of parallel access) */
- if(H5F_block_read(f, H5FD_MEM_SUPER, cache_ptr->image_addr, cache_ptr->image_len, dxpl_id, cache_ptr->image_buffer) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_READERROR, FAIL, "Can't read metadata cache image block")
+ if ( H5F_block_read(f, H5FD_MEM_SUPER, cache_ptr->image_addr,
+ cache_ptr->image_len, dxpl_id,
+ cache_ptr->image_buffer) < 0)
+
+ HGOTO_ERROR(H5E_CACHE, H5E_READERROR, FAIL, \
+ "Can't read metadata cache image block")
+
+ H5C__UPDATE_STATS_FOR_CACHE_IMAGE_READ(cache_ptr)
#ifdef H5_HAVE_PARALLEL
- if(aux_ptr) {
+ if ( aux_ptr ) {
+
/* Broadcast cache image */
- if(MPI_SUCCESS != (mpi_result = MPI_Bcast(cache_ptr->image_buffer, (int)cache_ptr->image_len, MPI_BYTE, 0, aux_ptr->mpi_comm)))
+ if ( MPI_SUCCESS !=
+ (mpi_result = MPI_Bcast(cache_ptr->image_buffer,
+ (int)cache_ptr->image_len, MPI_BYTE,
+ 0, aux_ptr->mpi_comm)) )
+
HMPI_GOTO_ERROR(FAIL, "MPI_Bcast failed", mpi_result)
+
} /* end if */
} /* end if */
- else if(aux_ptr) {
+ else if ( aux_ptr ) {
+
/* Retrieve the contents of the metadata cache image from process 0 */
- if(MPI_SUCCESS != (mpi_result = MPI_Bcast(cache_ptr->image_buffer, (int)cache_ptr->image_len, MPI_BYTE, 0, aux_ptr->mpi_comm)))
- HMPI_GOTO_ERROR(FAIL, "can't receive cache image MPI_Bcast", mpi_result)
+ if ( MPI_SUCCESS !=
+ (mpi_result = MPI_Bcast(cache_ptr->image_buffer,
+ (int)cache_ptr->image_len, MPI_BYTE,
+ 0, aux_ptr->mpi_comm)) )
+
+ HMPI_GOTO_ERROR(FAIL, "can't receive cache image MPI_Bcast", \
+ mpi_result)
} /* end else-if */
} /* end block */
#endif /* H5_HAVE_PARALLEL */
done:
+
FUNC_LEAVE_NOAPI(ret_value)
+
} /* H5C__read_cache_image() */
@@ -3203,26 +3225,31 @@ H5C__reconstruct_cache_contents(H5F_t *f, hid_t dxpl_id, H5C_t *cache_ptr)
i = -1;
entry_ptr = cache_ptr->LRU_head_ptr;
+
while(entry_ptr != NULL) {
- HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+
+ HDassert(entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
HDassert(entry_ptr->type != NULL);
- if(entry_ptr->prefetched) {
- HDassert(i <= entry_ptr->lru_rank);
- HDassert((entry_ptr->lru_rank <= 2) ||
- (entry_ptr->lru_rank == i + 1) ||
- (entry_ptr->lru_rank == i + 2));
+ if ( entry_ptr->prefetched ) {
- if((entry_ptr->lru_rank <= 2) && (entry_ptr->lru_rank == i + 2))
- lru_rank_holes++;
+ HDassert(entry_ptr->lru_rank != 0);
+ HDassert((entry_ptr->lru_rank == -1) ||
+ (entry_ptr->lru_rank > i));
- i = entry_ptr->lru_rank;
- } /* end if */
+ if ( ( entry_ptr->lru_rank > 1 ) &&
+ ( entry_ptr->lru_rank > i + 1 ) )
+
+ lru_rank_holes += entry_ptr->lru_rank - (i + 1);
+
+ i = entry_ptr->lru_rank;
+
+ } /* end if */
- entry_ptr = entry_ptr->next;
+ entry_ptr = entry_ptr->next;
} /* end while */
- /* Holes of size 1 appear in the LRU ranking due to epoch
+ /* Holes in the sequences of LRU ranks can appear due to epoch
* markers. They are left in to allow re-insertion of the
* epoch markers on reconstruction of the cache -- thus
* the following sanity check will have to be revised when
diff --git a/src/H5Cmpio.c b/src/H5Cmpio.c
index 06ce714..0d1a3ff 100644
--- a/src/H5Cmpio.c
+++ b/src/H5Cmpio.c
@@ -950,12 +950,15 @@ H5C__collective_write(H5F_t *f, hid_t dxpl_id)
/* Get original transfer mode */
if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data transfer property list")
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, \
+ "not a data transfer property list")
+
if(H5P_get(plist, H5D_XFER_IO_XFER_MODE_NAME, &orig_xfer_mode) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set MPI-I/O property")
/* Get number of entries in collective write list */
count = (int)H5SL_count(cache_ptr->coll_write_list);
+
if(count > 0) {
H5FD_mpio_xfer_t xfer_mode = H5FD_MPIO_COLLECTIVE;
H5SL_node_t *node;
@@ -964,21 +967,34 @@ H5C__collective_write(H5F_t *f, hid_t dxpl_id)
int i;
if(H5P_set(plist, H5D_XFER_IO_XFER_MODE_NAME, &xfer_mode) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set MPI-I/O property")
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, \
+ "can't set MPI-I/O property")
/* Allocate arrays */
- if(NULL == (length_array = (int *)H5MM_malloc((size_t)count * sizeof(int))))
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "memory allocation failed for collective write table length array")
- if(NULL == (buf_array = (MPI_Aint *)H5MM_malloc((size_t)count * sizeof(MPI_Aint))))
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "memory allocation failed for collective buf table length array")
- if(NULL == (offset_array = (MPI_Aint *)H5MM_malloc((size_t)count * sizeof(MPI_Aint))))
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "memory allocation failed for collective offset table length array")
+ if ( NULL == (length_array =
+ (int *)H5MM_malloc((size_t)count * sizeof(int))) )
+
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, \
+ "memory allocation failed for collective write table length array")
+
+ if ( NULL == (buf_array =
+ (MPI_Aint *)H5MM_malloc((size_t)count * sizeof(MPI_Aint))) )
+
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, \
+ "memory allocation failed for collective buf table length array")
+
+ if(NULL == (offset_array =
+ (MPI_Aint *)H5MM_malloc((size_t)count * sizeof(MPI_Aint))) )
+
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, \
+ "memory allocation failed for collective offset table length array")
/* Fill arrays */
node = H5SL_first(cache_ptr->coll_write_list);
HDassert(node);
if(NULL == (entry_ptr = (H5C_cache_entry_t *)H5SL_item(node)))
- HGOTO_ERROR(H5E_CACHE, H5E_NOTFOUND, FAIL, "can't retrieve skip list item")
+ HGOTO_ERROR(H5E_CACHE, H5E_NOTFOUND, FAIL, \
+ "can't retrieve skip list item")
/* Set up initial array position & buffer base address */
length_array[0] = (int)entry_ptr->size;
@@ -989,8 +1005,10 @@ H5C__collective_write(H5F_t *f, hid_t dxpl_id)
node = H5SL_next(node);
i = 1;
while(node) {
+
if(NULL == (entry_ptr = (H5C_cache_entry_t *)H5SL_item(node)))
- HGOTO_ERROR(H5E_CACHE, H5E_NOTFOUND, FAIL, "can't retrieve skip list item")
+ HGOTO_ERROR(H5E_CACHE, H5E_NOTFOUND, FAIL, \
+ "can't retrieve skip list item")
/* Set up array position */
length_array[i] = (int)entry_ptr->size;
@@ -1003,48 +1021,85 @@ H5C__collective_write(H5F_t *f, hid_t dxpl_id)
} /* end while */
/* Create memory MPI type */
- if(MPI_SUCCESS != (mpi_code = MPI_Type_create_hindexed(count, length_array, buf_array, MPI_BYTE, &btype)))
+ if(MPI_SUCCESS != (mpi_code =
+ MPI_Type_create_hindexed(count, length_array,
+ buf_array, MPI_BYTE,
+ &btype)))
HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hindexed failed", mpi_code)
+
btype_created = TRUE;
+
if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(&btype)))
HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code)
/* Create file MPI type */
- if(MPI_SUCCESS != (mpi_code = MPI_Type_create_hindexed(count, length_array, offset_array, MPI_BYTE, &ftype)))
+ if(MPI_SUCCESS != (mpi_code =
+ MPI_Type_create_hindexed(count, length_array,
+ offset_array, MPI_BYTE,
+ &ftype)))
HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hindexed failed", mpi_code)
+
ftype_created = TRUE;
+
if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(&ftype)))
HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code)
/* Pass buf type, file type to the file driver */
if(H5FD_mpi_setup_collective(dxpl_id, &btype, &ftype) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set MPI-I/O properties")
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, \
+ "can't set MPI-I/O properties")
/* Write data */
- if(H5F_block_write(f, H5FD_MEM_DEFAULT, (haddr_t)0, (size_t)1, dxpl_id, base_buf) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to write entries collectively")
+ if(H5F_block_write(f, H5FD_MEM_DEFAULT, (haddr_t)0,
+ (size_t)1, dxpl_id, base_buf) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
+ "unable to write entries collectively")
+
} /* end if */
else {
MPI_Status mpi_stat;
- MPI_File mpi_fh_p;
+ MPI_File *mpi_fh_p;
MPI_File mpi_fh;
+ MPI_Info *info_p;
+ MPI_Info info;
if(H5F_get_mpi_handle(f, (MPI_File **)&mpi_fh_p) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get mpi file handle")
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, \
+ "can't get mpi file handle")
+
mpi_fh = *(MPI_File*)mpi_fh_p;
- /* just to match up with the 1st MPI_File_set_view from H5FD_mpio_write() */
- if(MPI_SUCCESS != (mpi_code = MPI_File_set_view(mpi_fh, (MPI_Offset)0, MPI_BYTE, MPI_BYTE, "native", MPI_INFO_NULL)))
+ if (H5F_get_mpi_info(f, &info_p) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, \
+ "can't get mpi file info")
+
+ info = *info_p;
+
+ /* just to match up with the 1st MPI_File_set_view from
+ * H5FD_mpio_write()
+ */
+ if(MPI_SUCCESS != (mpi_code =
+ MPI_File_set_view(mpi_fh, (MPI_Offset)0, MPI_BYTE,
+ MPI_BYTE, "native",
+ info)))
HMPI_GOTO_ERROR(FAIL, "MPI_File_set_view failed", mpi_code)
/* just to match up with MPI_File_write_at_all from H5FD_mpio_write() */
HDmemset(&mpi_stat, 0, sizeof(MPI_Status));
- if(MPI_SUCCESS != (mpi_code = MPI_File_write_at_all(mpi_fh, (MPI_Offset)0, NULL, 0, MPI_BYTE, &mpi_stat)))
+ if(MPI_SUCCESS != (mpi_code =
+ MPI_File_write_at_all(mpi_fh, (MPI_Offset)0,
+ NULL, 0, MPI_BYTE, &mpi_stat)))
HMPI_GOTO_ERROR(FAIL, "MPI_File_write_at_all failed", mpi_code)
- /* just to match up with the 2nd MPI_File_set_view (reset) in H5FD_mpio_write() */
- if(MPI_SUCCESS != (mpi_code = MPI_File_set_view(mpi_fh, (MPI_Offset)0, MPI_BYTE, MPI_BYTE, "native", MPI_INFO_NULL)))
+ /* just to match up with the 2nd MPI_File_set_view (reset) in
+ * H5FD_mpio_write()
+ */
+ if(MPI_SUCCESS != (mpi_code =
+ MPI_File_set_view(mpi_fh, (MPI_Offset)0, MPI_BYTE,
+ MPI_BYTE, "native",
+ info)))
HMPI_GOTO_ERROR(FAIL, "MPI_File_set_view failed", mpi_code)
+
} /* end else */
done:
@@ -1063,7 +1118,8 @@ done:
if(orig_xfer_mode != H5FD_MPIO_COLLECTIVE) {
HDassert(plist);
if(H5P_set(plist, H5D_XFER_IO_XFER_MODE_NAME, &orig_xfer_mode) < 0)
- HDONE_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set MPI-I/O property")
+ HDONE_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, \
+ "can't set MPI-I/O property")
} /* end if */
FUNC_LEAVE_NOAPI(ret_value);
diff --git a/src/H5Cpkg.h b/src/H5Cpkg.h
index 69e8145..90a84c4 100644
--- a/src/H5Cpkg.h
+++ b/src/H5Cpkg.h
@@ -686,6 +686,13 @@ if ( ( ( ( (head_ptr) == NULL ) || ( (tail_ptr) == NULL ) ) && \
(cache_ptr)->images_created++; \
}
+#define H5C__UPDATE_STATS_FOR_CACHE_IMAGE_READ(cache_ptr) \
+{ \
+ /* make sure image len is still good */ \
+ HDassert((cache_ptr)->image_len > 0); \
+ (cache_ptr)->images_read++; \
+}
+
#define H5C__UPDATE_STATS_FOR_CACHE_IMAGE_LOAD(cache_ptr) \
{ \
/* make sure image len is still good */ \
@@ -931,6 +938,7 @@ if ( ( ( ( (head_ptr) == NULL ) || ( (tail_ptr) == NULL ) ) && \
#define H5C__UPDATE_STATS_FOR_LRU_SCAN_RESTART(cache_ptr)
#define H5C__UPDATE_STATS_FOR_INDEX_SCAN_RESTART(cache_ptr)
#define H5C__UPDATE_STATS_FOR_CACHE_IMAGE_CREATE(cache_ptr)
+#define H5C__UPDATE_STATS_FOR_CACHE_IMAGE_READ(cache_ptr)
#define H5C__UPDATE_STATS_FOR_CACHE_IMAGE_LOAD(cache_ptr)
#define H5C__UPDATE_STATS_FOR_PREFETCH(cache_ptr, dirty)
#define H5C__UPDATE_STATS_FOR_PREFETCH_HIT(cache_ptr)
@@ -4549,6 +4557,18 @@ typedef struct H5C_tag_info_t {
* Further, since cache images are only created at file
* close, this field should only be set at that time.
*
+ * images_read: Integer field containing the number of cache images
+ * read from file. Note that reading an image is different
+ * from loading it -- reading the image means just that,
+ * while loading the image refers to decoding it and loading
+ * it into the metadata cache.
+ *
+ * In the serial case, image_read should always equal
+ * images_loaded. However, in the parallel case, the
+ * image should only be read by process 0. All other
+ * processes should receive the cache image via a broadcast
+ * from process 0.
+ *
* images_loaded: Integer field containing the number of cache images
* loaded since the last time statistics were reset.
*
@@ -4864,6 +4884,7 @@ struct H5C_t {
/* Fields for tracking cache image operations */
int32_t images_created;
+ int32_t images_read;
int32_t images_loaded;
hsize_t last_image_size;
diff --git a/src/H5Cprivate.h b/src/H5Cprivate.h
index bdfb23e..5c5a666 100644
--- a/src/H5Cprivate.h
+++ b/src/H5Cprivate.h
@@ -2340,9 +2340,12 @@ H5_DLL herr_t H5C_dump_cache_LRU(H5C_t *cache_ptr, const char *cache_name);
H5_DLL hbool_t H5C_get_serialization_in_progress(const H5C_t *cache_ptr);
H5_DLL hbool_t H5C_cache_is_clean(const H5C_t *cache_ptr, H5C_ring_t inner_ring);
H5_DLL herr_t H5C_dump_cache_skip_list(H5C_t *cache_ptr, char *calling_fcn);
+#ifdef H5_HAVE_PARALLEL
+H5_DLL herr_t H5C_dump_coll_write_list(H5C_t * cache_ptr, char * calling_fcn);
+#endif /* H5_HAVE_PARALLEL */
H5_DLL herr_t H5C_get_entry_ptr_from_addr(H5C_t *cache_ptr, haddr_t addr,
void **entry_ptr_ptr);
-H5_DLL herr_t H5C_flush_dependency_exists(H5C_t *cache_ptr, haddr_t parent_addr,
+H5_DLL herr_t H5C_flush_dependency_exists(H5C_t *cache_ptr, haddr_t parent_addr,
haddr_t child_addr, hbool_t *fd_exists_ptr);
H5_DLL herr_t H5C_verify_entry_type(H5C_t *cache_ptr, haddr_t addr,
const H5C_class_t *expected_type, hbool_t *in_cache_ptr,
diff --git a/src/H5Ctag.c b/src/H5Ctag.c
index a9bcca1..0170ce9 100644
--- a/src/H5Ctag.c
+++ b/src/H5Ctag.c
@@ -58,8 +58,18 @@
typedef struct {
H5F_t * f; /* File pointer for evicting entry */
hid_t dxpl_id; /* DXPL for evicting entry */
- hbool_t evicted_entries_last_pass; /* Flag to indicate that an entry was evicted when iterating over cache */
- hbool_t pinned_entries_need_evicted; /* Flag to indicate that a pinned entry was attempted to be evicted */
+ hbool_t evicted_entries_last_pass; /* Flag to indicate that an entry
+ * was evicted when iterating over
+ * cache
+ */
+ hbool_t pinned_entries_need_evicted;/* Flag to indicate that a pinned
+ * entry was attempted to be evicted
+ */
+ hbool_t skipped_pf_dirty_entries; /* Flag indicating that one or more
+ * entries marked prefetched_dirty
+ * were encountered and not
+ * evicted.
+ */
} H5C_tag_iter_evict_ctx_t;
/* Typedef for tagged entry iterator callback context - expunge tag type metadata */
@@ -470,7 +480,9 @@ H5C__evict_tagged_entries_cb(H5C_cache_entry_t *entry, void *_ctx)
if(H5C__flush_single_entry(ctx->f, ctx->dxpl_id, entry, H5C__FLUSH_INVALIDATE_FLAG | H5C__FLUSH_CLEAR_ONLY_FLAG | H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, H5_ITER_ERROR, "Entry eviction failed.")
ctx->evicted_entries_last_pass = TRUE;
- } /* end else */
+ } else {
+ ctx->skipped_pf_dirty_entries = TRUE;
+ }
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -516,6 +528,7 @@ H5C_evict_tagged_entries(H5F_t * f, hid_t dxpl_id, haddr_t tag, hbool_t match_gl
/* Reset pinned/evicted tracking flags */
ctx.pinned_entries_need_evicted = FALSE;
ctx.evicted_entries_last_pass = FALSE;
+ ctx.skipped_pf_dirty_entries = FALSE;
/* Iterate through entries in the cache */
if(H5C__iter_tagged_entries(cache, tag, match_global, H5C__evict_tagged_entries_cb, &ctx) < 0)
@@ -524,8 +537,32 @@ H5C_evict_tagged_entries(H5F_t * f, hid_t dxpl_id, haddr_t tag, hbool_t match_gl
/* Keep doing this until we have stopped evicted entries */
} while(TRUE == ctx.evicted_entries_last_pass);
- /* Fail if we have finished evicting entries and pinned entries still need evicted */
- if(ctx.pinned_entries_need_evicted)
+ /* In most cases, fail if we have finished evicting entries and pinned
+ * entries still need evicted
+ *
+ * However, things can get strange if the file was opened R/O and
+ * the file contains a cache image and the cache image contains dirty
+ * entries.
+ *
+ * Since the file was opened read only, dirty entries in the cache
+ * image were marked as clean when they were inserted into the metadata
+ * cache. This is necessary, as if they are marked dirty, the metadata
+ * cache will attempt to write them on file close, which is frowned
+ * upon when the file is opened R/O.
+ *
+ * On the other hand, such entries (marked prefetched_dirty) must not
+ * be evicted, as should the cache be asked to re-load them, the cache
+ * will attempt to read them from the file, and at best load an outdated
+ * version.
+ *
+ * To avoid this, H5C__evict_tagged_entries_cb has been modified to
+ * skip such entries. However, by doing so, it may prevent pinned
+ * entries from becoming unpinned.
+ *
+ * Thus we must ignore ctx.pinned_entries_need_evicted if
+ * ctx.skipped_pf_dirty_entries is TRUE.
+ */
+ if((!ctx.skipped_pf_dirty_entries) && (ctx.pinned_entries_need_evicted))
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Pinned entries still need evicted?!")
done:
diff --git a/src/H5Dchunk.c b/src/H5Dchunk.c
index 4999f39..7ab9658 100644
--- a/src/H5Dchunk.c
+++ b/src/H5Dchunk.c
@@ -6056,9 +6056,9 @@ H5D__chunk_stats(const H5D_t *dset, hbool_t headers)
#endif
if (headers) {
- if (rdcc->nhits>0 || rdcc->nmisses>0) {
- miss_rate = 100.0 * rdcc->nmisses /
- (rdcc->nhits + rdcc->nmisses);
+ if (rdcc->stats.nhits>0 || rdcc->stats.nmisses>0) {
+ miss_rate = 100.0 * rdcc->stats.nmisses /
+ (rdcc->stats.nhits + rdcc->stats.nmisses);
} else {
miss_rate = 0.0;
}
@@ -6069,8 +6069,8 @@ H5D__chunk_stats(const H5D_t *dset, hbool_t headers)
}
fprintf(H5DEBUG(AC), " %-18s %8u %8u %7s %8d+%-9ld\n",
- "raw data chunks", rdcc->nhits, rdcc->nmisses, ascii,
- rdcc->ninits, (long)(rdcc->nflushes)-(long)(rdcc->ninits));
+ "raw data chunks", rdcc->stats.nhits, rdcc->stats.nmisses, ascii,
+ rdcc->stats.ninits, (long)(rdcc->stats.nflushes)-(long)(rdcc->stats.ninits));
}
done:
diff --git a/src/H5FDmpi.c b/src/H5FDmpi.c
index fdc4eca..bf4e03a 100644
--- a/src/H5FDmpi.c
+++ b/src/H5FDmpi.c
@@ -148,6 +148,45 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5FD_get_mpi_info
+ *
+ * Purpose: Retrieves the file's mpi info
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: Negative
+ *
+ * Programmer: John Mainzer
+ * 4/4/17
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FD_get_mpi_info(H5FD_t *file, void** mpi_info)
+{
+ const H5FD_class_mpi_t *cls;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ HDassert(file);
+ cls = (const H5FD_class_mpi_t *)(file->cls);
+ HDassert(cls);
+ HDassert(cls->get_mpi_info); /* All MPI drivers must implement this */
+
+ /* Dispatch to driver */
+ if ((ret_value=(cls->get_mpi_info)(file, mpi_info)) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTGET, MPI_COMM_NULL, \
+ "driver get_mpi_info request failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_get_mpi_info() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5FD_mpi_MPIOff_to_haddr
*
* Purpose: Convert an MPI_Offset value to haddr_t.
diff --git a/src/H5FDmpio.c b/src/H5FDmpio.c
index a3a404f..9417d46 100644
--- a/src/H5FDmpio.c
+++ b/src/H5FDmpio.c
@@ -95,6 +95,7 @@ static herr_t H5FD_mpio_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing);
static int H5FD_mpio_mpi_rank(const H5FD_t *_file);
static int H5FD_mpio_mpi_size(const H5FD_t *_file);
static MPI_Comm H5FD_mpio_communicator(const H5FD_t *_file);
+static herr_t H5FD_mpio_get_info(H5FD_t *_file, void** mpi_info);
/* The MPIO file driver information */
static const H5FD_class_mpi_t H5FD_mpio_g = {
@@ -134,7 +135,8 @@ static const H5FD_class_mpi_t H5FD_mpio_g = {
}, /* End of superclass information */
H5FD_mpio_mpi_rank, /*get_rank */
H5FD_mpio_mpi_size, /*get_size */
- H5FD_mpio_communicator /*get_comm */
+ H5FD_mpio_communicator, /*get_comm */
+ H5FD_mpio_get_info /*get_info */
};
#ifdef H5FDmpio_DEBUG
@@ -1308,6 +1310,39 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5FD_mpio_get_info
+ *
+ * Purpose: Returns the file info of MPIO file driver.
+ *
+ * Returns: Non-negative if succeed or negative if fails.
+ *
+ * Programmer: John Mainzer
+ * April 4, 2017
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+*/
+static herr_t
+H5FD_mpio_get_info(H5FD_t *_file, void** mpi_info)
+{
+ H5FD_mpio_t *file = (H5FD_mpio_t *)_file;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ if(!mpi_info)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "mpi info not valid")
+
+ *mpi_info = &(file->info);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5FD_mpio_get_info() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5FD_mpio_read
*
* Purpose: Reads SIZE bytes of data from FILE beginning at address ADDR
diff --git a/src/H5FDprivate.h b/src/H5FDprivate.h
index c64ec30..fb7c43c 100644
--- a/src/H5FDprivate.h
+++ b/src/H5FDprivate.h
@@ -53,6 +53,7 @@ typedef struct H5FD_class_mpi_t {
int (*get_rank)(const H5FD_t *file); /* Get the MPI rank of a process */
int (*get_size)(const H5FD_t *file); /* Get the MPI size of a communicator */
MPI_Comm (*get_comm)(const H5FD_t *file); /* Get the communicator for a file */
+ herr_t (*get_mpi_info)(H5FD_t *file, void** mpi_info); /* get MPI_Info for a file */
} H5FD_class_mpi_t;
#endif
@@ -202,6 +203,7 @@ H5_DLL herr_t H5FD_get_mpio_atomicity(H5FD_t *file, hbool_t *flag);
H5_DLL int H5FD_mpi_get_rank(const H5FD_t *file);
H5_DLL int H5FD_mpi_get_size(const H5FD_t *file);
H5_DLL MPI_Comm H5FD_mpi_get_comm(const H5FD_t *_file);
+H5_DLL herr_t H5FD_get_mpi_info(H5FD_t *file, void** file_info);
#endif /* H5_HAVE_PARALLEL */
#endif /* !_H5FDprivate_H */
diff --git a/src/H5Fmpi.c b/src/H5Fmpi.c
index 5434aa5..60593a8 100644
--- a/src/H5Fmpi.c
+++ b/src/H5Fmpi.c
@@ -356,5 +356,31 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5F_mpi_retrieve_comm */
+/*-------------------------------------------------------------------------
+ * Function: H5F_get_mpi_info
+ *
+ * Purpose: Retrieves MPI File info.
+ *
+ * Return: Success: The size (positive)
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_get_mpi_info(const H5F_t *f, MPI_Info **f_info)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ HDassert(f && f->shared);
+
+ /* Dispatch to driver */
+ if ((ret_value = H5FD_get_mpi_info(f->shared->lf, (void **)f_info)) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get mpi file info")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_get_mpi_info() */
#endif /* H5_HAVE_PARALLEL */
diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h
index 886063a..8ef353a 100644
--- a/src/H5Fprivate.h
+++ b/src/H5Fprivate.h
@@ -852,6 +852,7 @@ H5_DLL int H5F_mpi_get_rank(const H5F_t *f);
H5_DLL MPI_Comm H5F_mpi_get_comm(const H5F_t *f);
H5_DLL int H5F_mpi_get_size(const H5F_t *f);
H5_DLL herr_t H5F_mpi_retrieve_comm(hid_t loc_id, hid_t acspl_id, MPI_Comm *mpi_comm);
+H5_DLL herr_t H5F_get_mpi_info(const H5F_t *f, MPI_Info **f_info);
#endif /* H5_HAVE_PARALLEL */
/* External file cache routines */
diff --git a/src/H5L.c b/src/H5L.c
index b5c6240..ecdf8a2 100644
--- a/src/H5L.c
+++ b/src/H5L.c
@@ -2351,9 +2351,11 @@ H5L_delete_cb(H5G_loc_t *grp_loc/*in*/, const char *name, const H5O_link_t *lnk,
if(name == NULL)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "name doesn't exist")
- /* Check for removing '.' */
+ /* Check for non-existent (NULL) link.
+ * Note that this can also occur when attempting to remove '.'
+ */
if(lnk == NULL)
- HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "can't delete self")
+ HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "callback link pointer is NULL (specified link may be '.' or not exist)")
/* Remove the link from the group */
if(H5G_obj_remove(grp_loc->oloc, grp_loc->path->full_path_r, name, udata->dxpl_id) < 0)
diff --git a/src/H5PL.c b/src/H5PL.c
index 1f7bb2a..bfa3ace 100644
--- a/src/H5PL.c
+++ b/src/H5PL.c
@@ -25,15 +25,33 @@
#include "H5private.h" /* Generic Functions */
#include "H5Eprivate.h" /* Error handling */
#include "H5MMprivate.h" /* Memory management */
-#include "H5PLprivate.h" /* Plugin */
+#include "H5PLpkg.h" /* Plugin */
#include "H5Zprivate.h" /* Filter pipeline */
/****************/
/* Local Macros */
/****************/
-
-#define H5PL_MAX_PATH_NUM 16
+#ifdef H5_HAVE_WIN32_API
+#define H5PL_EXPAND_ENV_VAR { \
+ long bufCharCount; \
+ char *tempbuf; \
+ if(NULL == (tempbuf = (char *)H5MM_malloc(H5PL_EXPAND_BUFFER_SIZE))) \
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't allocate memory for expanded path") \
+ if((bufCharCount = ExpandEnvironmentStringsA(dl_path, tempbuf, H5PL_EXPAND_BUFFER_SIZE)) > H5PL_EXPAND_BUFFER_SIZE) { \
+ tempbuf = (char *)H5MM_xfree(tempbuf); \
+ HGOTO_ERROR(H5E_PLUGIN, H5E_NOSPACE, FAIL, "expanded path is too long") \
+ } \
+ if(bufCharCount == 0) { \
+ tempbuf = (char *)H5MM_xfree(tempbuf); \
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "failed to expand path") \
+ } \
+ dl_path = (char *)H5MM_xfree(dl_path); \
+ dl_path = tempbuf; \
+ }
+#else
+#define H5PL_EXPAND_ENV_VAR
+#endif /* H5_HAVE_WIN32_API */
/****************************/
/* Macros for supporting
@@ -390,6 +408,244 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5PLappend
+ *
+ * Purpose: Insert a plugin path at the end of the list.
+ *
+ * Return: Non-negative or success.
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5PLappend(const char* plugin_path)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+ char *dl_path = NULL;
+
+ FUNC_ENTER_API(FAIL)
+ if(H5PL_num_paths_g == H5PL_MAX_PATH_NUM)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_NOSPACE, FAIL, "too many directories in path for table")
+ if(NULL == plugin_path)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "no path provided")
+ if(NULL == (dl_path = H5MM_strdup(plugin_path)))
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't allocate memory for path")
+
+ H5PL_EXPAND_ENV_VAR
+
+ H5PL_path_table_g[H5PL_num_paths_g] = dl_path;
+ H5PL_num_paths_g++;
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5PLappend() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PLprepend
+ *
+ * Purpose: Insert a plugin path at the beginning of the list.
+ *
+ * Return: Non-negative or success.
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5PLprepend(const char* plugin_path)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+ char *dl_path = NULL;
+ unsigned int plindex;
+
+ FUNC_ENTER_API(FAIL)
+ if(H5PL_num_paths_g == H5PL_MAX_PATH_NUM)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_NOSPACE, FAIL, "too many directories in path for table")
+ if(NULL == plugin_path)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "no path provided")
+ if(NULL == (dl_path = H5MM_strdup(plugin_path)))
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't allocate memory for path")
+
+ H5PL_EXPAND_ENV_VAR
+
+ for (plindex = (unsigned int)H5PL_num_paths_g; plindex > 0; plindex--)
+ H5PL_path_table_g[plindex] = H5PL_path_table_g[plindex - 1];
+ H5PL_path_table_g[0] = dl_path;
+ H5PL_num_paths_g++;
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5PLprepend() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PLreplace
+ *
+ * Purpose: Replace the path at the specified index.
+ *
+ * Return: Non-negative or success.
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5PLreplace(const char* plugin_path, unsigned int index)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+ char *dl_path = NULL;
+
+ FUNC_ENTER_API(FAIL)
+ if(NULL == plugin_path)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "no path provided")
+ if(index >= H5PL_MAX_PATH_NUM)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_NOSPACE, FAIL, "index path out of bounds for table")
+ if(NULL == (dl_path = H5MM_strdup(plugin_path)))
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't allocate memory for path")
+
+ H5PL_EXPAND_ENV_VAR
+
+ if(H5PL_path_table_g[index])
+ H5PL_path_table_g[index] = (char *)H5MM_xfree(H5PL_path_table_g[index]);
+ H5PL_path_table_g[index] = dl_path;
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5PLreplace() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PLinsert
+ *
+ * Purpose: Insert a plugin path at the specified index, moving other paths after the index.
+ *
+ * Return: Non-negative or success.
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5PLinsert(const char* plugin_path, unsigned int index)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+ char *dl_path = NULL;
+ unsigned int plindex;
+
+ FUNC_ENTER_API(FAIL)
+ if(H5PL_num_paths_g == H5PL_MAX_PATH_NUM)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_NOSPACE, FAIL, "too many directories in path for table")
+ if(NULL == plugin_path)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "no path provided")
+ if(index >= H5PL_MAX_PATH_NUM)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_NOSPACE, FAIL, "index path out of bounds for table")
+ if(NULL == (dl_path = H5MM_strdup(plugin_path)))
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't allocate memory for path")
+
+ H5PL_EXPAND_ENV_VAR
+
+ for(plindex = (unsigned int)H5PL_num_paths_g; plindex > index; plindex--)
+ H5PL_path_table_g[plindex] = H5PL_path_table_g[plindex - 1];
+ H5PL_path_table_g[index] = dl_path;
+ H5PL_num_paths_g++;
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5PLinsert() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PLremove
+ *
+ * Purpose: Remove the plugin path at the specifed index and compacting the list.
+ *
+ * Return: Non-negative or success.
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5PLremove(unsigned int index)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+ unsigned int plindex;
+
+ FUNC_ENTER_API(FAIL)
+ if(H5PL_num_paths_g == 0)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_NOSPACE, FAIL, "no directories in table")
+ if(index >= H5PL_MAX_PATH_NUM)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_NOSPACE, FAIL, "index path out of bounds for table")
+ if(NULL == H5PL_path_table_g[index])
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "no directory path at index")
+ H5PL_path_table_g[index] = (char *)H5MM_xfree(H5PL_path_table_g[index]);
+
+ H5PL_num_paths_g--;
+ for(plindex = index; plindex < (unsigned int)H5PL_num_paths_g; plindex++)
+ H5PL_path_table_g[plindex] = H5PL_path_table_g[plindex + 1];
+ H5PL_path_table_g[H5PL_num_paths_g] = NULL;
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5PLremove() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PLget
+ *
+ * Purpose: Query the plugin path at the specified index.
+ *
+ * Return: Success: The length of path.
+ *
+ * If `pathname' is non-NULL then write up to `size' bytes into that
+ * buffer and always return the length of the pathname.
+ * Otherwise `size' is ignored and the function does not store the pathname,
+ * just returning the number of characters required to store the pathname.
+ * If an error occurs then the buffer pointed to by `pathname' (NULL or non-NULL)
+ * is unchanged and the function returns a negative value.
+ * If a zero is returned for the name's length, then there is no pathname
+ * associated with the index.
+ *
+ *-------------------------------------------------------------------------
+ */
+ssize_t
+H5PLget(unsigned int index, char *pathname/*out*/, size_t size)
+{
+ ssize_t ret_value = 0; /* Return value */
+ ssize_t len = 0; /* Length of pathname */
+ char *dl_path = NULL;
+
+ FUNC_ENTER_API(FAIL)
+ if(H5PL_num_paths_g == 0)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_NOSPACE, FAIL, "no directories in table")
+ if(index >= H5PL_MAX_PATH_NUM)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_NOSPACE, FAIL, "index path out of bounds for table")
+ if(NULL == (dl_path = H5PL_path_table_g[index]))
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "no directory path at index")
+ len = HDstrlen(dl_path);
+ if(pathname) {
+ HDstrncpy(pathname, dl_path, MIN((size_t)(len + 1), size));
+ if((size_t)len >= size)
+ pathname[size - 1] = '\0';
+ } /* end if */
+
+ /* Set return value */
+ ret_value = len;
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5PLget() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PLsize
+ *
+ * Purpose: Query the size of the current list of plugin paths.
+ *
+ * Return: Non-negative or success.
+ *
+ *-------------------------------------------------------------------------
+ */
+unsigned int
+H5PLsize(void)
+{
+ return (unsigned int)H5PL_num_paths_g;
+} /* end H5PLsize() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5PL__init_path_table
*
* Purpose: Initialize the path table.
@@ -422,25 +678,7 @@ H5PL__init_path_table(void)
if(NULL == dl_path)
HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't allocate memory for path")
-#ifdef H5_HAVE_WIN32_API
- else { /* Expand windows env var*/
- long bufCharCount;
- char *tempbuf;
- if(NULL == (tempbuf = (char *)H5MM_malloc(H5PL_EXPAND_BUFFER_SIZE)))
- HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't allocate memory for expanded path")
- if((bufCharCount = ExpandEnvironmentStrings(dl_path, tempbuf, H5PL_EXPAND_BUFFER_SIZE)) > H5PL_EXPAND_BUFFER_SIZE) {
- tempbuf = (char *)H5MM_xfree(tempbuf);
- HGOTO_ERROR(H5E_PLUGIN, H5E_NOSPACE, FAIL, "expanded path is too long")
- }
- if(bufCharCount == 0) {
- tempbuf = (char *)H5MM_xfree(tempbuf);
- HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "failed to expand path")
- }
- dl_path = (char *)H5MM_xfree(dl_path);
- dl_path = H5MM_strdup(tempbuf);
- tempbuf = (char *)H5MM_xfree(tempbuf);
- }
-#endif /* H5_HAVE_WIN32_API */
+ H5PL_EXPAND_ENV_VAR
/* Put paths in the path table. They are separated by ":" */
dir = HDstrtok(dl_path, H5PL_PATH_SEPARATOR);
diff --git a/src/H5PLpkg.h b/src/H5PLpkg.h
new file mode 100644
index 0000000..5cf3096
--- /dev/null
+++ b/src/H5PLpkg.h
@@ -0,0 +1,50 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#if !(defined H5PL_FRIEND || defined H5PL_MODULE)
+#error "Do not include this file outside the H5PL package!"
+#endif
+
+#ifndef _H5PLpkg_H
+#define _H5PLpkg_H
+
+/* Include private header file */
+#include "H5PLprivate.h" /* Filter functions */
+
+/* Other private headers needed by this file */
+
+/**************************/
+/* Package Private Macros */
+/**************************/
+
+#define H5PL_MAX_PATH_NUM 16
+
+
+/****************************/
+/* Package Private Typedefs */
+/****************************/
+
+
+/*****************************/
+/* Package Private Variables */
+/*****************************/
+
+
+/******************************/
+/* Package Private Prototypes */
+/******************************/
+
+#endif /* _H5PLpkg_H */
+
diff --git a/src/H5PLpublic.h b/src/H5PLpublic.h
index 0528945..5e4dcae 100644
--- a/src/H5PLpublic.h
+++ b/src/H5PLpublic.h
@@ -44,6 +44,13 @@ extern "C" {
/* plugin state */
H5_DLL herr_t H5PLset_loading_state(unsigned int plugin_type);
H5_DLL herr_t H5PLget_loading_state(unsigned int* plugin_type/*out*/);
+H5_DLL herr_t H5PLappend(const char* plugin_path);
+H5_DLL herr_t H5PLprepend(const char* plugin_path);
+H5_DLL herr_t H5PLreplace(const char* plugin_path, unsigned int index);
+H5_DLL herr_t H5PLinsert(const char* plugin_path, unsigned int index);
+H5_DLL herr_t H5PLremove(unsigned int index);
+H5_DLL ssize_t H5PLget(unsigned int index, char *pathname/*out*/, size_t size);
+H5_DLL unsigned int H5PLsize(void);
#ifdef __cplusplus
}