summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDana Robinson <derobins@hdfgroup.org>2017-08-01 16:02:41 (GMT)
committerDana Robinson <derobins@hdfgroup.org>2017-08-01 16:02:41 (GMT)
commit464926f2a3adf3ef1c1e3ae60105544f08ff1e51 (patch)
tree31ad5d96c432f466844091a51e732b75ef3c6a00
parent80745c75087fc30200fd6a6ceed4ce94378ee0ee (diff)
parent9bcf8b2f2568083449ae3f9b6c2efbf6ed7f413a (diff)
downloadhdf5-464926f2a3adf3ef1c1e3ae60105544f08ff1e51.zip
hdf5-464926f2a3adf3ef1c1e3ae60105544f08ff1e51.tar.gz
hdf5-464926f2a3adf3ef1c1e3ae60105544f08ff1e51.tar.bz2
Merge pull request #621 in HDFFV/hdf5 from ~DEROBINS/hdf5_der:h5pl_commit to develop
* commit '9bcf8b2f2568083449ae3f9b6c2efbf6ed7f413a': Minor tweaks in response to code review. Fixed a failing Java plugin test. Major rework of H5PL package code before bringing VOL changes over.
-rw-r--r--MANIFEST3
-rwxr-xr-xbin/trace4
-rw-r--r--java/test/TestH5PL.java88
-rw-r--r--src/CMakeLists.txt3
-rw-r--r--src/H5PL.c987
-rw-r--r--src/H5PLextern.h4
-rw-r--r--src/H5PLint.c381
-rw-r--r--src/H5PLmodule.h10
-rw-r--r--src/H5PLpath.c776
-rw-r--r--src/H5PLpkg.h113
-rw-r--r--src/H5PLplugin_cache.c308
-rw-r--r--src/H5PLprivate.h4
-rw-r--r--src/H5PLpublic.h34
-rw-r--r--src/H5system.c46
-rw-r--r--src/H5win32defs.h1
-rw-r--r--src/Makefile.am2
-rw-r--r--test/plugin.c486
17 files changed, 2235 insertions, 1015 deletions
diff --git a/MANIFEST b/MANIFEST
index e5a038d..c7729e8 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -799,8 +799,11 @@
./src/H5PBpkg.h
./src/H5PBprivate.h
./src/H5PL.c
+./src/H5PLint.c
./src/H5PLmodule.h
+./src/H5PLpath.c
./src/H5PLpkg.h
+./src/H5PLplugin_cache.c
./src/H5PLprivate.h
./src/H5PLpublic.h
./src/H5PLextern.h
diff --git a/bin/trace b/bin/trace
index 3f532ab..cf41238 100755
--- a/bin/trace
+++ b/bin/trace
@@ -76,7 +76,7 @@ $Source = "";
"off_t" => "o",
"H5O_type_t" => "Ot",
"H5P_class_t" => "p",
- "hobj_ref_t" => "r",
+ "hobj_ref_t" => "r",
"H5R_type_t" => "Rt",
"char" => "s",
"unsigned char" => "s",
@@ -124,7 +124,7 @@ $Source = "";
"H5G_iterate_t" => "x",
"H5G_info_t" => "x",
"H5I_free_t" => "x",
- "H5I_search_func_t" => "x",
+ "H5I_search_func_t" => "x",
"H5L_class_t" => "x",
"H5L_elink_traverse_t" => "x",
"H5L_iterate_t" => "x",
diff --git a/java/test/TestH5PL.java b/java/test/TestH5PL.java
index aa59478..8ce708b 100644
--- a/java/test/TestH5PL.java
+++ b/java/test/TestH5PL.java
@@ -70,26 +70,74 @@ public class TestH5PL {
@Test
public void TestH5PLpaths() {
try {
- int original_entries = H5.H5PLsize();
- H5.H5PLappend("path_one");
- int plugin_entries = H5.H5PLsize();
- assertTrue("H5.H5PLsize: "+plugin_entries, (original_entries+1) == plugin_entries);
- H5.H5PLprepend("path_two");
- plugin_entries = H5.H5PLsize();
- assertTrue("H5.H5PLsize: "+plugin_entries, (original_entries+2) == plugin_entries);
- H5.H5PLinsert("path_three", original_entries);
- plugin_entries = H5.H5PLsize();
- assertTrue("H5.H5PLsize: "+plugin_entries, (original_entries+3) == plugin_entries);
- String first_path = H5.H5PLget(original_entries);
- assertTrue("First path was : "+first_path + " ",first_path.compareToIgnoreCase("path_three")==0);
- H5.H5PLreplace("path_four", original_entries);
- first_path = H5.H5PLget(original_entries);
- assertTrue("First path changed to : "+first_path + " ",first_path.compareToIgnoreCase("path_four")==0);
- H5.H5PLremove(original_entries);
- first_path = H5.H5PLget(original_entries);
- assertTrue("First path now : "+first_path + " ",first_path.compareToIgnoreCase("path_two")==0);
- plugin_entries = H5.H5PLsize();
- assertTrue("H5.H5PLsize: "+plugin_entries, (original_entries+2) == plugin_entries);
+ // Get the original number of paths
+ int nStartPaths = H5.H5PLsize();
+
+ int nPaths; /* # paths from H5PLSize() */
+ int nTruePaths = nStartPaths; /* What the # paths should be */
+ int index; /* Path table index */
+ String path; /* Path from H5PLget() */
+
+ // APPEND a path and ensure it was added correctly
+ String pathAppend = "path_append";
+ H5.H5PLappend(pathAppend);
+
+ nPaths = H5.H5PLsize();
+ nTruePaths++;
+ assertTrue("# paths should be " + nTruePaths + " but was " + nPaths, nTruePaths == nPaths);
+
+ index = nTruePaths - 1;
+ path = H5.H5PLget(index);
+ assertTrue("Path should be " + pathAppend + " but was " + path, path.compareToIgnoreCase(pathAppend) == 0);
+
+ // PREPEND a path and ensure it was added correctly
+ String pathPrepend = "path_prepend";
+ H5.H5PLprepend(pathPrepend);
+
+ nPaths = H5.H5PLsize();
+ nTruePaths++;
+ assertTrue("# paths should be " + nTruePaths + " but was " + nPaths, nTruePaths == nPaths);
+
+ index = 0;
+ path = H5.H5PLget(index);
+ assertTrue("Path should be " + pathPrepend + " but was " + path, path.compareToIgnoreCase(pathPrepend) == 0);
+
+ // INSERT a path and ensure it was added correctly
+ // Inserting at the index == # of start paths ensures we're in the middle
+ String pathInsert = "path_insert";
+ index = nStartPaths;
+ H5.H5PLinsert(pathInsert, index);
+
+ nPaths = H5.H5PLsize();
+ nTruePaths++;
+ assertTrue("# paths should be " + nTruePaths + " but was " + nPaths, nTruePaths == nPaths);
+
+ path = H5.H5PLget(index);
+ assertTrue("Path should be " + pathInsert + " but was " + path, path.compareToIgnoreCase(pathInsert) == 0);
+
+ // REPLACE the path we just added and ensure it updated correctly
+ String pathReplace = "path_replace";
+ index = nStartPaths;
+ H5.H5PLreplace(pathReplace, index);
+
+ nPaths = H5.H5PLsize();
+ assertTrue("# paths should be " + nTruePaths + " but was " + nPaths, nTruePaths == nPaths);
+
+ path = H5.H5PLget(index);
+ assertTrue("Path should be " + pathReplace + " but was " + path, path.compareToIgnoreCase(pathReplace) == 0);
+
+ // REMOVE the path we just replaced and check that the table was compacted
+ // The (index+1) path should move down to fill the space when the path is removed.
+ index = nStartPaths;
+ String pathRemove = H5.H5PLget(index + 1);
+ H5.H5PLremove(index);
+
+ nPaths = H5.H5PLsize();
+ nTruePaths--;
+ assertTrue("# paths should be " + nTruePaths + " but was " + nPaths, nTruePaths == nPaths);
+
+ path = H5.H5PLget(index);
+ assertTrue("Path should be " + pathRemove + " but was " + path, path.compareToIgnoreCase(pathRemove) == 0);
}
catch (Throwable err) {
err.printStackTrace();
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 178c954..96ea589 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -516,6 +516,9 @@ IDE_GENERATED_PROPERTIES ("H5PB" "${H5PB_HDRS}" "${H5PB_SOURCES}" )
set (H5PL_SOURCES
${HDF5_SRC_DIR}/H5PL.c
+ ${HDF5_SRC_DIR}/H5PLint.c
+ ${HDF5_SRC_DIR}/H5PLpath.c
+ ${HDF5_SRC_DIR}/H5PLplugin_cache.c
)
set (H5PL_HDRS
diff --git a/src/H5PL.c b/src/H5PL.c
index 65d6c91..fc42554 100644
--- a/src/H5PL.c
+++ b/src/H5PL.c
@@ -22,135 +22,28 @@
/***********/
#include "H5private.h" /* Generic Functions */
#include "H5Eprivate.h" /* Error handling */
-#include "H5MMprivate.h" /* Memory management */
#include "H5PLpkg.h" /* Plugin */
-#include "H5Zprivate.h" /* Filter pipeline */
/****************/
/* Local Macros */
/****************/
-#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
- * both Windows and Unix */
-/****************************/
-/* Windows support
- *
- * SPECIAL WINDOWS NOTE
- *
- * Some of the Win32 API functions expand to fooA or fooW depending on
- * whether UNICODE or _UNICODE are defined. You MUST explicitly use
- * the A version of the functions to force char * behavior until we
- * work out a scheme for proper Windows Unicode support.
- *
- * If you do not do this, people will be unable to incorporate our
- * source code into their own CMake builds if they define UNICODE.
- */
-#ifdef H5_HAVE_WIN32_API
-
-#define H5PL_PATH_SEPARATOR ";"
-
-/* Handle for dynamic library */
-#define H5PL_HANDLE HINSTANCE
-
-/* Get a handle to a plugin library. Windows: TEXT macro handles Unicode strings */
-#define H5PL_OPEN_DLIB(S) LoadLibraryExA(S, NULL, LOAD_WITH_ALTERED_SEARCH_PATH)
-
-/* Get the address of a symbol in dynamic library */
-#define H5PL_GET_LIB_FUNC(H,N) GetProcAddress(H,N)
-
-/* Close dynamic library */
-#define H5PL_CLOSE_LIB(H) FreeLibrary(H)
-
-/* Clear error - nothing to do */
-#define H5PL_CLR_ERROR
-
-/* maximum size for expanding env vars */
-#define H5PL_EXPAND_BUFFER_SIZE 32767
-
-typedef const void *(__cdecl *H5PL_get_plugin_info_t)(void);
-
-/* Unix support */
-#else /* H5_HAVE_WIN32_API */
-
-#define H5PL_PATH_SEPARATOR ":"
-
-/* Handle for dynamic library */
-#define H5PL_HANDLE void *
-
-/* Get a handle to a plugin library. Windows: TEXT macro handles Unicode strings */
-#define H5PL_OPEN_DLIB(S) dlopen(S, RTLD_LAZY)
-
-/* Get the address of a symbol in dynamic library */
-#define H5PL_GET_LIB_FUNC(H,N) dlsym(H,N)
-
-/* Close dynamic library */
-#define H5PL_CLOSE_LIB(H) dlclose(H)
-
-/* Clear error */
-#define H5PL_CLR_ERROR HERROR(H5E_PLUGIN, H5E_CANTGET, "can't dlopen:%s", dlerror())
-
-typedef const void *(*H5PL_get_plugin_info_t)(void);
-#endif /* H5_HAVE_WIN32_API */
-
-/* Whether to preload pathnames for plugin libraries */
-#define H5PL_DEFAULT_PATH H5_DEFAULT_PLUGINDIR
-
-/* Special symbol to indicate no plugin loading */
-#define H5PL_NO_PLUGIN "::"
/******************/
/* Local Typedefs */
/******************/
-/* Type for the list of info for opened plugin libraries */
-typedef struct H5PL_table_t {
- H5PL_type_t pl_type; /* plugin type */
- int pl_id; /* ID for the plugin */
- H5PL_HANDLE handle; /* plugin handle */
-} H5PL_table_t;
-
/********************/
/* Local Prototypes */
/********************/
-static herr_t H5PL__init_path_table(void);
-static htri_t H5PL__find(H5PL_type_t plugin_type, int type_id, char *dir, const void **info);
-static htri_t H5PL__open(H5PL_type_t pl_type, char *libname, int plugin_id, const void **pl_info);
-static htri_t H5PL__search_table(H5PL_type_t plugin_type, int type_id, const void **info);
-static herr_t H5PL__close(H5PL_HANDLE handle);
-
/*********************/
/* Package Variables */
/*********************/
-/* Package initialization variable */
-hbool_t H5_PKG_INIT_VAR = FALSE;
-
/*****************************/
/* Library Private Variables */
@@ -161,145 +54,43 @@ hbool_t H5_PKG_INIT_VAR = FALSE;
/* Local Variables */
/*******************/
-/* Table for opened plugin libraries */
-static size_t H5PL_table_alloc_g = 0;
-static size_t H5PL_table_used_g = 0;
-static H5PL_table_t *H5PL_table_g = NULL;
-
-/* Table of location paths for plugin libraries */
-static char *H5PL_path_table_g[H5PL_MAX_PATH_NUM];
-static size_t H5PL_num_paths_g = 0;
-static hbool_t H5PL_path_found_g = FALSE;
-
-/* Enable all plugin libraries */
-static unsigned int H5PL_plugin_g = H5PL_ALL_PLUGIN;
-
-
-
-/*--------------------------------------------------------------------------
-NAME
- H5PL__init_package -- Initialize interface-specific information
-USAGE
- herr_t H5PL__init_package()
-RETURNS
- Non-negative on success/Negative on failure
-DESCRIPTION
- Initializes any interface-specific data or routines.
-
---------------------------------------------------------------------------*/
-herr_t
-H5PL__init_package(void)
-{
- char *preload_path;
-
- FUNC_ENTER_PACKAGE_NOERR
-
- /* Retrieve pathnames from HDF5_PLUGIN_PRELOAD if the user sets it
- * to tell the library to load plugin libraries without search.
- */
- if(NULL != (preload_path = HDgetenv("HDF5_PLUGIN_PRELOAD")))
- /* Special symbol "::" means no plugin during data reading. */
- if(!HDstrcmp(preload_path, H5PL_NO_PLUGIN))
- H5PL_plugin_g = 0;
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5PL__init_package() */
/*-------------------------------------------------------------------------
- * Function: H5PL_term_package
- *
- * Purpose: Terminate the H5PL interface: release all memory, reset all
- * global variables to initial values. This only happens if all
- * types have been destroyed from other interfaces.
+ * Function: H5PLset_loading_state
*
- * Return: Success: Positive if any action was taken that might
- * affect some other interface; zero otherwise.
- * Failure: Negative.
- *
- * Programmer: Raymond Lu
- * 20 February 2013
- *
- *-------------------------------------------------------------------------
- */
-int
-H5PL_term_package(void)
-{
- int n = 0;
-
- FUNC_ENTER_NOAPI_NOINIT_NOERR
-
- if(H5_PKG_INIT_VAR) {
- size_t u; /* Local index variable */
-
- /* Close opened dynamic libraries */
- if(H5PL_table_g) {
- for(u = 0; u < H5PL_table_used_g; u++)
- H5PL__close((H5PL_table_g[u]).handle);
-
- /* Free the table of dynamic libraries */
- H5PL_table_g = (H5PL_table_t *)H5MM_xfree(H5PL_table_g);
- H5PL_table_used_g = H5PL_table_alloc_g = 0;
-
- n++;
- } /* end if */
-
- /* Free the table of search paths */
- if(H5PL_num_paths_g > 0) {
- for(u = 0; u < H5PL_num_paths_g; u++)
- if(H5PL_path_table_g[u])
- H5PL_path_table_g[u] = (char *)H5MM_xfree(H5PL_path_table_g[u]);
- H5PL_num_paths_g = 0;
- H5PL_path_found_g = FALSE;
-
- n++;
- } /* end if */
-
- /* Mark the interface as uninitialized */
- if(0 == n)
- H5_PKG_INIT_VAR = FALSE;
- } /* end if */
-
- FUNC_LEAVE_NOAPI(n)
-} /* end H5PL_term_package() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5PLset_loading_state
+ * Purpose: Control the loading of dynamic plugin types.
*
- * Purpose: Control the loading of dynamic plugin types.
+ * The plugin_control_mask parameter is a bitfield that controls
+ * whether certain classes of plugins (e.g.: filters,
+ * VOL drivers) will be loaded by the library.
*
- * This function will not allow plugin types if the pathname from the HDF5_PLUGIN_PRELOAD
- * environment variable is set to the special "::" string.
+ * plugin bit = 0, will prevent the use of that dynamic plugin type.
+ * plugin bit = 1, will allow the use of that dynamic plugin type.
*
- * plugin bit = 0, will prevent the use of that dynamic plugin type.
- * plugin bit = 1, will allow the use of that dynamic plugin type.
+ * A list of pre-defined masks can be found in H5PLpublic.h.
+ * Set the mask to 0 to disable all plugins.
*
- * H5PL_TYPE_FILTER changes just dynamic filters
- * A H5PL_ALL_PLUGIN will enable all dynamic plugin types
- * A zero value will disable all dynamic plugin types
+ * This function will not allow plugin types if the pathname
+ * from the HDF5_PLUGIN_PRELOAD environment variable is set to
+ * the special "::" string.
*
- * Return: Non-negative or success
+ * Return: Success: Non-negative
+ * Failture: Negative
*
*-------------------------------------------------------------------------
*/
herr_t
-H5PLset_loading_state(unsigned int plugin_type)
+H5PLset_loading_state(unsigned int plugin_control_mask)
{
- char *preload_path;
- herr_t ret_value = SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
- H5TRACE1("e", "Iu", plugin_type);
-
- /* change the bit value of the requested plugin type(s) */
- H5PL_plugin_g = plugin_type;
+ H5TRACE1("e", "Iu", plugin_control_mask);
- /* check if special ENV variable is set and disable all plugin types */
- if(NULL != (preload_path = HDgetenv("HDF5_PLUGIN_PRELOAD")))
- /* Special symbol "::" means no plugin during data reading. */
- if(!HDstrcmp(preload_path, H5PL_NO_PLUGIN))
- H5PL_plugin_g = 0;
+ /* Set the plugin control mask */
+ if(H5PL__set_plugin_control_mask(plugin_control_mask) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTSET, FAIL, "error setting plugin control mask")
done:
FUNC_LEAVE_API(ret_value)
@@ -307,27 +98,35 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5PLget_loading_state
+ * Function: H5PLget_loading_state
*
- * Purpose: Query state of the loading of dynamic plugin types.
+ * Purpose: Get the bitmask that controls whether certain classes
+ * of plugins (e.g.: filters, VOL drivers) will be loaded
+ * by the library.
*
- * This function will return the state of the global flag.
+ * Zero if all plugin types are disabled
+ * Negative if all plugin types are enabled
+ * Positive if one or more of the plugin types are enabled
*
- * Return: Zero if all plugin types are disabled, negative if all
- * plugin types are enabled, positive if one or more of the plugin types are enabled.
+ * Return: Success: Non-negative
+ * Failture: Negative
*
*-------------------------------------------------------------------------
*/
herr_t
-H5PLget_loading_state(unsigned int *plugin_type)
+H5PLget_loading_state(unsigned int *plugin_control_mask)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
- H5TRACE1("e", "*Iu", plugin_type);
+ H5TRACE1("e", "*Iu", plugin_control_mask);
+
+ if (NULL == plugin_control_mask)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "plugin_control_mask parameter cannot be NULL")
- if(plugin_type)
- *plugin_type = H5PL_plugin_g;
+ /* Set the plugin control mask */
+ if(H5PL__get_plugin_control_mask(plugin_control_mask) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTGET, FAIL, "error getting plugin control mask")
done:
FUNC_LEAVE_API(ret_value)
@@ -335,674 +134,282 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5PL_load
- *
- * Purpose: Given the plugin type and identifier, this function searches
- * and/or loads a dynamic plugin library first among the already
- * opened libraries then in the designated location paths.
- *
- * Return: Non-NULL on success/NULL on failure
- *
- * Programmer: Raymond Lu
- * 13 February 2013
- *
- *-------------------------------------------------------------------------
- */
-const void *
-H5PL_load(H5PL_type_t type, int id)
-{
- htri_t found; /* Whether the plugin was found */
- const void *plugin_info = NULL;
- const void *ret_value = NULL;
-
- FUNC_ENTER_NOAPI(NULL)
-
- switch(type) {
- case H5PL_TYPE_FILTER:
- if((H5PL_plugin_g & H5PL_FILTER_PLUGIN) == 0)
- HGOTO_ERROR(H5E_PLUGIN, H5E_CANTLOAD, NULL, "required dynamically loaded plugin filter '%d' is not available", id)
- break;
-
- case H5PL_TYPE_ERROR:
- case H5PL_TYPE_NONE:
- default:
- HGOTO_ERROR(H5E_PLUGIN, H5E_CANTLOAD, NULL, "required dynamically loaded plugin '%d' is not valid", id)
- } /* end switch */
-
- /* Initialize the location paths for dynamic libraries, if they aren't
- * already set up.
- */
- if(FALSE == H5PL_path_found_g)
- if(H5PL__init_path_table() < 0)
- HGOTO_ERROR(H5E_PLUGIN, H5E_CANTINIT, NULL, "can't initialize search path table")
-
- /* Search in the table of already loaded plugin libraries */
- if((found = H5PL__search_table(type, id, &plugin_info)) < 0)
- HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, NULL, "search in table failed")
-
- /* If not found, iterate through the path table to find the right dynamic library */
- if(!found) {
- size_t i; /* Local index variable */
-
- for(i = 0; i < H5PL_num_paths_g; i++) {
- if((found = H5PL__find(type, id, H5PL_path_table_g[i], &plugin_info)) < 0)
- HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, NULL, "search in paths failed")
-
- /* Break out if found */
- if(found) {
- HDassert(plugin_info);
- break;
- } /* end if */
- } /* end for */
- } /* end if */
-
- /* Check if we found the plugin */
- if(found)
- ret_value = plugin_info;
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5PL_load() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5PLappend
+ * Function: H5PLappend
*
- * Purpose: Insert a plugin path at the end of the list.
+ * Purpose: Insert a plugin search path at the end of the list.
*
- * Return: Non-negative or success.
+ * Return: Success: Non-negative
+ * Failture: Negative
*
*-------------------------------------------------------------------------
*/
herr_t
-H5PLappend(const char *plugin_path)
+H5PLappend(const char *search_path)
{
herr_t ret_value = SUCCEED; /* Return value */
- char *dl_path = NULL;
FUNC_ENTER_API(FAIL)
- H5TRACE1("e", "*s", plugin_path);
- 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")
+ H5TRACE1("e", "*s", search_path);
- H5PL_EXPAND_ENV_VAR
+ /* Check args */
+ if (NULL == search_path)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "plugin_path parameter cannot be NULL")
+ if (0 == HDstrlen(search_path))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "plugin_path parameter cannot have length zero")
- H5PL_path_table_g[H5PL_num_paths_g] = dl_path;
- H5PL_num_paths_g++;
+ /* Append the search path to the path table */
+ if (H5PL__append_path(search_path) < 0)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTAPPEND, FAIL, "unable to append search path")
done:
FUNC_LEAVE_API(ret_value)
} /* end H5PLappend() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5PLprepend
+ * Function: H5PLprepend
*
- * Purpose: Insert a plugin path at the beginning of the list.
+ * Purpose: Insert a plugin search path at the beginning of the list.
*
- * Return: Non-negative or success.
+ * Return: Success: Non-negative
+ * Failture: Negative
*
*-------------------------------------------------------------------------
*/
herr_t
-H5PLprepend(const char *plugin_path)
+H5PLprepend(const char *search_path)
{
herr_t ret_value = SUCCEED; /* Return value */
- char *dl_path = NULL;
- unsigned int plindex;
FUNC_ENTER_API(FAIL)
- H5TRACE1("e", "*s", plugin_path);
- 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")
+ H5TRACE1("e", "*s", search_path);
- H5PL_EXPAND_ENV_VAR
+ /* Check args */
+ if (NULL == search_path)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "plugin_path parameter cannot be NULL")
+ if (0 == HDstrlen(search_path))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "plugin_path parameter cannot have length zero")
- 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++;
+ /* Prepend the search path to the path table */
+ if (H5PL__prepend_path(search_path) < 0)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTINSERT, FAIL, "unable to prepend search path")
done:
FUNC_LEAVE_API(ret_value)
} /* end H5PLprepend() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5PLreplace
+ * Function: H5PLreplace
*
- * Purpose: Replace the path at the specified index.
+ * Purpose: Replace the path at the specified index. The path at the
+ * index must exist.
*
- * Return: Non-negative or success.
+ * Return: Non-negative or success.
*
*-------------------------------------------------------------------------
*/
herr_t
-H5PLreplace(const char *plugin_path, unsigned int index)
+H5PLreplace(const char *search_path, unsigned int index)
{
- herr_t ret_value = SUCCEED; /* Return value */
- char *dl_path = NULL;
+ unsigned num_paths; /* Current number of stored paths */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
- H5TRACE2("e", "*sIu", plugin_path, index);
- 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")
+ H5TRACE2("e", "*sIu", search_path, index);
- H5PL_EXPAND_ENV_VAR
+ /* Check args */
+ if (NULL == search_path)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "plugin_path parameter cannot be NULL")
+ if (0 == HDstrlen(search_path))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "plugin_path parameter cannot have length zero")
- 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;
+ /* Check index */
+ num_paths = H5PL__get_num_paths();
+ if (0 == num_paths)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "path table is empty")
+ else if (index >= num_paths)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "index path out of bounds for table - can't be more than %u", (num_paths - 1))
+
+ /* Insert the search path into the path table */
+ if (H5PL__replace_path(search_path, index) < 0)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTINSERT, FAIL, "unable to replace search path")
done:
FUNC_LEAVE_API(ret_value)
} /* end H5PLreplace() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5PLinsert
+ * Function: H5PLinsert
*
- * Purpose: Insert a plugin path at the specified index, moving other paths after the index.
+ * Purpose: Insert a plugin search path at the specified index, moving
+ * other paths after the index.
*
- * Return: Non-negative or success.
+ * Return: Success: Non-negative
+ * Failture: Negative
*
*-------------------------------------------------------------------------
*/
herr_t
-H5PLinsert(const char *plugin_path, unsigned int index)
+H5PLinsert(const char *search_path, unsigned int index)
{
- herr_t ret_value = SUCCEED; /* Return value */
- char *dl_path = NULL;
- unsigned int plindex;
+ unsigned num_paths; /* Current number of stored paths */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
- H5TRACE2("e", "*sIu", plugin_path, index);
- 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++;
+ H5TRACE2("e", "*sIu", search_path, index);
+
+ /* Check args */
+ if (NULL == search_path)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "plugin_path parameter cannot be NULL")
+ if (0 == HDstrlen(search_path))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "plugin_path parameter cannot have length zero")
+
+ /* Check index */
+ num_paths = H5PL__get_num_paths();
+ if ((0 != num_paths) && (index >= num_paths))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "index path out of bounds for table - can't be more than %u", (num_paths - 1))
+
+ /* Insert the search path into the path table */
+ if (H5PL__insert_path(search_path, index) < 0)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTINSERT, FAIL, "unable to insert search path")
done:
FUNC_LEAVE_API(ret_value)
} /* end H5PLinsert() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5PLremove
+ * Function: H5PLremove
+ *
+ * Purpose: Remove the plugin path at the specifed index and compact
+ * the list.
*
- * Purpose: Remove the plugin path at the specifed index and compacting the list.
+ * Return: Success: Non-negative
+ * Failture: Negative
*
- * Return: Non-negative or success.
+ * Return: Non-negative or success.
*
*-------------------------------------------------------------------------
*/
herr_t
H5PLremove(unsigned int index)
{
- herr_t ret_value = SUCCEED; /* Return value */
- unsigned int plindex;
+ unsigned num_paths; /* Current number of stored paths */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE1("e", "Iu", index);
- 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;
+
+ /* Check index */
+ num_paths = H5PL__get_num_paths();
+ if (0 == num_paths)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "path table is empty")
+ else if (index >= num_paths)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "index path out of bounds for table - can't be more than %u", (num_paths - 1))
+
+ /* Delete the search path from the path table */
+ if (H5PL__remove_path(index) < 0)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTDELETE, FAIL, "unable to remove search path")
done:
FUNC_LEAVE_API(ret_value)
} /* end H5PLremove() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5PLget
+ * Function: H5PLget
+ *
+ * Purpose: Query the plugin path at a specified index.
+ *
+ * If 'path_buf' is non-NULL then up to 'buf_size' bytes will be written into
+ * that buffer and the length of the path name will be returned.
*
- * Purpose: Query the plugin path at the specified index.
+ * If 'path_buf' is NULL, this function will simply return the number of
+ * characters required to store the path name, ignoring 'path_buf' and
+ * 'buf_size'
*
- * Return: Success: The length of path.
+ * If an error occurs then the buffer pointed to by 'path_buf'
+ * (NULL or non-NULL) will be unchanged and the function will return a
+ * negative value.
*
- * 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.
+ * If a zero is returned for the name's length, then there is no path name
+ * associated with the index and the 'path_buf' buffer will be unchanged.
+ *
+ * Return: Success: The length of path
+ * Failure: A negative value
*
*-------------------------------------------------------------------------
*/
ssize_t
-H5PLget(unsigned int index, char *pathname/*out*/, size_t size)
+H5PLget(unsigned int index, char *path_buf, size_t buf_size)
{
- ssize_t ret_value = 0; /* Return value */
- size_t len = 0; /* Length of pathname */
- char *dl_path = NULL;
+ unsigned num_paths; /* Current number of stored paths */
+ const char *path = NULL; /* path from table */
+ size_t path_len = 0; /* Length of path */
+ ssize_t ret_value = 0; /* Return value */
FUNC_ENTER_API(FAIL)
- H5TRACE3("Zs", "Iuxz", index, pathname, size);
- 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';
+ H5TRACE3("Zs", "Iu*sz", index, path_buf, buf_size);
+
+ /* Check index */
+ num_paths = H5PL__get_num_paths();
+ if (0 == num_paths)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "path table is empty")
+ else if (index >= num_paths)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "index path out of bounds for table - can't be more than %u", (num_paths - 1))
+
+ /* Check if the search table is empty */
+ if (H5PL__get_num_paths() == 0)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_NOSPACE, (-1), "plugin search path table is empty")
+
+ /* Get the path at the specified index and its length */
+ if (NULL == (path = H5PL__get_path(index)))
+ HGOTO_ERROR(H5E_PLUGIN, H5E_BADVALUE, (-1), "no path stored at that index")
+ path_len = HDstrlen(path);
+
+ /* If the path buffer is not NULL, copy the path to the buffer */
+ if (path_buf) {
+ HDstrncpy(path_buf, path, MIN((size_t)(path_len + 1), buf_size));
+ if ((size_t)path_len >= buf_size)
+ path_buf[buf_size - 1] = '\0';
} /* end if */
/* Set return value */
- ret_value = (ssize_t)len;
+ ret_value = (ssize_t)path_len;
done:
FUNC_LEAVE_API(ret_value)
} /* end H5PLget() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5PLsize
+ * Function: H5PLsize
*
- * Purpose: Query the size of the current list of plugin paths.
+ * Purpose: Get the number of stored plugin paths.
+ * XXX: This is a terrible name. Can it be changed?
*
- * Return: Plugin path size
+ * Return: SUCCEED/FAIL
*
*-------------------------------------------------------------------------
*/
herr_t
-H5PLsize(unsigned int *listsize)
+H5PLsize(unsigned int *num_paths)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
- H5TRACE1("e", "*Iu", listsize);
+ H5TRACE1("e", "*Iu", num_paths);
- *listsize = (unsigned int)H5PL_num_paths_g;
+ /* Check arguments */
+ if (!num_paths)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "num_paths parameter cannot be NULL")
+
+ /* Get the number of stored plugin paths */
+ *num_paths = H5PL__get_num_paths();
done:
FUNC_LEAVE_API(ret_value)
} /* end H5PLsize() */
-
-/*-------------------------------------------------------------------------
- * Function: H5PL__init_path_table
- *
- * Purpose: Initialize the path table.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * 18 March 2013
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5PL__init_path_table(void)
-{
- char *dl_path = NULL;
- char *origin_dl_path;
- char *dir;
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_STATIC
-
- /* Retrieve paths from HDF5_PLUGIN_PATH if the user sets it
- * or from the default paths if it isn't set.
- */
- origin_dl_path = HDgetenv("HDF5_PLUGIN_PATH");
- if(NULL == origin_dl_path)
- dl_path = H5MM_strdup(H5PL_DEFAULT_PATH);
- else
- dl_path = H5MM_strdup(origin_dl_path);
- if(NULL == dl_path)
- HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't allocate memory for path")
-
- H5PL_EXPAND_ENV_VAR
-
- /* Put paths in the path table. They are separated by ":" */
- dir = HDstrtok(dl_path, H5PL_PATH_SEPARATOR);
- while(dir) {
- /* Check for too many directories in path */
- 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 == (H5PL_path_table_g[H5PL_num_paths_g] = H5MM_strdup(dir)))
- HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't allocate memory for path")
- H5PL_num_paths_g++;
- dir = HDstrtok(NULL, H5PL_PATH_SEPARATOR);
- } /* end while */
-
- H5PL_path_found_g = TRUE;
-
-done:
- if(dl_path)
- dl_path = (char *)H5MM_xfree(dl_path);
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5PL__init_path_table() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5PL__find
- *
- * Purpose: Given a path, this function opens the directory and envokes
- * another function to go through all files to find the right
- * plugin library. Two function definitions are for Unix and
- * Windows.
- *
- * Return: TRUE on success,
- * FALSE on not found,
- * negative on failure
- *
- * Programmer: Raymond Lu
- * 13 February 2013
- *
- *-------------------------------------------------------------------------
- */
-#ifndef H5_HAVE_WIN32_API
-static htri_t
-H5PL__find(H5PL_type_t plugin_type, int type_id, char *dir, const void **info)
-{
- char *pathname = NULL;
- DIR *dirp = NULL;
- struct dirent *dp;
- htri_t ret_value = FALSE;
-
- FUNC_ENTER_STATIC
-
- /* Open the directory */
- if(!(dirp = HDopendir(dir)))
- HGOTO_ERROR(H5E_PLUGIN, H5E_OPENERROR, FAIL, "can't open directory: %s", dir)
-
- /* Iterates through all entries in the directory to find the right plugin library */
- while(NULL != (dp = HDreaddir(dirp))) {
- /* The library we are looking for should be called libxxx.so... on Unix
- * or libxxx.xxx.dylib on Mac.
- */
-#ifndef __CYGWIN__
- if(!HDstrncmp(dp->d_name, "lib", (size_t)3) &&
- (HDstrstr(dp->d_name, ".so") || HDstrstr(dp->d_name, ".dylib"))) {
-#else
- if(!HDstrncmp(dp->d_name, "cyg", (size_t)3) &&
- HDstrstr(dp->d_name, ".dll") ) {
-
-#endif
- h5_stat_t my_stat;
- size_t pathname_len;
- htri_t found_in_dir;
-
- /* Allocate & initialize the path name */
- pathname_len = HDstrlen(dir) + HDstrlen(dp->d_name) + 2;
- if(NULL == (pathname = (char *)H5MM_malloc(pathname_len)))
- HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't allocate memory for path")
- HDsnprintf(pathname, pathname_len, "%s/%s", dir, dp->d_name);
-
- /* Get info for directory entry */
- if(HDstat(pathname, &my_stat) == -1)
- HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't stat file: %s", HDstrerror(errno))
-
- /* If it is a directory, skip it */
- if(S_ISDIR(my_stat.st_mode))
- continue;
-
- /* Attempt to open the dynamic library as a filter library */
- if((found_in_dir = H5PL__open(plugin_type, pathname, type_id, info)) < 0)
- HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "search in directory failed")
- if(found_in_dir)
- HGOTO_DONE(TRUE) /* Indicate success */
- pathname = (char *)H5MM_xfree(pathname);
- } /* end if */
- } /* end while */
-
-done:
- if(dirp)
- if(HDclosedir(dirp) < 0)
- HDONE_ERROR(H5E_FILE, H5E_CLOSEERROR, FAIL, "can't close directory: %s", HDstrerror(errno))
- pathname = (char *)H5MM_xfree(pathname);
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5PL__find() */
-#else /* H5_HAVE_WIN32_API */
-static htri_t
-H5PL__find(H5PL_type_t plugin_type, int type_id, char *dir, const void **info)
-{
- WIN32_FIND_DATAA fdFile;
- HANDLE hFind;
- char *pathname = NULL;
- char service[2048];
- htri_t ret_value = FALSE;
-
- FUNC_ENTER_STATIC
-
- /* Specify a file mask. *.* = We want everything! */
- sprintf(service, "%s\\*.dll", dir);
- if((hFind = FindFirstFileA(service, &fdFile)) == INVALID_HANDLE_VALUE)
- HGOTO_ERROR(H5E_PLUGIN, H5E_OPENERROR, FAIL, "can't open directory")
-
- do {
- /* Find first file will always return "."
- * and ".." as the first two directories.
- */
- if(HDstrcmp(fdFile.cFileName, ".") != 0 && HDstrcmp(fdFile.cFileName, "..") != 0) {
- size_t pathname_len;
- htri_t found_in_dir;
-
- /* Allocate & initialize the path name */
- pathname_len = HDstrlen(dir) + HDstrlen(fdFile.cFileName) + 2;
- if(NULL == (pathname = (char *)H5MM_malloc(pathname_len)))
- HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't allocate memory for path")
- HDsnprintf(pathname, pathname_len, "%s\\%s", dir, fdFile.cFileName);
-
- /* Is the entity a File or Folder? */
- if(fdFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- continue;
-
- if((found_in_dir = H5PL__open(plugin_type, pathname, type_id, info)) < 0)
- HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "search in directory failed")
- if(found_in_dir)
- HGOTO_DONE(TRUE) /* Indicate success */
- pathname = (char *)H5MM_xfree(pathname);
- } /* end if */
- } while(FindNextFileA(hFind, &fdFile)); /* Find the next file. */
-
-done:
- if(hFind)
- FindClose(hFind);
- if(pathname)
- pathname = (char *)H5MM_xfree(pathname);
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5PL__find() */
-#endif /* H5_HAVE_WIN32_API */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5PL__open
- *
- * Purpose: Iterates through all files to find the right plugin library.
- * It loads the dynamic plugin library and keeps it on the list
- * of loaded libraries.
- *
- * Return: TRUE on success,
- * FALSE on not found,
- * negative on failure
- *
- * Programmer: Raymond Lu
- * 13 February 2013
- *
- *-------------------------------------------------------------------------
- */
-static htri_t
-H5PL__open(H5PL_type_t pl_type, char *libname, int pl_id, const void **pl_info)
-{
- H5PL_HANDLE handle = NULL;
- htri_t ret_value = FALSE;
-
- FUNC_ENTER_STATIC
-
- /* There are different reasons why a library can't be open, e.g. wrong architecture.
- * simply continue if we can't open it.
- */
- if(NULL == (handle = H5PL_OPEN_DLIB(libname))) {
- H5PL_CLR_ERROR; /* clear error */
- } /* end if */
- else {
- H5PL_get_plugin_info_t get_plugin_info = NULL;
-
- /* Return a handle for the function H5PLget_plugin_info in the dynamic library.
- * The plugin library is suppose to define this function.
- */
- if(NULL == (get_plugin_info = (H5PL_get_plugin_info_t)H5PL_GET_LIB_FUNC(handle, "H5PLget_plugin_info"))) {
- if(H5PL__close(handle) < 0)
- HGOTO_ERROR(H5E_PLUGIN, H5E_CLOSEERROR, FAIL, "can't close dynamic library")
- } /* end if */
- else {
- const H5Z_class2_t *plugin_info;
-
- /* Invoke H5PLget_plugin_info to verify this is the right library we are looking for.
- * Move on if it isn't.
- */
- if(NULL == (plugin_info = (const H5Z_class2_t *)(*get_plugin_info)())) {
- if(H5PL__close(handle) < 0)
- HGOTO_ERROR(H5E_PLUGIN, H5E_CLOSEERROR, FAIL, "can't close dynamic library")
- HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "can't get plugin info")
- } /* end if */
-
- /* Successfully found plugin library, check if it's the right one */
- if(plugin_info->id == pl_id) {
- /* Expand the table if it is too small */
- if(H5PL_table_used_g >= H5PL_table_alloc_g) {
- size_t n = MAX(H5Z_MAX_NFILTERS, 2 * H5PL_table_alloc_g);
- H5PL_table_t *table = (H5PL_table_t *)H5MM_realloc(H5PL_table_g, n * sizeof(H5PL_table_t));
-
- if(!table)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "unable to extend dynamic library table")
-
- H5PL_table_g = table;
- H5PL_table_alloc_g = n;
- } /* end if */
-
- (H5PL_table_g[H5PL_table_used_g]).handle = handle;
- (H5PL_table_g[H5PL_table_used_g]).pl_type = pl_type;
- (H5PL_table_g[H5PL_table_used_g]).pl_id = plugin_info->id;
- H5PL_table_used_g++;
-
- /* Set the plugin info to return */
- *pl_info = (const void *)plugin_info;
-
- /* Indicate success */
- ret_value = TRUE;
- } /* end if */
- else
- if(H5PL__close(handle) < 0)
- HGOTO_ERROR(H5E_PLUGIN, H5E_CLOSEERROR, FAIL, "can't close dynamic library")
- } /* end if */
- } /* end else */
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5PL__open() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5PL__search_table
- *
- * Purpose: Search in the list of already opened dynamic libraries
- * to see if the one we are looking for is already opened.
- *
- * Return: TRUE on success,
- * FALSE on not found,
- * Negative on failure
- *
- * Programmer: Raymond Lu
- * 13 February 2013
- *
- *-------------------------------------------------------------------------
- */
-static htri_t
-H5PL__search_table(H5PL_type_t plugin_type, int type_id, const void **info)
-{
- htri_t ret_value = FALSE;
-
- FUNC_ENTER_STATIC
-
- /* Search in the table of already opened dynamic libraries */
- if(H5PL_table_used_g > 0) {
- size_t i;
-
- for(i = 0; i < H5PL_table_used_g; i++) {
- if((plugin_type == (H5PL_table_g[i]).pl_type) && (type_id == (H5PL_table_g[i]).pl_id)) {
- H5PL_get_plugin_info_t get_plugin_info;
- const H5Z_class2_t *plugin_info;
-
- if(NULL == (get_plugin_info = (H5PL_get_plugin_info_t)H5PL_GET_LIB_FUNC((H5PL_table_g[i]).handle, "H5PLget_plugin_info")))
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "can't get function for H5PLget_plugin_info")
-
- if(NULL == (plugin_info = (const H5Z_class2_t *)(*get_plugin_info)()))
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "can't get plugin info")
-
- *info = plugin_info;
- HGOTO_DONE(TRUE)
- } /* end if */
- } /* end for */
- } /* end if */
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5PL__search_table() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5PL__close
- *
- * Purpose: Closes the handle for dynamic library
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Raymond Lu
- * 13 February 2013
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5PL__close(H5PL_HANDLE handle)
-{
- FUNC_ENTER_STATIC_NOERR
-
- H5PL_CLOSE_LIB(handle);
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5PL__close() */
-
diff --git a/src/H5PLextern.h b/src/H5PLextern.h
index 7547ad7..cd5464d 100644
--- a/src/H5PLextern.h
+++ b/src/H5PLextern.h
@@ -11,9 +11,9 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
- * Programmer: Raymond Lu <songyulu@hdfgroup.org>
- * 13 February 2013
+ * Purpose: Header file for writing external HDF5 plugins.
*/
+
#ifndef _H5PLextern_H
#define _H5PLextern_H
diff --git a/src/H5PLint.c b/src/H5PLint.c
new file mode 100644
index 0000000..bd6bf7d
--- /dev/null
+++ b/src/H5PLint.c
@@ -0,0 +1,381 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Purpose: Internal routines for managing plugins.
+ *
+ */
+
+
+/****************/
+/* Module Setup */
+/****************/
+
+#include "H5PLmodule.h" /* This source code file is part of the H5PL module */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5MMprivate.h" /* Memory management */
+#include "H5PLpkg.h" /* Plugin */
+#include "H5Zprivate.h" /* Filter pipeline */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+/* Package initialization variable */
+hbool_t H5_PKG_INIT_VAR = FALSE;
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* Bitmask that controls whether classes of plugins
+ * (e.g.: filters, VOL drivers) can be loaded.
+ */
+static unsigned int H5PL_plugin_control_mask_g = H5PL_ALL_PLUGIN;
+
+/* This flag will be set to FALSE if the HDF5_PLUGIN_PRELOAD
+ * environment variable was set to H5PL_NO_PLUGIN at
+ * package initialization.
+ */
+static hbool_t H5PL_allow_plugins_g = TRUE;
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PL__get_plugin_control_mask
+ *
+ * Purpose: Gets the internal plugin control mask value.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5PL__get_plugin_control_mask(unsigned int *mask /*out*/)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE_NOERR
+
+ /* Check args - Just assert on package functions */
+ HDassert(mask);
+
+ /* Return the mask */
+ *mask = H5PL_plugin_control_mask_g;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* end H5PL__get_plugin_control_mask() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PL__set_plugin_control_mask
+ *
+ * Purpose: Sets the internal plugin control mask value.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5PL__set_plugin_control_mask(unsigned int mask)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE_NOERR
+
+ /* Only allow setting this if plugins have not been disabled.
+ * XXX: Note that we don't consider this an error, but instead
+ * silently ignore it. We may want to consider this behavior
+ * more carefully.
+ */
+ if (H5PL_allow_plugins_g)
+ H5PL_plugin_control_mask_g = mask;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* end H5PL__set_plugin_control_mask() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PL__init_package
+ *
+ * Purpose: Initialize any package-specific data and call any init
+ * routines for the package.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5PL__init_package(void)
+{
+ char *env_var = NULL;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_PACKAGE
+
+ /* Check the environment variable to determine if the user wants
+ * to ignore plugins. The special symbol H5PL_NO_PLUGIN (defined in
+ * H5PLpublic.h) means we don't want to load plugins.
+ */
+ if (NULL != (env_var = HDgetenv("HDF5_PLUGIN_PRELOAD")))
+ if (!HDstrcmp(env_var, H5PL_NO_PLUGIN)) {
+ H5PL_plugin_control_mask_g = 0;
+ H5PL_allow_plugins_g = FALSE;
+ }
+
+ /* Create the table of previously-loaded plugins */
+ if (H5PL__create_plugin_cache() < 0)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTINIT, FAIL, "can't create plugin cache")
+
+ /* Create the table of search paths for dynamic libraries */
+ if (H5PL__create_path_table() < 0)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTINIT, FAIL, "can't create plugin search path table")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5PL__init_package() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PL_term_package
+ *
+ * Purpose: Terminate the H5PL interface: release all memory, reset all
+ * global variables to initial values. This only happens if all
+ * types have been destroyed from other interfaces.
+ *
+ * Return: Success: Positive if any action was taken that might
+ * affect some other interface; zero otherwise
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+H5PL_term_package(void)
+{
+ hbool_t already_closed = FALSE;
+ int ret_value = 0;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ if (H5_PKG_INIT_VAR) {
+
+ /* Close the plugin cache.
+ * We need to bump the return value if we did any real work here.
+ */
+ if (H5PL__close_plugin_cache(&already_closed) < 0)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTFREE, (-1), "problem closing plugin cache")
+ if (!already_closed)
+ ret_value++;
+
+ /* Close the search path table and free the paths */
+ if (H5PL__close_path_table() < 0)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTFREE, (-1), "problem closing search path table")
+
+ /* Mark the interface as uninitialized */
+ if (0 == ret_value)
+ H5_PKG_INIT_VAR = FALSE;
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5PL_term_package() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PL_load
+ *
+ * Purpose: Given the plugin type and identifier, this function searches
+ * for and, if found, loads a dynamic plugin library.
+ *
+ * The function searches first in the cached plugins and then
+ * in the paths listed in the path table.
+ *
+ * Return: Success: A pointer to the plugin info
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+const void *
+H5PL_load(H5PL_type_t type, int id)
+{
+ H5PL_search_params_t search_params;
+ hbool_t found = FALSE; /* Whether the plugin was found */
+ const void *plugin_info = NULL;
+ const void *ret_value = NULL;
+
+ FUNC_ENTER_NOAPI(NULL)
+
+ /* Check if plugins can be loaded for this plugin type */
+ switch (type) {
+ case H5PL_TYPE_FILTER:
+ if ((H5PL_plugin_control_mask_g & H5PL_FILTER_PLUGIN) == 0)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTLOAD, NULL, "required dynamically loaded plugin filter '%d' is not available", id)
+ break;
+
+ case H5PL_TYPE_ERROR:
+ case H5PL_TYPE_NONE:
+ default:
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTLOAD, NULL, "required dynamically loaded plugin '%d' is not valid", id)
+ }
+
+ /* Set up the search parameters */
+ search_params.type = type;
+ search_params.id = id;
+
+ /* Search in the table of already loaded plugin libraries */
+ if(H5PL__find_plugin_in_cache(&search_params, &found, &plugin_info) < 0)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, NULL, "search in plugin cache failed")
+
+ /* If not found, try iterating through the path table to find an appropriate plugin */
+ if (!found)
+ if (H5PL__find_plugin_in_path_table(&search_params, &found, &plugin_info) < 0)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, NULL, "search in path table failed")
+
+ /* Set the return value we found the plugin */
+ if (found)
+ ret_value = plugin_info;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5PL_load() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PL__open
+ *
+ * Purpose: Opens a plugin.
+ *
+ * The success parameter will be set to TRUE and the plugin_info
+ * parameter will be filled in on success. Otherwise, they
+ * will be FALSE and NULL, respectively.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5PL__open(const char *path, H5PL_type_t type, int id, hbool_t *success, const void **plugin_info)
+{
+ H5PL_HANDLE handle = NULL;
+ H5PL_get_plugin_info_t get_plugin_info = NULL;
+ htri_t ret_value = SUCCEED;
+
+ FUNC_ENTER_PACKAGE
+
+ /* Check args - Just assert on package functions */
+ HDassert(path);
+ HDassert(success);
+ HDassert(plugin_info);
+
+ /* Initialize out parameters */
+ *success = FALSE;
+ *plugin_info = NULL;
+
+ /* There are different reasons why a library can't be open, e.g. wrong architecture.
+ * If we can't open the library, just return.
+ */
+ if (NULL == (handle = H5PL_OPEN_DLIB(path))) {
+ H5PL_CLR_ERROR; /* clear error */
+ HGOTO_DONE(SUCCEED);
+ }
+
+
+ /* Return a handle for the function H5PLget_plugin_info in the dynamic library.
+ * The plugin library is suppose to define this function.
+ *
+ * NOTE: We turn off -Wpedantic in gcc to quiet a warning about converting
+ * object pointers to function pointers, which is undefined in ANSI C.
+ * This is basically unavoidable due to the nature of dlsym() and *is*
+ * defined in POSIX, so it's fine.
+ */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpedantic"
+ if (NULL != (get_plugin_info = (H5PL_get_plugin_info_t)H5PL_GET_LIB_FUNC(handle, "H5PLget_plugin_info"))) {
+#pragma GCC diagnostic pop
+
+ const H5Z_class2_t *info;
+
+ /* Get the plugin info */
+ if (NULL == (info = (const H5Z_class2_t *)(*get_plugin_info)()))
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "can't get plugin info")
+
+ /* Check if the filter IDs match */
+ if (info->id == id) {
+
+ /* Store the plugin in the cache */
+ if (H5PL__add_plugin(type, id, handle))
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTINSERT, FAIL, "unable to add new plugin to plugin cache")
+
+ /* Set output parameters */
+ *success = TRUE;
+ *plugin_info = (const void *)info;
+ }
+ }
+
+done:
+ if (!success && handle)
+ if (H5PL__close(handle) < 0)
+ HDONE_ERROR(H5E_PLUGIN, H5E_CLOSEERROR, FAIL, "can't close dynamic library")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5PL__open() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PL__close
+ *
+ * Purpose: Closes the handle for dynamic library
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5PL__close(H5PL_HANDLE handle)
+{
+ FUNC_ENTER_PACKAGE_NOERR
+
+ H5PL_CLOSE_LIB(handle);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5PL__close() */
+
diff --git a/src/H5PLmodule.h b/src/H5PLmodule.h
index b441aed..945441e 100644
--- a/src/H5PLmodule.h
+++ b/src/H5PLmodule.h
@@ -11,13 +11,11 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
- * Programmer: Quincey Koziol <koziol@hdfgroup.org>
- * Saturday, September 12, 2015
- *
- * Purpose: This file contains declarations which define macros for the
- * H5PL package. Including this header means that the source file
- * is part of the H5PL package.
+ * Purpose: This file contains declarations which define macros for the
+ * H5PL package. Including this header means that the source file
+ * is part of the H5PL package.
*/
+
#ifndef _H5PLmodule_H
#define _H5PLmodule_H
diff --git a/src/H5PLpath.c b/src/H5PLpath.c
new file mode 100644
index 0000000..435802a
--- /dev/null
+++ b/src/H5PLpath.c
@@ -0,0 +1,776 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Purpose: Code to implement a path table which stores plugin search paths.
+ *
+ * The path table is implemented as a dynamic, global array which
+ * will grow as new paths are inserted. The capacity of the path
+ * table never shrinks (though given the low number of paths
+ * expected and the low likelihood of paths being removed, this
+ * seems unlikely to be a problem). Inserts and removals rework
+ * the array so that there are no 'holes' in the in-use part
+ * of the array.
+ *
+ * Note that it's basically up to the user to manage the indexes
+ * when a complicated series of insert, overwrite, and, remove
+ * operations take place.
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#include "H5PLmodule.h" /* This source code file is part of the H5PL module */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5MMprivate.h" /* Memory management */
+#include "H5PLpkg.h" /* Plugin */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+/* Initial capacity of the path table */
+#define H5PL_INITIAL_PATH_CAPACITY 16
+
+/* The amount to add to the capacity when the table is full */
+#define H5PL_PATH_CAPACITY_ADD 16
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+static herr_t H5PL__insert_at(const char *path, unsigned int index);
+static herr_t H5PL__make_space_at(unsigned int index);
+static herr_t H5PL__replace_at(const char *path, unsigned int index);
+static herr_t H5PL__expand_path_table(void);
+static herr_t H5PL__find_plugin_in_path(const H5PL_search_params_t *search_params, hbool_t *found, const char *dir, const void **plugin_info);
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* Stored plugin paths to search */
+static char **H5PL_paths_g = NULL;
+
+/* The number of stored paths */
+static unsigned H5PL_num_paths_g = 0;
+
+/* The capacity of the path table */
+static unsigned H5PL_path_capacity_g = H5PL_INITIAL_PATH_CAPACITY;
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PL__insert_at()
+ *
+ * Purpose: Insert a path at a particular index in the path table.
+ * Does not clobber! Will move existing paths up to make
+ * room. Use H5PL__replace_at(index) if you want to clobber.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5PL__insert_at(const char *path, unsigned int index)
+{
+ char *path_copy = NULL; /* copy of path string (for storing) */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check args - Just assert on package functions */
+ HDassert(path);
+ HDassert(HDstrlen(path));
+
+ /* Expand the table if it is full */
+ if (H5PL_num_paths_g == H5PL_path_capacity_g)
+ if (H5PL__expand_path_table() < 0)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't expand path table")
+
+ /* Copy the path for storage so the caller can dispose of theirs */
+ if (NULL == (path_copy = H5MM_strdup(path)))
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't make internal copy of path")
+
+#ifdef H5_HAVE_WIN32_API
+ /* Clean up Microsoft Windows environment variables in the path string */
+ if(H5_expand_windows_env_vars(&path_copy))
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTCONVERT, FAIL, "can't expand environment variable string")
+#endif /* H5_HAVE_WIN32_API */
+
+ /* If the table entry is in use, make some space */
+ if (H5PL_paths_g[index])
+ if (H5PL__make_space_at(index) < 0)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_NOSPACE, FAIL, "unable to make space in the table for the new entry")
+
+ /* Insert the copy of the search path into the table at the specified index */
+ H5PL_paths_g[index] = path_copy;
+ H5PL_num_paths_g++;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5PL__insert_at() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PL__make_space_at()
+ *
+ * Purpose: Free up a slot in the path table, moving existing path
+ * entries as necessary.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5PL__make_space_at(unsigned int index)
+{
+ unsigned u; /* iterator */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Check args - Just assert on package functions */
+ HDassert(index < H5PL_path_capacity_g);
+
+ /* Copy the paths back to make a space */
+ for (u = H5PL_num_paths_g; u > index; u--)
+ H5PL_paths_g[u] = H5PL_paths_g[u-1];
+
+ H5PL_paths_g[index] = NULL;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5PL__make_space_at() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PL__replace_at()
+ *
+ * Purpose: Replace a path at a particular index in the path table.
+ * The path in the table must exist and will be freed by this
+ * function.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5PL__replace_at(const char *path, unsigned int index)
+{
+ char *path_copy = NULL; /* copy of path string (for storing) */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check args - Just assert on package functions */
+ HDassert(path);
+ HDassert(HDstrlen(path));
+
+ /* Check that the table entry is in use */
+ if (!H5PL_paths_g[index])
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTFREE, FAIL, "path entry at index %u in the table is NULL", index)
+
+ /* Copy the path for storage so the caller can dispose of theirs */
+ if (NULL == (path_copy = H5MM_strdup(path)))
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't make internal copy of path")
+
+#ifdef H5_HAVE_WIN32_API
+ /* Clean up Microsoft Windows environment variables in the path string */
+ if (H5_expand_windows_env_vars(&path_copy))
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTCONVERT, FAIL, "can't expand environment variable string")
+#endif /* H5_HAVE_WIN32_API */
+
+ /* Free the existing path entry */
+ H5PL_paths_g[index] = (char *)H5MM_xfree(H5PL_paths_g[index]);
+
+ /* Copy the search path into the table at the specified index */
+ H5PL_paths_g[index] = path_copy;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5PL__replace_at() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PL__create_path_table
+ *
+ * Purpose: Create the collection of paths that will be searched
+ * when loading plugins.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5PL__create_path_table(void)
+{
+ char *env_var= NULL; /* Path string from environment variable */
+ char *paths = NULL; /* Delimited paths string. Either from the
+ * environment variable or the default.
+ */
+ char *next_path = NULL; /* A path tokenized from the paths string */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Allocate memory for the path table */
+ H5PL_num_paths_g = 0;
+ H5PL_path_capacity_g = H5PL_INITIAL_PATH_CAPACITY;
+ if (NULL == (H5PL_paths_g = (char **)H5MM_calloc((size_t)H5PL_path_capacity_g * sizeof(char *))))
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't allocate memory for path table")
+
+ /* Retrieve paths from HDF5_PLUGIN_PATH if the user sets it
+ * or from the default paths if it isn't set.
+ */
+ env_var = HDgetenv("HDF5_PLUGIN_PATH");
+ if (NULL == env_var)
+ paths = H5MM_strdup(H5PL_DEFAULT_PATH);
+ else
+ paths = H5MM_strdup(env_var);
+
+ if (NULL == paths)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't allocate memory for path copy")
+
+ /* Separate the paths and store them */
+ /* XXX: strtok() is not thread-safe */
+ next_path = HDstrtok(paths, H5PL_PATH_SEPARATOR);
+ while (next_path) {
+
+ /* Insert the path into the table */
+ if (H5PL__append_path(next_path) < 0)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't insert path: %s", next_path)
+
+ /* Get the next path from the environment string */
+ next_path = HDstrtok(NULL, H5PL_PATH_SEPARATOR);
+ } /* end while */
+
+done:
+ if (paths)
+ paths = (char *)H5MM_xfree(paths);
+
+ /* Try to clean up on errors */
+ if (FAIL == ret_value) {
+ if (H5PL_paths_g)
+ H5PL_paths_g = (char **)H5MM_xfree(H5PL_paths_g);
+ H5PL_path_capacity_g = 0;
+ }
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5PL__create_path_table() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PL__close_path_table
+ *
+ * Purpose: Close the collection of paths that will be searched
+ * when loading plugins.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5PL__close_path_table(void)
+{
+ unsigned u; /* iterator */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE_NOERR
+
+ /* Free paths */
+ for (u = 0; u < H5PL_num_paths_g; u++)
+ if (H5PL_paths_g[u])
+ H5PL_paths_g[u] = (char *)H5MM_xfree(H5PL_paths_g[u]);
+
+ /* Free path table */
+ H5PL_paths_g = (char **)H5MM_xfree(H5PL_paths_g);
+
+ /* Reset values */
+ H5PL_num_paths_g = 0;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* end H5PL__close_path_table() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PL__get_num_paths
+ *
+ * Purpose: Gets the number of plugin paths that have been stored.
+ *
+ * Return: Success: The number of paths
+ * Failture: Can't fail
+ *-------------------------------------------------------------------------
+ */
+unsigned
+H5PL__get_num_paths(void)
+{
+ FUNC_ENTER_PACKAGE_NOERR
+
+ FUNC_LEAVE_NOAPI(H5PL_num_paths_g)
+
+} /* end H5PL__get_num_paths() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PL__expand_path_table
+ *
+ * Purpose: Expand the path table when it's full.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5PL__expand_path_table(void)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Update the capacity */
+ H5PL_path_capacity_g += H5PL_PATH_CAPACITY_ADD;
+
+ /* Resize the array */
+ if(NULL == (H5PL_paths_g = (char **)H5MM_realloc(H5PL_paths_g, (size_t)H5PL_path_capacity_g * sizeof(char *))))
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "allocating additional memory for path table failed")
+
+ /* Initialize the new memory */
+ HDmemset(H5PL_paths_g + H5PL_num_paths_g, 0, (size_t)H5PL_PATH_CAPACITY_ADD * sizeof(char *));
+
+done:
+ /* Set the path capacity back if there were problems */
+ if (FAIL == ret_value)
+ H5PL_path_capacity_g -= H5PL_PATH_CAPACITY_ADD;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5PL__expand_path_table() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PL__append_path
+ *
+ * Purpose: Insert a path at the end of the table.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5PL__append_path(const char *path)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Check args - Just assert on package functions */
+ HDassert(path);
+ HDassert(HDstrlen(path));
+
+ /* Insert the path at the end of the table */
+ if (H5PL__insert_at(path, H5PL_num_paths_g) < 0)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTINSERT, FAIL, "unable to append search path")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5PL__append_path() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PL__prepend_path
+ *
+ * Purpose: Insert a path at the beginning of the table.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5PL__prepend_path(const char *path)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Check args - Just assert on package functions */
+ HDassert(path);
+ HDassert(HDstrlen(path));
+
+ /* Insert the path at the beginning of the table */
+ if (H5PL__insert_at(path, 0) < 0)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTINSERT, FAIL, "unable to prepend search path")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5PL__prepend_path() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PL__replace_path
+ *
+ * Purpose: Replace a path at particular index in the table.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5PL__replace_path(const char *path, unsigned int index)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Check args - Just assert on package functions */
+ HDassert(path);
+ HDassert(HDstrlen(path));
+ HDassert(index < H5PL_path_capacity_g);
+
+ /* Insert the path at the requested index */
+ if (H5PL__replace_at(path, index) < 0)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTINSERT, FAIL, "unable to replace search path")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5PL__replace_path() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PL__insert_path
+ *
+ * Purpose: Insert a path at particular index in the table, moving
+ * any existing paths back to make space.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5PL__insert_path(const char *path, unsigned int index)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Check args - Just assert on package functions */
+ HDassert(path);
+ HDassert(HDstrlen(path));
+ HDassert(index < H5PL_path_capacity_g);
+
+ /* Insert the path at the requested index */
+ if (H5PL__insert_at(path, index) < 0)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTINSERT, FAIL, "unable to insert search path")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5PL__insert_path() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PL__remove_path
+ *
+ * Purpose: Remove a path at particular index in the table, freeing
+ * the path string and moving the paths down to close the gap.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5PL__remove_path(unsigned int index)
+{
+ unsigned u; /* iterator */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Check args - Just assert on package functions */
+ HDassert(index < H5PL_path_capacity_g);
+
+ /* Check if the path at that index is set */
+ if (!H5PL_paths_g[index])
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTDELETE, FAIL, "search path at index %u is NULL", index)
+
+ /* Delete the path */
+ H5PL_num_paths_g--;
+ H5PL_paths_g[index] = (char *)H5MM_xfree(H5PL_paths_g[index]);
+
+ /* Shift the paths down to close the gap */
+ for (u = index; u < H5PL_num_paths_g; u++)
+ H5PL_paths_g[u] = H5PL_paths_g[u+1];
+
+ /* Set the (former) last path to NULL */
+ H5PL_paths_g[H5PL_num_paths_g] = NULL;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5PL__remove_path() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PL__get_path
+ *
+ * Purpose: Get a pointer to a path at particular index in the table.
+ *
+ * Return: Success: A pointer to a path string stored in the table
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+const char *
+H5PL__get_path(unsigned int index)
+{
+ char *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Get the path at the requested index */
+ if (index >= H5PL_num_paths_g)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, NULL, "path index %u is out of range in table", index)
+
+ return H5PL_paths_g[index];
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5PL__replace_path() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PL__find_plugin_in_path_table
+ *
+ * Purpose: Attempts to find a matching plugin in the file system
+ * using the paths stored in the path table.
+ *.
+ * The 'found' parameter will be set appropriately.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5PL__find_plugin_in_path_table(const H5PL_search_params_t *search_params, hbool_t *found, const void **plugin_info)
+{
+ unsigned int u; /* iterator */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_PACKAGE
+
+ /* Check args - Just assert on package functions */
+ HDassert(search_params);
+ HDassert(found);
+ HDassert(plugin_info);
+
+ /* Initialize output parameters */
+ *found = FALSE;
+ *plugin_info = NULL;
+
+ /* Loop over the paths in the table, checking for an appropriate plugin */
+ for (u = 0; u < H5PL_num_paths_g; u++) {
+
+ /* Search for the plugin in this path */
+ if (H5PL__find_plugin_in_path(search_params, found, H5PL_paths_g[u], plugin_info) < 0)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "search in path %s encountered an error", H5PL_paths_g[u])
+
+ /* Break out if found */
+ if (*found) {
+ if (!plugin_info)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_BADVALUE, FAIL, "plugin info should not be NULL")
+ break;
+ }
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5PL__find_plugin_in_path_table() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PL__find_plugin_in_path
+ *
+ * Purpose: Given a path, this function opens the directory and envokes
+ * another function to go through all files to find the right
+ * plugin library. Two function definitions are for Unix and
+ * Windows.
+ *
+ * The found parameter will be set to TRUE and the info
+ * parameter will be filled in on success.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef H5_HAVE_WIN32_API
+static herr_t
+H5PL__find_plugin_in_path(const H5PL_search_params_t *search_params, hbool_t *found, const char *dir, const void **plugin_info)
+{
+ char *path = NULL;
+ DIR *dirp = NULL; /* Directory stream */
+ struct dirent *dp = NULL; /* Directory entry */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Check args - Just assert on package functions */
+ HDassert(search_params);
+ HDassert(found);
+ HDassert(dir);
+ HDassert(plugin_info);
+
+ /* Initialize the found parameter */
+ *found = FALSE;
+
+ /* Open the directory */
+ if (!(dirp = HDopendir(dir)))
+ HGOTO_ERROR(H5E_PLUGIN, H5E_OPENERROR, FAIL, "can't open directory: %s", dir)
+
+ /* Iterate through all entries in the directory */
+ while (NULL != (dp = HDreaddir(dirp))) {
+
+ /* The library we are looking for should be called libxxx.so... on Unix
+ * or libxxx.xxx.dylib on Mac.
+ */
+#ifndef __CYGWIN__
+ if (!HDstrncmp(dp->d_name, "lib", (size_t)3) &&
+ (HDstrstr(dp->d_name, ".so") || HDstrstr(dp->d_name, ".dylib"))) {
+#else
+ if (!HDstrncmp(dp->d_name, "cyg", (size_t)3) &&
+ HDstrstr(dp->d_name, ".dll") ) {
+#endif
+
+ h5_stat_t my_stat;
+ size_t len;
+
+ /* Allocate & initialize the path name */
+ len = HDstrlen(dir) + HDstrlen(H5PL_PATH_SEPARATOR) + HDstrlen(dp->d_name) + 1 /*\0*/;
+
+ if (NULL == (path = (char *)H5MM_calloc(len)))
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't allocate memory for path")
+
+ HDsnprintf(path, len, "%s/%s", dir, dp->d_name);
+
+ /* Get info for directory entry */
+ if (HDstat(path, &my_stat) == -1)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't stat file %s -- error was: %s", path, HDstrerror(errno))
+
+ /* If it is a directory, skip it */
+ if (S_ISDIR(my_stat.st_mode))
+ continue;
+
+ /* attempt to open the dynamic library as a filter library */
+ if (H5PL__open(path, search_params->type, search_params->id, found, plugin_info) < 0)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "search in directory failed")
+ if (*found)
+ HGOTO_DONE(SUCCEED)
+
+ path = (char *)H5MM_xfree(path);
+ } /* end if */
+ } /* end while */
+
+done:
+ if (dirp)
+ if (HDclosedir(dirp) < 0)
+ HDONE_ERROR(H5E_FILE, H5E_CLOSEERROR, FAIL, "can't close directory: %s", HDstrerror(errno))
+
+ path = (char *)H5MM_xfree(path);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5PL__find_plugin_in_path() */
+#else /* H5_HAVE_WIN32_API */
+static herr_t
+H5PL__find_plugin_in_path(const H5PL_search_params_t *search_params, hbool_t *found, const char *dir, const void **plugin_info)
+{
+ WIN32_FIND_DATAA fdFile;
+ HANDLE hFind = INVALID_HANDLE_VALUE;
+ char *path = NULL;
+ char service[2048];
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Check args - Just assert on package functions */
+ HDassert(search_params);
+ HDassert(found);
+ HDassert(dir);
+ HDassert(plugin_info);
+
+ /* Initialize the found parameter */
+ *found = FALSE;
+
+ /* Specify a file mask. *.* = We want everything! */
+ HDsprintf(service, "%s\\*.dll", dir);
+ if ((hFind = FindFirstFileA(service, &fdFile)) == INVALID_HANDLE_VALUE)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_OPENERROR, FAIL, "can't open directory")
+
+ /* Loop over all the files */
+ do {
+ /* Ignore '.' and '..' */
+ if (HDstrcmp(fdFile.cFileName, ".") != 0 && HDstrcmp(fdFile.cFileName, "..") != 0) {
+
+ /* XXX: Probably just continue here and move the code below over one tab */
+
+ size_t len;
+
+ /* Allocate & initialize the path name */
+ len = HDstrlen(dir) + HDstrlen(H5PL_PATH_SEPARATOR) + HDstrlen(fdFile.cFileName) + 1;
+
+ if (NULL == (path = (char *)H5MM_calloc(len)))
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't allocate memory for path")
+
+ HDsnprintf(path, len, "%s\\%s", dir, fdFile.cFileName);
+
+ /* Ignore directories */
+ if (fdFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ continue;
+
+ /* attempt to open the dynamic library as a filter library */
+ if (H5PL__open(path, search_params->type, search_params->id, found, plugin_info) < 0)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "search in directory failed")
+ if (*found)
+ HGOTO_DONE(SUCCEED)
+
+ path = (char *)H5MM_xfree(path);
+ }
+ } while (FindNextFileA(hFind, &fdFile));
+
+done:
+ if (hFind != INVALID_HANDLE_VALUE)
+ FindClose(hFind);
+ if (path)
+ path = (char *)H5MM_xfree(path);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5PL__find_plugin_in_path() */
+#endif /* H5_HAVE_WIN32_API */
+
diff --git a/src/H5PLpkg.h b/src/H5PLpkg.h
index e356893..0d1c271 100644
--- a/src/H5PLpkg.h
+++ b/src/H5PLpkg.h
@@ -11,6 +11,12 @@
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/*
+ * Purpose: This file contains declarations which are visible only within
+ * the H5PL package. Source files outside the H5PL package should
+ * include H5PLprivate.h instead.
+ */
+
#if !(defined H5PL_FRIEND || defined H5PL_MODULE)
#error "Do not include this file outside the H5PL package!"
#endif
@@ -27,13 +33,92 @@
/* Package Private Macros */
/**************************/
-#define H5PL_MAX_PATH_NUM 16
+/* Whether to pre-load pathnames for plugin libraries */
+#define H5PL_DEFAULT_PATH H5_DEFAULT_PLUGINDIR
+
+
+/****************************/
+/* Macros for supporting */
+/* both Windows and POSIX */
+/****************************/
+
+/*******************/
+/* Windows support */
+/*******************/
+/*
+ * SPECIAL WINDOWS NOTE
+ *
+ * Some of the Win32 API functions expand to fooA or fooW depending on
+ * whether UNICODE or _UNICODE are defined. You MUST explicitly use
+ * the A version of the functions to force char * behavior until we
+ * work out a scheme for proper Windows Unicode support.
+ *
+ * If you do not do this, people will be unable to incorporate our
+ * source code into their own CMake builds if they define UNICODE.
+ */
+#ifdef H5_HAVE_WIN32_API
+
+ /* The path separator on this platform */
+# define H5PL_PATH_SEPARATOR ";"
+
+ /* Handle for dynamic library */
+# define H5PL_HANDLE HINSTANCE
+
+ /* Get a handle to a plugin library. Windows: TEXT macro handles Unicode strings */
+# define H5PL_OPEN_DLIB(S) LoadLibraryExA(S, NULL, LOAD_WITH_ALTERED_SEARCH_PATH)
+
+ /* Get the address of a symbol in dynamic library */
+# define H5PL_GET_LIB_FUNC(H,N) GetProcAddress(H,N)
+
+ /* Close dynamic library */
+# define H5PL_CLOSE_LIB(H) FreeLibrary(H)
+
+ /* Clear error - nothing to do */
+# define H5PL_CLR_ERROR
+
+ /* maximum size for expanding env vars */
+# define H5PL_EXPAND_BUFFER_SIZE 32767
+
+ typedef const void *(__cdecl *H5PL_get_plugin_info_t)(void);
+
+#else /* H5_HAVE_WIN32_API */
+
+ /*****************/
+ /* POSIX support */
+ /*****************/
+
+ /* The path separator on this platform */
+# define H5PL_PATH_SEPARATOR ":"
+
+ /* Handle for dynamic library */
+# define H5PL_HANDLE void *
+
+ /* Get a handle to a plugin library. Windows: TEXT macro handles Unicode strings */
+# define H5PL_OPEN_DLIB(S) dlopen(S, RTLD_LAZY)
+
+ /* Get the address of a symbol in dynamic library */
+# define H5PL_GET_LIB_FUNC(H,N) dlsym(H,N)
+
+ /* Close dynamic library */
+# define H5PL_CLOSE_LIB(H) dlclose(H)
+
+ /* Clear error */
+# define H5PL_CLR_ERROR HERROR(H5E_PLUGIN, H5E_CANTGET, "can't dlopen:%s", dlerror())
+
+ typedef const void *(*H5PL_get_plugin_info_t)(void);
+#endif /* H5_HAVE_WIN32_API */
/****************************/
/* Package Private Typedefs */
/****************************/
+/* Data used to search for plugins */
+typedef struct H5PL_search_params_t {
+ H5PL_type_t type;
+ int id;
+} H5PL_search_params_t;
+
/*****************************/
/* Package Private Variables */
@@ -44,5 +129,31 @@
/* Package Private Prototypes */
/******************************/
+/* Accessors to global variables and flags */
+H5_DLL herr_t H5PL__get_plugin_control_mask(unsigned int *mask /*out*/);
+H5_DLL herr_t H5PL__set_plugin_control_mask(unsigned int mask);
+
+/* Plugin search and manipulation */
+H5_DLL herr_t H5PL__open(const char *libname, H5PL_type_t type, int id, hbool_t *success /*out*/, const void **plugin_info /*out*/);
+H5_DLL herr_t H5PL__close(H5PL_HANDLE handle);
+
+/* Plugin cache calls */
+H5_DLL herr_t H5PL__create_plugin_cache(void);
+H5_DLL herr_t H5PL__close_plugin_cache(hbool_t *already_closed /*out*/);
+H5_DLL herr_t H5PL__add_plugin(H5PL_type_t type, int id, H5PL_HANDLE handle);
+H5_DLL herr_t H5PL__find_plugin_in_cache(const H5PL_search_params_t *search_params, hbool_t *found /*out*/, const void **plugin_info /*out*/);
+
+/* Plugin search path calls */
+H5_DLL herr_t H5PL__create_path_table(void);
+H5_DLL herr_t H5PL__close_path_table(void);
+H5_DLL unsigned H5PL__get_num_paths(void);
+H5_DLL herr_t H5PL__append_path(const char *path);
+H5_DLL herr_t H5PL__prepend_path(const char *path);
+H5_DLL herr_t H5PL__replace_path(const char *path, unsigned int index);
+H5_DLL herr_t H5PL__insert_path(const char *path, unsigned int index);
+H5_DLL herr_t H5PL__remove_path(unsigned int index);
+H5_DLL const char *H5PL__get_path(unsigned int index);
+H5_DLL herr_t H5PL__find_plugin_in_path_table(const H5PL_search_params_t *search_params, hbool_t *found /*out*/, const void **plugin_info /*out*/);
+
#endif /* _H5PLpkg_H */
diff --git a/src/H5PLplugin_cache.c b/src/H5PLplugin_cache.c
new file mode 100644
index 0000000..30a0798
--- /dev/null
+++ b/src/H5PLplugin_cache.c
@@ -0,0 +1,308 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Purpose: Code to implement a plugin cache which stores information
+ * about plugins which have already been loaded.
+ *
+ * The plugin cache is implemented as a dynamic, global array which
+ * will grow as new plugins are added. The capacity of the cache
+ * never shrinks since plugins stay in memory once loaded.
+ *
+ * Note that this functionality has absolutely nothing to do with
+ * the metadata or chunk caches.
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#include "H5PLmodule.h" /* This source code file is part of the H5PL module */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5MMprivate.h" /* Memory management */
+#include "H5PLpkg.h" /* Plugin */
+#include "H5Zprivate.h" /* Filter pipeline */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+/* Initial capacity of the plugin cache */
+#define H5PL_INITIAL_CACHE_CAPACITY 16
+
+/* The amount to add to the capacity when the cache is full */
+#define H5PL_CACHE_CAPACITY_ADD 16
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+/* Type for the list of info for opened plugin libraries */
+typedef struct H5PL_plugin_t {
+ H5PL_type_t type; /* Plugin type */
+ int id; /* ID for the plugin */
+ H5PL_HANDLE handle; /* Plugin handle */
+} H5PL_plugin_t;
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+static herr_t H5PL__expand_cache(void);
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* Cache for storing opened plugin libraries */
+static H5PL_plugin_t *H5PL_cache_g = NULL;
+
+/* The number of stored plugins */
+static unsigned int H5PL_num_plugins_g = 0;
+
+/* The capacity of the plugin cache */
+static unsigned int H5PL_cache_capacity_g = 0;
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PL__create_plugin_cache
+ *
+ * Purpose: Create the cache that will store plugins that have already
+ * been loaded.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5PL__create_plugin_cache(void)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_PACKAGE
+
+ /* Allocate memory for the plugin cache */
+ H5PL_num_plugins_g = 0;
+
+ H5PL_cache_capacity_g = H5PL_INITIAL_CACHE_CAPACITY;
+
+ if (NULL == (H5PL_cache_g = (H5PL_plugin_t *)H5MM_calloc((size_t)H5PL_cache_capacity_g * sizeof(H5PL_plugin_t))))
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't allocate memory for plugin cache")
+
+done:
+ /* Try to clean up on errors */
+ if (FAIL == ret_value) {
+ if (H5PL_cache_g)
+ H5PL_cache_g = (H5PL_plugin_t *)H5MM_xfree(H5PL_cache_g);
+ H5PL_cache_capacity_g = 0;
+ }
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5PL__create_plugin_cache() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PL__close_plugin_cache
+ *
+ * Purpose: Close the cache of plugins that have already been loaded,
+ * closing all the plugins contained inside.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5PL__close_plugin_cache(hbool_t *already_closed /*out*/)
+{
+ unsigned int u; /* iterator */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_PACKAGE_NOERR
+
+ /* Close opened dynamic libraries */
+ if (H5PL_cache_g) {
+
+ /* Close any cached plugins */
+ for (u = 0; u < H5PL_num_plugins_g; u++)
+ H5PL__close((H5PL_cache_g[u]).handle);
+
+ /* Free the cache array */
+ H5PL_cache_g = (H5PL_plugin_t *)H5MM_xfree(H5PL_cache_g);
+ H5PL_num_plugins_g = 0;
+ H5PL_cache_capacity_g = 0;
+
+ /* Note that actually closed the table (needed by package close call) */
+ *already_closed = FALSE;
+ }
+ else
+ *already_closed = TRUE;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5PL__close_plugin_cache() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PL__expand_cache
+ *
+ * Purpose: Expand the plugin cache when it's full.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5PL__expand_cache(void)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* Update the capacity */
+ H5PL_cache_capacity_g += H5PL_CACHE_CAPACITY_ADD;
+
+ /* Resize the array */
+ if(NULL == (H5PL_cache_g = (H5PL_plugin_t *)H5MM_realloc(H5PL_cache_g, (size_t)H5PL_cache_capacity_g * sizeof(H5PL_plugin_t))))
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "allocating additional memory for plugin cache failed")
+
+ /* Initialize the new memory */
+ HDmemset(H5PL_cache_g + H5PL_num_plugins_g, 0, (size_t)H5PL_CACHE_CAPACITY_ADD * sizeof(H5PL_plugin_t));
+
+done:
+ /* Set the cache capacity back if there were problems */
+ if (FAIL == ret_value)
+ H5PL_cache_capacity_g -= H5PL_CACHE_CAPACITY_ADD;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5PL__expand_cache() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PL__add_plugin
+ *
+ * Purpose: Add a plugin to the plugin cached.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5PL__add_plugin(H5PL_type_t type, int id, H5PL_HANDLE handle)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_PACKAGE
+
+ /* Expand the cache if it is too small */
+ if (H5PL_num_plugins_g >= H5PL_cache_capacity_g)
+ if (H5PL__expand_cache() < 0)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't expand plugin cache")
+
+ /* Store the plugin info and bump the # of plugins */
+ H5PL_cache_g[H5PL_num_plugins_g].type = type;
+ H5PL_cache_g[H5PL_num_plugins_g].id = id;
+ H5PL_cache_g[H5PL_num_plugins_g].handle = handle;
+
+ H5PL_num_plugins_g++;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5PL__add_plugin() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5PL__find_plugin_in_cache
+ *
+ * Purpose: Attempts to find a matching plugin from the cache.
+ *
+ * The 'found' parameter will be set appropriately.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5PL__find_plugin_in_cache(const H5PL_search_params_t *search_params, hbool_t *found, const void **plugin_info)
+{
+ unsigned int u; /* iterator */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_PACKAGE
+
+ /* Check args - Just assert on package functions */
+ HDassert(search_params);
+ HDassert(found);
+ HDassert(plugin_info);
+
+ /* Initialize output parameters */
+ *found = FALSE;
+ *plugin_info = NULL;
+
+ /* Loop over all the plugins, looking for one that matches */
+ for (u = 0; u < H5PL_num_plugins_g; u++) {
+
+ /* If the plugin type (filter, etc.) and ID match, query the plugin for its info */
+ if ((search_params->type == (H5PL_cache_g[u]).type) && (search_params->id == (H5PL_cache_g[u]).id)) {
+
+ H5PL_get_plugin_info_t get_plugin_info_function;
+ const H5Z_class2_t *filter_info;
+
+ /* Get the "get plugin info" function from the plugin.
+ *
+ * See the other use of H5PL_GET_LIB_FUNC() for an explanation
+ * for why we disable -Wpedantic here.
+ */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpedantic"
+ if (NULL == (get_plugin_info_function = (H5PL_get_plugin_info_t)H5PL_GET_LIB_FUNC((H5PL_cache_g[u]).handle, "H5PLget_plugin_info")))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "can't get function for H5PLget_plugin_info")
+#pragma GCC diagnostic pop
+
+ /* Call the "get plugin info" function */
+ if (NULL == (filter_info = (const H5Z_class2_t *)(*get_plugin_info_function)()))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "can't get plugin info")
+
+ /* Set output parameters */
+ *found = TRUE;
+ *plugin_info = filter_info;
+
+ /* No need to continue processing */
+ break;
+
+ } /* end if */
+
+ } /* end for */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5PL__find_plugin_in_cache() */
+
diff --git a/src/H5PLprivate.h b/src/H5PLprivate.h
index 0ab8f8c..bc12e64 100644
--- a/src/H5PLprivate.h
+++ b/src/H5PLprivate.h
@@ -10,8 +10,8 @@
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-/* Programmer: Raymond Lu <songyulu@hdfgroup.org>
- * 13 February 2013
+/*
+ * This file contains private information about the H5PL module
*/
#ifndef _H5PLprivate_H
diff --git a/src/H5PLpublic.h b/src/H5PLpublic.h
index 9ce1fca..3b36ccd 100644
--- a/src/H5PLpublic.h
+++ b/src/H5PLpublic.h
@@ -10,8 +10,8 @@
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-/* Programmer: Raymond Lu <songyulu@hdfgroup.org>
- * 13 February 2013
+/*
+ * This file contains public declarations for the H5PL module.
*/
#ifndef _H5PLpublic_H
@@ -24,31 +24,35 @@
/* Public Typedefs */
/*******************/
+/* Special string to indicate no plugin loading.
+ */
+#define H5PL_NO_PLUGIN "::"
+
/* Plugin type used by the plugin library */
typedef enum H5PL_type_t {
- H5PL_TYPE_ERROR = -1, /*error */
- H5PL_TYPE_FILTER = 0, /*filter */
- H5PL_TYPE_NONE = 1 /*this must be last! */
+ H5PL_TYPE_ERROR = -1, /* Error */
+ H5PL_TYPE_FILTER = 0, /* Filter */
+ H5PL_TYPE_NONE = 1 /* This must be last! */
} H5PL_type_t;
/* Common dynamic plugin type flags used by the set/get_loading_state functions */
-#define H5PL_FILTER_PLUGIN 0x0001
-#define H5PL_ALL_PLUGIN 0xFFFF
+#define H5PL_FILTER_PLUGIN 0x0001
+#define H5PL_ALL_PLUGIN 0xFFFF
#ifdef __cplusplus
extern "C" {
#endif
/* 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 H5PLset_loading_state(unsigned int plugin_control_mask);
+H5_DLL herr_t H5PLget_loading_state(unsigned int *plugin_control_mask /*out*/);
+H5_DLL herr_t H5PLappend(const char *search_path);
+H5_DLL herr_t H5PLprepend(const char *search_path);
+H5_DLL herr_t H5PLreplace(const char *search_path, unsigned int index);
+H5_DLL herr_t H5PLinsert(const char *search_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 herr_t H5PLsize(unsigned int *listsize/*out*/);
+H5_DLL ssize_t H5PLget(unsigned int index, char *path_buf /*out*/, size_t buf_size);
+H5_DLL herr_t H5PLsize(unsigned int *num_paths /*out*/);
#ifdef __cplusplus
}
diff --git a/src/H5system.c b/src/H5system.c
index 7e25540..a1cdf19 100644
--- a/src/H5system.c
+++ b/src/H5system.c
@@ -1237,3 +1237,49 @@ H5_get_time(void)
} /* end H5_get_time() */
+#ifdef H5_HAVE_WIN32_API
+
+#define H5_WIN32_ENV_VAR_BUFFER_SIZE 32767
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5_expand_windows_env_vars()
+ *
+ * Purpose: Replaces windows environment variables of the form %foo%
+ * with user-specific values.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5_expand_windows_env_vars(char **env_var)
+{
+ long n_chars = 0;
+ char *temp_buf = NULL;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* Allocate buffer for expanded environment variable string */
+ if (NULL == (temp_buf = (char *)H5MM_calloc((size_t)H5_WIN32_ENV_VAR_BUFFER_SIZE)))
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't allocate memory for expanded path")
+
+ /* Expand the environment variable string */
+ if ((n_chars = ExpandEnvironmentStringsA(*env_var, temp_buf, H5_WIN32_ENV_VAR_BUFFER_SIZE)) > H5_WIN32_ENV_VAR_BUFFER_SIZE)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_NOSPACE, FAIL, "expanded path is too long")
+
+ if (0 == n_chars)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "failed to expand path")
+
+ *env_var = (char *)H5MM_xfree(*env_var);
+ *env_var = temp_buf;
+
+done:
+ if (FAIL == ret_value && temp_buf)
+ temp_buf = (char *)H5MM_xfree(temp_buf);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5_expand_windows_env_vars() */
+#endif /* H5_HAVE_WIN32_API */
+
diff --git a/src/H5win32defs.h b/src/H5win32defs.h
index 97f7179..4522228 100644
--- a/src/H5win32defs.h
+++ b/src/H5win32defs.h
@@ -119,6 +119,7 @@ extern "C" {
H5_DLL int c99_snprintf(char* str, size_t size, const char* format, ...);
H5_DLL int c99_vsnprintf(char* str, size_t size, const char* format, va_list ap);
H5_DLL int Wnanosleep(const struct timespec *req, struct timespec *rem);
+ H5_DLL herr_t H5_expand_windows_env_vars(char **env_var);
/* Round functions only needed for VS2012 and earlier.
* They are always built to ensure they don't go stale and
diff --git a/src/Makefile.am b/src/Makefile.am
index 0b664a7..9a64717 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -97,7 +97,7 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \
H5Pgcpl.c H5Pint.c \
H5Plapl.c H5Plcpl.c H5Pocpl.c H5Pocpypl.c H5Pstrcpl.c H5Ptest.c \
H5PB.c \
- H5PL.c \
+ H5PL.c H5PLint.c H5PLpath.c H5PLplugin_cache.c \
H5R.c H5Rdeprec.c \
H5UC.c \
H5RS.c \
diff --git a/test/plugin.c b/test/plugin.c
index 3034c0b..ea199f6 100644
--- a/test/plugin.c
+++ b/test/plugin.c
@@ -10,9 +10,6 @@
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
- * Programmer: Raymond Lu
- * 13 February 2013
- *
* Purpose: Tests the plugin module (H5PL)
*/
@@ -660,13 +657,10 @@ error:
/*-------------------------------------------------------------------------
* Function: test_groups_with_filters
*
- * Purpose: Tests opening group with dynamically loaded filters
- *
- * Return: Success: 0
- * Failure: -1
+ * Purpose: Tests opening group with dynamically loaded filters
*
- * Programmer: Raymond Lu
- * 1 April 2013
+ * Return: Success: 0
+ * Failure: -1
*
*-------------------------------------------------------------------------
*/
@@ -710,264 +704,388 @@ error:
/*-------------------------------------------------------------------------
- * Function: test_filter_path_apis
+ * Function: test_path_api_calls
*
- * Purpose: Tests accessing the path table for dynamically loaded filters
+ * Purpose: Tests the H5PL API calls that manipulate the plugin search
+ * paths.
*
- * Return: Success: 0
- * Failure: -1
+ * Return: SUCCEED/FAIL
+ *
*-------------------------------------------------------------------------
*/
static herr_t
-test_filter_path_apis(void)
+test_path_api_calls(void)
{
- herr_t ret_value = -1;
- unsigned int i;
- unsigned int ndx;
+ unsigned int n_starting_paths;
+ unsigned int u;
+ unsigned int n_paths;
herr_t ret;
- ssize_t pathlen = -1;
- char pathname[256];
- char tempname[256];
+ ssize_t path_len = -1;
+ char path[256];
+ char temp_name[256];
HDputs("Testing access to the filter path table");
- if(H5Zfilter_avail(H5Z_FILTER_DYNLIB1) != TRUE) TEST_ERROR
+ if(H5Zfilter_avail(H5Z_FILTER_DYNLIB1) != TRUE)
+ TEST_ERROR
+
+ /* Set the number of paths to create for this test.
+ *
+ * This should be set high enough to ensure that at least one array
+ * expansion will take place. See H5PLpath.c for details.
+ */
+ n_starting_paths = 42;
+ /* Check that initialization is correct */
TESTING(" initialize");
- H5PLsize(&ndx);
- if(ndx!=2) TEST_ERROR
+
+ if(H5PLsize(&n_paths) < 0)
+ TEST_ERROR
+ if(n_paths != 2)
+ TEST_ERROR
+
PASSED();
+ /****************/
+ /* H5PLremove() */
+ /****************/
+
+ /* Remove all the current paths */
TESTING(" remove");
- /* Remove all existing paths*/
- for(i=ndx; i > 0; i--)
- if(H5PLremove(i-1) < 0) {
- HDfprintf(stderr," at %d: %s\n", i, pathname);
+
+ /* Get the current size */
+ if(H5PLsize(&n_paths) < 0)
+ TEST_ERROR
+
+ /* Remove all existing paths */
+ for(u = n_paths; u > 0; u--)
+ if(H5PLremove(u-1) < 0) {
+ HDfprintf(stderr," at %u: %s\n", u, path);
TEST_ERROR
- } /* end if */
+ }
+
/* Verify the table is empty */
- H5PLsize(&ndx);
- if(ndx > 0) TEST_ERROR
+ if(H5PLsize(&n_paths) < 0)
+ TEST_ERROR
+ if(n_paths > 0)
+ TEST_ERROR
+
PASSED();
- TESTING(" remove (exceed min)");
- /* Exceed the min path removal */
+
+ TESTING(" remove (index 0 in empty table)");
+
+ /* Try to remove index zero in an empty list (SHOULD FAIL) */
H5E_BEGIN_TRY {
ret = H5PLremove(0);
} H5E_END_TRY
- if(ret >= 0) TEST_ERROR
+ if(ret >= 0)
+ TEST_ERROR
+
PASSED();
+
+ /****************/
+ /* H5PLappend() */
+ /****************/
+
TESTING(" append");
- /* Create multiple paths to fill table */
- for(i=0; i < H5PL_MAX_PATH_NUM; i++) {
- HDsprintf(pathname, "a_path_%d", i);
- if(H5PLappend(pathname) < 0) {
- HDfprintf(stderr," at %d: %s\n", i, pathname);
+
+ /* Add a bunch of paths to the path table */
+ for(u = 0; u < n_starting_paths; u++) {
+ HDsprintf(path, "a_path_%u", u);
+ if(H5PLappend(path) < 0) {
+ HDfprintf(stderr," at %u: %s\n", u, path);
TEST_ERROR
}
}
- /* Verify the table is full */
- H5PLsize(&ndx);
- if(ndx != H5PL_MAX_PATH_NUM) TEST_ERROR
- PASSED();
- TESTING(" append (exceed)");
- /* Exceed the max path append */
- H5E_BEGIN_TRY {
- HDsprintf(pathname, "a_path_%d", H5PL_MAX_PATH_NUM);
- ret = H5PLappend(pathname);
- } H5E_END_TRY
- if(ret >= 0) TEST_ERROR
PASSED();
- TESTING(" remove (exceed max)");
- /* Exceed the max path removal */
+
+ /**********************/
+ /* H5PLremove() again */
+ /**********************/
+
+ TESTING(" remove (index too high)");
+
+ /* Try to remove a path where the index is beyond the table capacity (SHOULD FAIL) */
H5E_BEGIN_TRY {
- ret = H5PLremove(H5PL_MAX_PATH_NUM);
+ ret = H5PLremove(n_starting_paths);
} H5E_END_TRY
- if(ret >= 0) TEST_ERROR
+
+ if(ret >= 0)
+ TEST_ERROR
+
PASSED();
+
+ /*************/
+ /* H5PLget() */
+ /*************/
+
TESTING(" get (path name)");
- if((pathlen = H5PLget(0, NULL, 0)) <= 0) {
+
+ /* Get the path length by passing in NULL */
+ if((path_len = H5PLget(0, NULL, 0)) <= 0) {
HDfprintf(stderr," get path 0 length failed\n");
TEST_ERROR
}
- if(pathlen != 8) TEST_ERROR
+ if(path_len != 8)
+ TEST_ERROR
- if((pathlen = H5PLget(0, pathname, 256)) <= 0) {
- HDfprintf(stderr," get 0 len: %d : %s\n", pathlen, pathname);
+ /* Get the path */
+ if((path_len = H5PLget(0, path, 256)) <= 0) {
+ HDfprintf(stderr," get 0 len: %u : %s\n", path_len, path);
TEST_ERROR
}
- if(HDstrcmp(pathname, "a_path_0") != 0) {
- HDfprintf(stderr," get 0: %s\n", pathname);
+ if(HDstrcmp(path, "a_path_0") != 0) {
+ HDfprintf(stderr," get 0: %s\n", path);
TEST_ERROR
}
+
PASSED();
- TESTING(" get (bounds)");
- if((pathlen = H5PLget(1, pathname, 256)) <= 0) TEST_ERROR
- if(HDstrcmp(pathname, "a_path_1") != 0) {
- HDfprintf(stderr," get 1: %s\n", pathname);
+
+ TESTING(" get (high and low indices)");
+
+ /* Get path at index 1 */
+ if((path_len = H5PLget(1, path, 256)) <= 0)
+ TEST_ERROR
+ if(HDstrcmp(path, "a_path_1") != 0) {
+ HDfprintf(stderr," get 1: %s\n", path);
TEST_ERROR
}
- if((pathlen = H5PLget(H5PL_MAX_PATH_NUM - 1, pathname, 256)) <= 0) TEST_ERROR
- HDsprintf(tempname, "a_path_%d", H5PL_MAX_PATH_NUM - 1);
- if(HDstrcmp(pathname, tempname) != 0) {
- HDfprintf(stderr," get %d: %s\n", H5PL_MAX_PATH_NUM - 1, pathname);
+
+ /* Get path at the last index */
+ if((path_len = H5PLget(n_starting_paths - 1, path, 256)) <= 0)
+ TEST_ERROR
+ HDsprintf(temp_name, "a_path_%u", n_starting_paths - 1);
+ if(HDstrcmp(path, temp_name) != 0) {
+ HDfprintf(stderr," get %u: %s\n", n_starting_paths - 1, path);
TEST_ERROR
}
+
PASSED();
- TESTING(" get (bounds exceed)");
+
+ TESTING(" get (index too high)");
+
+ /* Get path at the last + 1 index (SHOULD FAIL) */
H5E_BEGIN_TRY {
- pathlen = H5PLget(H5PL_MAX_PATH_NUM, NULL, 0);
+ path_len = H5PLget(n_starting_paths, NULL, 0);
} H5E_END_TRY
- if(pathlen > 0) TEST_ERROR
+ if(path_len > 0)
+ TEST_ERROR
+
PASSED();
- TESTING(" remove (verify for prepend)");
- /* Remove one path*/
- if(H5PLremove(8) < 0) TEST_ERROR
+
+ /*****************/
+ /* H5PLprepend() */
+ /*****************/
+
+ /* We'll remove a path at an arbitrary index and then
+ * prepend a new path.
+ */
+
+ TESTING(" remove (arbitrary index 1)");
+
+ /* Remove one path */
+ if(H5PLremove(8) < 0)
+ TEST_ERROR
/* Verify that the entries were moved */
- if((pathlen = H5PLget(8, pathname, 256)) <= 0) TEST_ERROR
- if(HDstrcmp(pathname, "a_path_9") != 0) {
- HDfprintf(stderr," get 8: %s\n", pathname);
+ if((path_len = H5PLget(8, path, 256)) <= 0)
+ TEST_ERROR
+ if(HDstrcmp(path, "a_path_9") != 0) {
+ HDfprintf(stderr," get 8: %s\n", path);
TEST_ERROR
}
+
+ /* Verify the table shrank */
+ if(H5PLsize(&n_paths) < 0)
+ TEST_ERROR
+ if(n_paths != n_starting_paths - 1)
+ TEST_ERROR
+
PASSED();
- /* Verify the table is not full */
- H5PLsize(&ndx);
- if (ndx != H5PL_MAX_PATH_NUM - 1) TEST_ERROR
TESTING(" prepend");
- /* Prepend one path*/
- HDsprintf(pathname, "a_path_%d", H5PL_MAX_PATH_NUM + 1);
- if(H5PLprepend(pathname) < 0) {
- HDfprintf(stderr," prepend %d: %s\n", H5PL_MAX_PATH_NUM + 1, pathname);
+
+ /* Prepend one path */
+ HDsprintf(path, "a_path_%d", n_starting_paths + 1);
+ if(H5PLprepend(path) < 0) {
+ HDfprintf(stderr," prepend %u: %s\n", n_starting_paths + 1, path);
TEST_ERROR
}
- /* Verify the table is full */
- H5PLsize(&ndx);
- if(ndx != H5PL_MAX_PATH_NUM) TEST_ERROR
+ /* Verify the table increased */
+ if(H5PLsize(&n_paths) < 0)
+ TEST_ERROR
+ if(n_paths != n_starting_paths)
+ TEST_ERROR
/* Verify that the entries were moved */
- if(H5PLget(8, pathname, 256) <= 0) TEST_ERROR
- if(HDstrcmp(pathname, "a_path_7") != 0) {
- HDfprintf(stderr," get 8: %s\n", pathname);
+ if(H5PLget(8, path, 256) <= 0)
+ TEST_ERROR
+ if(HDstrcmp(path, "a_path_7") != 0) {
+ HDfprintf(stderr," get 8: %s\n", path);
TEST_ERROR
}
- if(H5PLget(0, pathname, 256) <= 0) TEST_ERROR
- HDsprintf(tempname, "a_path_%d", H5PL_MAX_PATH_NUM + 1);
- if(HDstrcmp(pathname, tempname) != 0) {
- HDfprintf(stderr," get 0: %s\n", pathname);
+
+ /* Verify that the path was inserted at index zero */
+ if(H5PLget(0, path, 256) <= 0)
+ TEST_ERROR
+ HDsprintf(temp_name, "a_path_%d", n_starting_paths + 1);
+ if(HDstrcmp(path, temp_name) != 0) {
+ HDfprintf(stderr," get 0: %s\n", path);
TEST_ERROR
}
- PASSED();
- TESTING(" prepend (exceed)");
- /* Exceed the max path prepend */
- H5E_BEGIN_TRY {
- HDsprintf(pathname, "a_path_%d", H5PL_MAX_PATH_NUM + 2);
- ret = H5PLprepend(pathname);
- } H5E_END_TRY
- if(ret >= 0) TEST_ERROR
PASSED();
+
+ /*****************/
+ /* H5PLreplace() */
+ /*****************/
+
TESTING(" replace");
- /* Replace one path*/
- HDsprintf(pathname, "a_path_%d", H5PL_MAX_PATH_NUM + 4);
- if(H5PLreplace(pathname, 1) < 0) {
- HDfprintf(stderr," replace 1: %s\n", pathname);
+
+ /* Replace one path at index 1 */
+ HDsprintf(path, "a_path_%u", n_starting_paths + 4);
+ if(H5PLreplace(path, 1) < 0) {
+ HDfprintf(stderr," replace 1: %s\n", path);
TEST_ERROR
}
- /* Verify the table is full */
- H5PLsize(&ndx);
- if(ndx != H5PL_MAX_PATH_NUM) TEST_ERROR
+ /* Verify the table size remained the same */
+ if(H5PLsize(&n_paths) < 0)
+ TEST_ERROR
+ if(n_paths != n_starting_paths)
+ TEST_ERROR
+
+ /* Verify that the entries were not moved by
+ * inspecting the paths at indices +/- 1.
+ */
- /* Verify that the entries were not moved */
- if(H5PLget(0, pathname, 256) <= 0) TEST_ERROR
- HDsprintf(tempname, "a_path_%d", H5PL_MAX_PATH_NUM + 1);
- if(HDstrcmp(pathname, tempname) != 0) {
- HDfprintf(stderr," get 0: %s\n", pathname);
+ /* Check path at index 0 */
+ if(H5PLget(0, path, 256) <= 0)
+ TEST_ERROR
+ HDsprintf(temp_name, "a_path_%u", n_starting_paths + 1);
+ if(HDstrcmp(path, temp_name) != 0) {
+ HDfprintf(stderr," get 0: %s\n", path);
TEST_ERROR
}
- if(H5PLget(2, pathname, 256) <= 0) TEST_ERROR
- if(HDstrcmp(pathname, "a_path_1") != 0) {
- HDfprintf(stderr," get 2: %s\n", pathname);
+
+ /* Check path at index 2 */
+ if(H5PLget(2, path, 256) <= 0)
+ TEST_ERROR
+ if(HDstrcmp(path, "a_path_1") != 0) {
+ HDfprintf(stderr," get 2: %s\n", path);
TEST_ERROR
}
+
PASSED();
- TESTING(" remove (verify for insert)");
- /* Remove one path*/
- if(H5PLremove(4) < 0) TEST_ERROR
+
+ /****************/
+ /* H5PLinsert() */
+ /****************/
+
+ /* We'll remove a path at an arbitrary index and then
+ * insert a new path.
+ */
+
+ TESTING(" remove (arbitrary index 2)");
+
+ /* Remove one path */
+ if(H5PLremove(4) < 0)
+ TEST_ERROR
/* Verify that the entries were moved */
- if(H5PLget(4, pathname, 256) <= 0) TEST_ERROR
- if(HDstrcmp(pathname, "a_path_4") != 0) {
- HDfprintf(stderr," get 4: %s\n", pathname);
+ if(H5PLget(4, path, 256) <= 0)
+ TEST_ERROR
+ if(HDstrcmp(path, "a_path_4") != 0) {
+ HDfprintf(stderr," get 4: %s\n", path);
TEST_ERROR
}
+
+ /* Verify the table size */
+ if(H5PLsize(&n_paths) < 0)
+ TEST_ERROR
+ if(n_paths != n_starting_paths - 1)
+ TEST_ERROR
PASSED();
- /* Verify the table is not full */
- H5PLsize(&ndx);
- if(ndx != 15) TEST_ERROR
TESTING(" insert");
- /* Insert one path*/
- HDsprintf(pathname, "a_path_%d", H5PL_MAX_PATH_NUM + 5);
- if(H5PLinsert(pathname, 3) < 0) {
- HDfprintf(stderr," insert 3: %s\n", pathname);
+
+ /* Insert one path at index 3*/
+ HDsprintf(path, "a_path_%d", n_starting_paths + 5);
+ if(H5PLinsert(path, 3) < 0) {
+ HDfprintf(stderr," insert 3: %s\n", path);
TEST_ERROR
}
/* Verify that the entries were moved */
- if(H5PLget(4, pathname, 256) <= 0) TEST_ERROR
- if(HDstrcmp(pathname, "a_path_2") != 0) {
- HDfprintf(stderr," get 4: %s\n", pathname);
+ if(H5PLget(4, path, 256) <= 0)
+ TEST_ERROR
+ if(HDstrcmp(path, "a_path_2") != 0) {
+ HDfprintf(stderr," get 4: %s\n", path);
TEST_ERROR
}
+
+ /* Verify the table size increased */
+ if(H5PLsize(&n_paths) < 0)
+ TEST_ERROR
+ if(n_paths != n_starting_paths)
+ TEST_ERROR
+
PASSED();
- /* Verify the table is full */
- H5PLsize(&ndx);
- if(ndx != H5PL_MAX_PATH_NUM) TEST_ERROR
- TESTING(" insert (exceed)");
- /* Exceed the max path insert */
- H5E_BEGIN_TRY {
- HDsprintf(pathname, "a_path_%d", H5PL_MAX_PATH_NUM + 6);
- ret = H5PLinsert(pathname, 12);
- } H5E_END_TRY
- if(ret >= 0) TEST_ERROR
+ /****************/
+ /* H5PLremove() */
+ /****************/
+
+ /* Remove all the current paths */
+ TESTING(" remove (all)");
+
+ /* Get the current size */
+ if(H5PLsize(&n_paths) < 0)
+ TEST_ERROR
+
+ /* Remove all existing paths */
+ for(u = n_paths; u > 0; u--)
+ if(H5PLremove(u-1) < 0) {
+ HDfprintf(stderr," at %u: %s\n", u, path);
+ TEST_ERROR
+ }
+
+ /* Verify the table is empty */
+ if(H5PLsize(&n_paths) < 0)
+ TEST_ERROR
+ if(n_paths > 0)
+ TEST_ERROR
PASSED();
- ret_value = 0;
+
+ return SUCCEED;
error:
- return ret_value;
-}
+ return FAIL;
+} /* end test_path_api_calls() */
/*-------------------------------------------------------------------------
* Function: main
*
- * Purpose: Tests the plugin module (H5PL)
+ * Purpose: Tests the plugin module (H5PL)
*
- * Return: Success: exit(EXIT_SUCCESS)
- *
- * Failure: exit(EXIT_FAILURE)
- *
- * Programmer: Raymond Lu
- * 14 March 2013
+ * Return: EXIT_SUCCESS/EXIT_FAILURE
*
*-------------------------------------------------------------------------
*/
@@ -987,37 +1105,44 @@ main(void)
/* Testing setup */
h5_reset();
- fapl = h5_fileaccess();
+
+ if ((fapl = h5_fileaccess()) < 0)
+ TEST_ERROR
/* Turn off the chunk cache, so all the chunks are immediately written to disk */
- if(H5Pget_cache(fapl, &mdc_nelmts, &rdcc_nelmts, &rdcc_nbytes, &rdcc_w0) < 0) TEST_ERROR
+ if (H5Pget_cache(fapl, &mdc_nelmts, &rdcc_nelmts, &rdcc_nbytes, &rdcc_w0) < 0)
+ TEST_ERROR
rdcc_nbytes = 0;
- if(H5Pset_cache(fapl, mdc_nelmts, rdcc_nelmts, rdcc_nbytes, rdcc_w0) < 0) TEST_ERROR
+ if (H5Pset_cache(fapl, mdc_nelmts, rdcc_nelmts, rdcc_nbytes, rdcc_w0) < 0)
+ TEST_ERROR
/* Copy the file access property list */
- if((fapl2 = H5Pcopy(fapl)) < 0) TEST_ERROR
+ if ((fapl2 = H5Pcopy(fapl)) < 0)
+ TEST_ERROR
/* Set the "use the latest version of the format" bounds for creating objects in the file */
- if(H5Pset_libver_bounds(fapl2, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) TEST_ERROR
+ if (H5Pset_libver_bounds(fapl2, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0)
+ TEST_ERROR
- h5_fixname(FILENAME[0], fapl, filename, sizeof filename);
+ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename));
/* Test with old & new format groups */
- for(new_format = FALSE; new_format <= TRUE; new_format++) {
+ for (new_format = FALSE; new_format <= TRUE; new_format++) {
hid_t my_fapl;
/* Set the FAPL for the type of format */
- if(new_format) {
+ if (new_format) {
HDputs("\nTesting with new file format:");
my_fapl = fapl2;
- } /* end if */
+ }
else {
HDputs("Testing with old file format:");
my_fapl = fapl;
- } /* end else */
+ }
/* Create the file for this test */
- if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, my_fapl)) < 0) TEST_ERROR
+ if ((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, my_fapl)) < 0)
+ TEST_ERROR
/* Test dynamically loaded filters for chunked dataset */
nerrors += (test_filters_for_datasets(file) < 0 ? 1 : 0);
@@ -1025,12 +1150,15 @@ main(void)
/* Test dynamically loaded filters for groups */
nerrors += (test_filters_for_groups(file) < 0 ? 1 : 0);
- if(H5Fclose(file) < 0) TEST_ERROR
+ if (H5Fclose(file) < 0)
+ TEST_ERROR
} /* end for */
/* Close FAPL */
- if(H5Pclose(fapl2) < 0) TEST_ERROR
- if(H5Pclose(fapl) < 0) TEST_ERROR
+ if (H5Pclose(fapl2) < 0)
+ TEST_ERROR
+ if (H5Pclose(fapl) < 0)
+ TEST_ERROR
/* Restore the default error handler (set in h5_reset()) */
h5_restore_err();
@@ -1039,10 +1167,12 @@ main(void)
/* Close the library so that all loaded plugin libraries are unloaded */
h5_reset();
- fapl = h5_fileaccess();
+ if ((fapl = h5_fileaccess()) < 0)
+ TEST_ERROR
/* Reopen the file for testing data reading */
- if((file = H5Fopen(filename, H5F_ACC_RDONLY, fapl)) < 0) TEST_ERROR
+ if ((file = H5Fopen(filename, H5F_ACC_RDONLY, fapl)) < 0)
+ TEST_ERROR
/* Read the data with filters */
nerrors += (test_read_with_filters(file) < 0 ? 1 : 0);
@@ -1055,29 +1185,33 @@ main(void)
/* Close the library so that all loaded plugin libraries are unloaded */
h5_reset();
- fapl = h5_fileaccess();
+ if ((fapl = h5_fileaccess()) < 0)
+ TEST_ERROR
/* Reopen the file for testing data reading */
- if((file = H5Fopen(filename, H5F_ACC_RDONLY, fapl)) < 0) TEST_ERROR
+ if ((file = H5Fopen(filename, H5F_ACC_RDONLY, fapl)) < 0)
+ TEST_ERROR
/* Read the data with disabled filters */
nerrors += (test_noread_with_filters(file) < 0 ? 1 : 0);
- if(H5Fclose(file) < 0) TEST_ERROR
+ if (H5Fclose(file) < 0)
+ TEST_ERROR
/* Test the APIs for access to the filter plugin path table */
- nerrors += (test_filter_path_apis() < 0 ? 1 : 0);
+ nerrors += (test_path_api_calls() < 0 ? 1 : 0);
- if(nerrors) TEST_ERROR
+ if (nerrors)
+ TEST_ERROR
HDprintf("All plugin tests passed.\n");
h5_cleanup(FILENAME, fapl);
- return 0;
+ HDexit(EXIT_SUCCESS);
error:
nerrors = MAX(1, nerrors);
HDprintf("***** %d PLUGIN TEST%s FAILED! *****\n", nerrors, 1 == nerrors ? "" : "S");
- return 1;
-}
+ HDexit(EXIT_FAILURE);
+} /* end main() */