summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjhendersonHDF <jhenderson@hdfgroup.org>2020-12-16 05:39:19 (GMT)
committerGitHub <noreply@github.com>2020-12-16 05:39:19 (GMT)
commitaffbead81a20712920bfe350eb90b0a4bb754ebf (patch)
tree633747a9663f2252380267c3dc1028326ac8d094
parent865b10b7a707005f08b13e92dec90e402de1f21d (diff)
downloadhdf5-affbead81a20712920bfe350eb90b0a4bb754ebf.zip
hdf5-affbead81a20712920bfe350eb90b0a4bb754ebf.tar.gz
hdf5-affbead81a20712920bfe350eb90b0a4bb754ebf.tar.bz2
Enable H5Fopen to probe list of available VOL connectors when opening a (#182)
file
-rw-r--r--src/H5F.c6
-rw-r--r--src/H5PLint.c63
-rw-r--r--src/H5PLpath.c227
-rw-r--r--src/H5PLpkg.h8
-rw-r--r--src/H5PLplugin_cache.c8
-rw-r--r--src/H5PLprivate.h13
-rw-r--r--src/H5VL.c21
-rw-r--r--src/H5VLcallback.c159
-rw-r--r--src/H5VLint.c21
-rw-r--r--src/H5VLprivate.h2
10 files changed, 479 insertions, 49 deletions
diff --git a/src/H5F.c b/src/H5F.c
index 365decf..d535ffe 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -690,7 +690,7 @@ done:
static hid_t
H5F__open_api_common(const char *filename, unsigned flags, hid_t fapl_id, void **token_ptr)
{
- H5F_t * new_file = NULL; /* File struct for new file */
+ void * new_file = NULL; /* File struct for new file */
H5P_genplist_t * plist; /* Property list pointer */
H5VL_connector_prop_t connector_prop; /* Property for VOL connector ID & info */
hid_t ret_value = H5I_INVALID_HID; /* Return value */
@@ -730,8 +730,8 @@ H5F__open_api_common(const char *filename, unsigned flags, hid_t fapl_id, void *
HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set VOL connector info in API context")
/* Open the file through the VOL layer */
- if (NULL == (new_file = (H5F_t *)H5VL_file_open(&connector_prop, filename, flags, fapl_id,
- H5P_DATASET_XFER_DEFAULT, token_ptr)))
+ if (NULL == (new_file = H5VL_file_open(&connector_prop, filename, flags, fapl_id,
+ H5P_DATASET_XFER_DEFAULT, token_ptr)))
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, H5I_INVALID_HID, "unable to open file")
/* Get an ID for the file */
diff --git a/src/H5PLint.c b/src/H5PLint.c
index 3b9683b..da9e084 100644
--- a/src/H5PLint.c
+++ b/src/H5PLint.c
@@ -253,7 +253,7 @@ H5PL_load(H5PL_type_t type, const H5PL_key_t *key)
/* 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")
+ 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)
@@ -293,12 +293,14 @@ done:
H5_GCC_DIAG_OFF("pedantic")
herr_t
H5PL__open(const char *path, H5PL_type_t type, const H5PL_key_t *key, hbool_t *success,
- const void **plugin_info)
+ H5PL_type_t *plugin_type, const void **plugin_info)
{
H5PL_HANDLE handle = NULL;
H5PL_get_plugin_type_t get_plugin_type = NULL;
H5PL_get_plugin_info_t get_plugin_info = NULL;
- herr_t ret_value = SUCCEED;
+ H5PL_type_t loaded_plugin_type;
+ H5PL_key_t tmp_key;
+ herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
@@ -310,6 +312,8 @@ H5PL__open(const char *path, H5PL_type_t type, const H5PL_key_t *key, hbool_t *s
/* Initialize out parameters */
*success = FALSE;
*plugin_info = NULL;
+ if (plugin_type)
+ *plugin_type = H5PL_TYPE_ERROR;
/* There are different reasons why a library can't be open, e.g. wrong architecture.
* If we can't open the library, just return.
@@ -332,11 +336,12 @@ H5PL__open(const char *path, H5PL_type_t type, const H5PL_key_t *key, hbool_t *s
HGOTO_DONE(SUCCEED)
/* Check the plugin type and return if it doesn't match the one passed in */
- if (type != (H5PL_type_t)(*get_plugin_type)())
+ loaded_plugin_type = (H5PL_type_t)(*get_plugin_type)();
+ if ((type != H5PL_TYPE_NONE) && (type != loaded_plugin_type))
HGOTO_DONE(SUCCEED)
/* Get the plugin information */
- switch (type) {
+ switch (loaded_plugin_type) {
case H5PL_TYPE_FILTER: {
const H5Z_class2_t *filter_info;
@@ -344,8 +349,16 @@ H5PL__open(const char *path, H5PL_type_t type, const H5PL_key_t *key, hbool_t *s
if (NULL == (filter_info = (const H5Z_class2_t *)(*get_plugin_info)()))
HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "can't get filter info from plugin")
+ /* Setup temporary plugin key if one wasn't supplied */
+ if (!key) {
+ tmp_key.id = filter_info->id;
+ key = &tmp_key;
+ }
+
/* If the filter IDs match, we're done. Set the output parameters. */
if (filter_info->id == key->id) {
+ if (plugin_type)
+ *plugin_type = H5PL_TYPE_FILTER;
*plugin_info = (const void *)filter_info;
*success = TRUE;
}
@@ -360,13 +373,23 @@ H5PL__open(const char *path, H5PL_type_t type, const H5PL_key_t *key, hbool_t *s
if (NULL == (cls = (const void *)(*get_plugin_info)()))
HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "can't get VOL connector info from plugin")
+ /* Setup temporary plugin key if one wasn't supplied */
+ if (!key) {
+ tmp_key.vol.kind = H5VL_GET_CONNECTOR_BY_NAME;
+ tmp_key.vol.u.name = ((const H5VL_class_t *)cls)->name;
+ key = &tmp_key;
+ }
+
/* Ask VOL interface if this class is the one we are looking for and is compatible, etc */
if (H5VL_check_plugin_load(cls, key, success) < 0)
HGOTO_ERROR(H5E_PLUGIN, H5E_CANTLOAD, FAIL, "VOL connector compatibility check failed")
/* Check for finding the correct plugin */
- if (*success)
+ if (*success) {
+ if (plugin_type)
+ *plugin_type = H5PL_TYPE_VOL;
*plugin_info = cls;
+ }
break;
}
@@ -379,7 +402,7 @@ H5PL__open(const char *path, H5PL_type_t type, const H5PL_key_t *key, hbool_t *s
/* If we found the correct plugin, store it in the cache */
if (*success)
- if (H5PL__add_plugin(type, key, handle))
+ if (H5PL__add_plugin(loaded_plugin_type, key, handle))
HGOTO_ERROR(H5E_PLUGIN, H5E_CANTINSERT, FAIL, "unable to add new plugin to plugin cache")
done:
@@ -409,3 +432,29 @@ H5PL__close(H5PL_HANDLE handle)
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5PL__close() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5PL_iterate
+ *
+ * Purpose: Iterates over all the available plugins and calls the
+ * specified callback function on each plugin.
+ *
+ * Return: H5_ITER_CONT if all plugins are processed successfully
+ * H5_ITER_STOP if short-circuit success occurs while
+ * processing plugins
+ * H5_ITER_ERROR if an error occurs while processing plugins
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5PL_iterate(H5PL_iterate_type_t iter_type, H5PL_iterate_t iter_op, void *op_data)
+{
+ herr_t ret_value = H5_ITER_CONT;
+
+ FUNC_ENTER_NOAPI(H5_ITER_ERROR)
+
+ ret_value = H5PL__path_table_iterate(iter_type, iter_op, op_data);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5PL_iterate() */
diff --git a/src/H5PLpath.c b/src/H5PLpath.c
index ff4dc0e..d566f66 100644
--- a/src/H5PLpath.c
+++ b/src/H5PLpath.c
@@ -62,6 +62,8 @@ static herr_t H5PL__insert_at(const char *path, unsigned int idx);
static herr_t H5PL__make_space_at(unsigned int idx);
static herr_t H5PL__replace_at(const char *path, unsigned int idx);
static herr_t H5PL__expand_path_table(void);
+static herr_t H5PL__path_table_iterate_process_path(const char *plugin_path, H5PL_iterate_type_t iter_type,
+ H5PL_iterate_t iter_op, void *op_data);
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);
@@ -546,7 +548,220 @@ H5PL__get_path(unsigned int idx)
return H5PL_paths_g[idx];
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5PL__replace_path() */
+} /* end H5PL__get_path() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5PL__path_table_iterate
+ *
+ * Purpose: Iterates over all the plugins in the plugin path table and
+ * calls the specified callback function on each plugin found.
+ *
+ * Return: H5_ITER_CONT if all plugins are processed successfully
+ * H5_ITER_STOP if short-circuit success occurs while
+ * processing plugins
+ * H5_ITER_ERROR if an error occurs while processing plugins
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5PL__path_table_iterate(H5PL_iterate_type_t iter_type, H5PL_iterate_t iter_op, void *op_data)
+{
+ unsigned int u;
+ herr_t ret_value = H5_ITER_CONT;
+
+ FUNC_ENTER_PACKAGE
+
+ for (u = 0; (u < H5PL_num_paths_g) && (ret_value == H5_ITER_CONT); u++)
+ ret_value = H5PL__path_table_iterate_process_path(H5PL_paths_g[u], iter_type, iter_op, op_data);
+
+ if (ret_value < 0)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_BADITER, H5_ITER_ERROR, "can't iterate over plugins in plugin path '%s'",
+ H5PL_paths_g[u]);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5PL__path_table_iterate() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5PL__path_table_iterate_process_path
+ *
+ * Purpose: Iterates over all the plugins within a single plugin path
+ * entry in the plugin path table and calls the specified
+ * callback function on each plugin found. Two function
+ * definitions are for Unix and Windows.
+ *
+ * Return: H5_ITER_CONT if all plugins are processed successfully
+ * H5_ITER_STOP if short-circuit success occurs while
+ * processing plugins
+ * H5_ITER_ERROR if an error occurs while processing plugins
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef H5_HAVE_WIN32_API
+static herr_t
+H5PL__path_table_iterate_process_path(const char *plugin_path, H5PL_iterate_type_t iter_type,
+ H5PL_iterate_t iter_op, void *op_data)
+{
+ H5PL_type_t plugin_type;
+ const void * plugin_info = NULL;
+ hbool_t plugin_loaded;
+ char * path = NULL;
+ DIR * dirp = NULL; /* Directory stream */
+ struct dirent *dp = NULL; /* Directory entry */
+ herr_t ret_value = H5_ITER_CONT;
+
+ FUNC_ENTER_STATIC
+
+ HDassert(plugin_path);
+ HDassert(iter_op);
+
+ /* Open the directory */
+ if (!(dirp = HDopendir(plugin_path)))
+ HGOTO_ERROR(H5E_PLUGIN, H5E_OPENERROR, H5_ITER_ERROR, "can't open directory: %s", plugin_path)
+
+ /* 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
+
+ hbool_t plugin_matches;
+ h5_stat_t my_stat;
+ size_t len;
+
+ /* Allocate & initialize the path name */
+ len = HDstrlen(plugin_path) + HDstrlen(H5PL_PATH_SEPARATOR) + HDstrlen(dp->d_name) + 1 /*\0*/ +
+ 4; /* Extra "+4" to quiet GCC warning - 2019/07/05, QAK */
+
+ if (NULL == (path = (char *)H5MM_calloc(len)))
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, H5_ITER_ERROR, "can't allocate memory for path")
+
+ HDsnprintf(path, len, "%s/%s", plugin_path, dp->d_name);
+
+ /* Get info for directory entry */
+ if (HDstat(path, &my_stat) == -1)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, H5_ITER_ERROR, "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 */
+ plugin_type = H5PL_TYPE_ERROR;
+ plugin_info = NULL;
+ plugin_loaded = FALSE;
+ if (H5PL__open(path, H5PL_TYPE_NONE, NULL, &plugin_loaded, &plugin_type, &plugin_info) < 0)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, H5_ITER_ERROR, "failed to open plugin '%s'", path);
+
+ /* Determine if we should process this plugin */
+ plugin_matches = (iter_type == H5PL_ITER_TYPE_ALL) ||
+ ((iter_type == H5PL_ITER_TYPE_FILTER) && (plugin_type == H5PL_TYPE_FILTER)) ||
+ ((iter_type == H5PL_ITER_TYPE_VOL) && (plugin_type == H5PL_TYPE_VOL));
+
+ /* If the plugin was successfully loaded, call supplied callback function on plugin */
+ if (plugin_loaded && plugin_matches && (ret_value = iter_op(plugin_type, plugin_info, op_data)))
+ break;
+
+ path = (char *)H5MM_xfree(path);
+ } /* end if */
+ } /* end while */
+
+ if (ret_value < 0)
+ HERROR(H5E_PLUGIN, H5E_CALLBACK, "callback operator function returned failure");
+
+done:
+ if (dirp)
+ if (HDclosedir(dirp) < 0)
+ HDONE_ERROR(H5E_FILE, H5E_CLOSEERROR, H5_ITER_ERROR, "can't close directory: %s",
+ HDstrerror(errno))
+
+ path = (char *)H5MM_xfree(path);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5PL__path_table_iterate_process_path() */
+#else /* H5_HAVE_WIN32_API */
+static herr_t
+H5PL__path_table_iterate_process_path(const char *plugin_path, H5PL_iterate_type_t iter_type,
+ H5PL_iterate_t iter_op, void *op_data)
+{
+ WIN32_FIND_DATAA fdFile;
+ HANDLE hFind = INVALID_HANDLE_VALUE;
+ H5PL_type_t plugin_type;
+ const void * plugin_info = NULL;
+ hbool_t plugin_loaded;
+ char * path = NULL;
+ char service[2048];
+ herr_t ret_value = H5_ITER_CONT;
+
+ FUNC_ENTER_STATIC
+
+ /* Check args - Just assert on package functions */
+ HDassert(plugin_path);
+ HDassert(iter_op);
+
+ /* Specify a file mask. *.* = We want everything! */
+ HDsprintf(service, "%s\\*.dll", plugin_path);
+ if ((hFind = FindFirstFileA(service, &fdFile)) == INVALID_HANDLE_VALUE)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_OPENERROR, H5_ITER_ERROR, "can't open directory")
+
+ /* Loop over all the files */
+ do {
+ /* Ignore '.' and '..' */
+ if (HDstrcmp(fdFile.cFileName, ".") != 0 && HDstrcmp(fdFile.cFileName, "..") != 0) {
+ hbool_t plugin_matches;
+ size_t len;
+
+ /* Allocate & initialize the path name */
+ len = HDstrlen(plugin_path) + HDstrlen(H5PL_PATH_SEPARATOR) + HDstrlen(fdFile.cFileName) + 1;
+
+ if (NULL == (path = (char *)H5MM_calloc(len)))
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, H5_ITER_ERROR, "can't allocate memory for path")
+
+ HDsnprintf(path, len, "%s\\%s", plugin_path, fdFile.cFileName);
+
+ /* Ignore directories */
+ if (fdFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ continue;
+
+ /* Attempt to open the dynamic library */
+ plugin_type = H5PL_TYPE_ERROR;
+ plugin_info = NULL;
+ plugin_loaded = FALSE;
+ if (H5PL__open(path, H5PL_TYPE_NONE, NULL, &plugin_loaded, &plugin_type, &plugin_info) < 0)
+ HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, H5_ITER_ERROR, "failed to open plugin '%s'", path);
+
+ /* Determine if we should process this plugin */
+ plugin_matches = (iter_type == H5PL_ITER_TYPE_ALL) ||
+ ((iter_type == H5PL_ITER_TYPE_FILTER) && (plugin_type == H5PL_TYPE_FILTER)) ||
+ ((iter_type == H5PL_ITER_TYPE_VOL) && (plugin_type == H5PL_TYPE_VOL));
+
+ /* If the plugin was successfully loaded, call supplied callback function on plugin */
+ if (plugin_loaded && plugin_matches && (ret_value = iter_op(plugin_type, plugin_info, op_data)))
+ break;
+
+ path = (char *)H5MM_xfree(path);
+ }
+ } while (FindNextFileA(hFind, &fdFile));
+
+ if (ret_value < 0)
+ HERROR(H5E_PLUGIN, H5E_CALLBACK, "callback operator function returned failure");
+
+done:
+ if (hFind != INVALID_HANDLE_VALUE)
+ FindClose(hFind);
+
+ path = (char *)H5MM_xfree(path);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5PL__path_table_iterate_process_path() */
+#endif /* H5_HAVE_WIN32_API */
/*-------------------------------------------------------------------------
* Function: H5PL__find_plugin_in_path_table
@@ -674,8 +889,8 @@ H5PL__find_plugin_in_path(const H5PL_search_params_t *search_params, hbool_t *fo
continue;
}
- /* attempt to open the dynamic library as a filter library */
- if (H5PL__open(path, search_params->type, search_params->key, found, plugin_info) < 0)
+ /* attempt to open the dynamic library */
+ if (H5PL__open(path, search_params->type, search_params->key, found, NULL, plugin_info) < 0)
HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "search in directory failed")
if (*found)
HGOTO_DONE(SUCCEED)
@@ -693,7 +908,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5PL__find_plugin_in_path() */
-#else /* H5_HAVE_WIN32_API */
+#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)
@@ -741,8 +956,8 @@ H5PL__find_plugin_in_path(const H5PL_search_params_t *search_params, hbool_t *fo
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->key, found, plugin_info) < 0)
+ /* attempt to open the dynamic library */
+ if (H5PL__open(path, search_params->type, search_params->key, found, NULL, plugin_info) < 0)
HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "search in directory failed")
if (*found)
HGOTO_DONE(SUCCEED)
diff --git a/src/H5PLpkg.h b/src/H5PLpkg.h
index 1018549..5d401a6 100644
--- a/src/H5PLpkg.h
+++ b/src/H5PLpkg.h
@@ -133,7 +133,8 @@ 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, const H5PL_key_t *key,
- hbool_t *success /*out*/, const void **plugin_info /*out*/);
+ hbool_t *success /*out*/, H5PL_type_t *plugin_type /*out*/,
+ const void **plugin_info /*out*/);
H5_DLL herr_t H5PL__close(H5PL_HANDLE handle);
/* Plugin cache calls */
@@ -153,7 +154,8 @@ 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*/);
+H5_DLL herr_t H5PL__path_table_iterate(H5PL_iterate_type_t iter_type, H5PL_iterate_t iter_op, void *op_data);
+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
index 9c25933..c5e5ca4 100644
--- a/src/H5PLplugin_cache.c
+++ b/src/H5PLplugin_cache.c
@@ -264,12 +264,12 @@ H5PL__find_plugin_in_cache(const H5PL_search_params_t *search_params, hbool_t *f
/* 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 the plugin type (filter, VOL connector, etc.) and ID match, query the plugin for its info */
if ((search_params->type == (H5PL_cache_g[u]).type) &&
(search_params->key->id == (H5PL_cache_g[u]).key.id)) {
H5PL_get_plugin_info_t get_plugin_info_function;
- const H5Z_class2_t * filter_info;
+ const void * info;
/* Get the "get plugin info" function from the plugin. */
if (NULL == (get_plugin_info_function = (H5PL_get_plugin_info_t)H5PL_GET_LIB_FUNC(
@@ -277,12 +277,12 @@ H5PL__find_plugin_in_cache(const H5PL_search_params_t *search_params, hbool_t *f
HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "can't get function for H5PLget_plugin_info")
/* Call the "get plugin info" function */
- if (NULL == (filter_info = (const H5Z_class2_t *)(*get_plugin_info_function)()))
+ if (NULL == (info = (*get_plugin_info_function)()))
HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "can't get plugin info")
/* Set output parameters */
*found = TRUE;
- *plugin_info = filter_info;
+ *plugin_info = info;
/* No need to continue processing */
break;
diff --git a/src/H5PLprivate.h b/src/H5PLprivate.h
index fff36a7..938959e 100644
--- a/src/H5PLprivate.h
+++ b/src/H5PLprivate.h
@@ -44,6 +44,18 @@ typedef union H5PL_key_t {
} vol;
} H5PL_key_t;
+/* Enum dictating the type of plugins to process
+ * when iterating through available plugins
+ */
+typedef enum {
+ H5PL_ITER_TYPE_FILTER,
+ H5PL_ITER_TYPE_VOL,
+ H5PL_ITER_TYPE_ALL,
+} H5PL_iterate_type_t;
+
+/* Callback function for iterating through the available plugins */
+typedef herr_t (*H5PL_iterate_t)(H5PL_type_t plugin_type, const void *plugin_info, void *op_data);
+
/*****************************/
/* Library-private Variables */
/*****************************/
@@ -54,5 +66,6 @@ typedef union H5PL_key_t {
/* Internal API routines */
H5_DLL const void *H5PL_load(H5PL_type_t plugin_type, const H5PL_key_t *key);
+H5_DLL herr_t H5PL_iterate(H5PL_iterate_type_t iter_type, H5PL_iterate_t iter_op, void *op_data);
#endif /* _H5PLprivate_H */
diff --git a/src/H5VL.c b/src/H5VL.c
index 55779d7..c1f8adb 100644
--- a/src/H5VL.c
+++ b/src/H5VL.c
@@ -87,27 +87,6 @@ H5VLregister_connector(const H5VL_class_t *cls, hid_t vipl_id)
FUNC_ENTER_API(H5I_INVALID_HID)
H5TRACE2("i", "*#i", cls, vipl_id);
- /* Check arguments */
- if (!cls)
- HGOTO_ERROR(H5E_ARGS, H5E_UNINITIALIZED, H5I_INVALID_HID,
- "VOL connector class pointer cannot be NULL")
- if (H5VL_VERSION != cls->version)
- HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "VOL connector has incompatible version")
- if (!cls->name)
- HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID,
- "VOL connector class name cannot be the NULL pointer")
- if (0 == HDstrlen(cls->name))
- HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID,
- "VOL connector class name cannot be the empty string")
- if (cls->info_cls.copy && !cls->info_cls.free)
- HGOTO_ERROR(
- H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID,
- "VOL connector must provide free callback for VOL info objects when a copy callback is provided")
- if (cls->wrap_cls.get_wrap_ctx && !cls->wrap_cls.free_wrap_ctx)
- HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID,
- "VOL connector must provide free callback for object wrapping contexts when a get "
- "callback is provided")
-
/* Check VOL initialization property list */
if (H5P_DEFAULT == vipl_id)
vipl_id = H5P_VOL_INITIALIZE_DEFAULT;
diff --git a/src/H5VLcallback.c b/src/H5VLcallback.c
index 4ab398f..8b58cea 100644
--- a/src/H5VLcallback.c
+++ b/src/H5VLcallback.c
@@ -29,10 +29,11 @@
#include "H5private.h" /* Generic Functions */
#include "H5Eprivate.h" /* Error handling */
-#include "H5Fprivate.h" /* File access */
+#include "H5Fprivate.h" /* File access */
#include "H5Iprivate.h" /* IDs */
#include "H5MMprivate.h" /* Memory management */
#include "H5Pprivate.h" /* Property lists */
+#include "H5PLprivate.h" /* Plugins */
#include "H5VLpkg.h" /* Virtual Object Layer */
/****************/
@@ -43,6 +44,16 @@
/* Local Typedefs */
/******************/
+/* Structure used when trying to find a
+ * VOL connector to open a given file with.
+ */
+typedef struct H5VL_file_open_find_connector_t {
+ const char * filename;
+ const H5VL_class_t * cls;
+ H5VL_connector_prop_t *connector_prop;
+ hid_t fapl_id;
+} H5VL_file_open_find_connector_t;
+
/********************/
/* Package Typedefs */
/********************/
@@ -101,6 +112,8 @@ static void * H5VL__file_create(const H5VL_class_t *cls, const char *name, unsig
hid_t fapl_id, hid_t dxpl_id, void **req);
static void * H5VL__file_open(const H5VL_class_t *cls, const char *name, unsigned flags, hid_t fapl_id,
hid_t dxpl_id, void **req);
+static herr_t H5VL__file_open_find_connector_cb(H5PL_type_t plugin_type, const void *plugin_info,
+ void *op_data);
static herr_t H5VL__file_get(void *obj, const H5VL_class_t *cls, H5VL_file_get_t get_type, hid_t dxpl_id,
void **req, va_list arguments);
static herr_t H5VL__file_specific(void *obj, const H5VL_class_t *cls, H5VL_file_specific_t specific_type,
@@ -3347,6 +3360,98 @@ done:
} /* end H5VL__file_open() */
/*-------------------------------------------------------------------------
+ * Function: H5VL__file_open_find_connector_cb
+ *
+ * Purpose: Iteration callback for H5PL_iterate that tries to find the
+ * correct VOL connector to open a file with when
+ * H5VL_file_open fails for its given VOL connector. Iterates
+ * through all of the available VOL connector plugins until
+ * H5Fis_accessible returns true for the given filename and
+ * VOL connector.
+ *
+ * Return: H5_ITER_CONT if current plugin can't open the given file
+ * H5_ITER_STOP if current plugin can open given file
+ * H5_ITER_ERROR if an error occurs while trying to determine
+ * if current plugin can open given file.
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__file_open_find_connector_cb(H5PL_type_t plugin_type, const void *plugin_info, void *op_data)
+{
+ H5VL_file_open_find_connector_t *udata = (H5VL_file_open_find_connector_t *)op_data;
+ const H5VL_class_t * cls = (const H5VL_class_t *)plugin_info;
+ H5P_genplist_t * fapl_plist;
+ H5P_genplist_t * fapl_plist_copy;
+ herr_t status;
+ htri_t is_accessible = FALSE;
+ hid_t connector_id = H5I_INVALID_HID;
+ hid_t fapl_id = H5I_INVALID_HID;
+ herr_t ret_value = H5_ITER_CONT;
+
+ FUNC_ENTER_STATIC
+
+ HDassert(udata);
+ HDassert(udata->filename);
+ HDassert(udata->connector_prop);
+ HDassert(cls);
+ HDassert(plugin_type == H5PL_TYPE_VOL);
+
+ /* Silence compiler */
+ (void)plugin_type;
+
+ udata->cls = cls;
+
+ /* Attempt to register plugin as a VOL connector */
+ if ((connector_id = H5VL__register_connector_by_class(cls, TRUE, H5P_VOL_INITIALIZE_DEFAULT)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5_ITER_ERROR, "unable to register VOL connector")
+
+ /* Setup FAPL with registered VOL connector */
+ if (NULL == (fapl_plist = (H5P_genplist_t *)H5I_object_verify(udata->fapl_id, H5I_GENPROP_LST)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5_ITER_ERROR, "not a property list")
+ if ((fapl_id = H5P_copy_plist(fapl_plist, TRUE)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy fapl");
+ if (NULL == (fapl_plist_copy = (H5P_genplist_t *)H5I_object_verify(fapl_id, H5I_GENPROP_LST)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5_ITER_ERROR, "not a property list")
+ if (H5P_set_vol(fapl_plist_copy, connector_id, NULL) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, H5_ITER_ERROR, "can't set VOL connector on fapl")
+
+ /* Check if file is accessible with given VOL connector */
+ H5E_BEGIN_TRY
+ {
+ status = H5VL_file_specific(NULL, H5VL_FILE_IS_ACCESSIBLE, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL,
+ fapl_id, udata->filename, &is_accessible);
+ }
+ H5E_END_TRY;
+
+ /* If the file was accessible with the current VOL connector, return
+ * the FAPL with that VOL connector set on it. Errors are ignored here
+ * as some VOL connectors may not support H5Fis_accessible.
+ */
+ if (status == SUCCEED && is_accessible > 0) {
+ /* Modify 'connector_prop' to point to the VOL connector that
+ * was actually used to open the file, rather than the original
+ * VOL connector that was requested.
+ */
+ udata->connector_prop->connector_id = connector_id;
+ udata->connector_prop->connector_info = NULL;
+
+ udata->fapl_id = fapl_id;
+ ret_value = H5_ITER_STOP;
+ } /* end if */
+
+done:
+ if (ret_value != H5_ITER_STOP) {
+ if (fapl_id >= 0 && H5I_dec_app_ref(fapl_id) < 0)
+ HDONE_ERROR(H5E_PLIST, H5E_CANTCLOSEOBJ, H5_ITER_ERROR, "can't close fapl")
+ if (connector_id >= 0 && H5I_dec_app_ref(connector_id) < 0)
+ HDONE_ERROR(H5E_ID, H5E_CANTCLOSEOBJ, H5_ITER_ERROR, "can't close VOL connector ID")
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__file_open_find_connector_cb() */
+
+/*-------------------------------------------------------------------------
* Function: H5VL_file_open
*
* Purpose: Opens a file through the VOL.
@@ -3360,7 +3465,7 @@ done:
*-------------------------------------------------------------------------
*/
void *
-H5VL_file_open(const H5VL_connector_prop_t *connector_prop, const char *name, unsigned flags, hid_t fapl_id,
+H5VL_file_open(H5VL_connector_prop_t *connector_prop, const char *name, unsigned flags, hid_t fapl_id,
hid_t dxpl_id, void **req)
{
H5VL_class_t *cls; /* VOL Class structure for callback info */
@@ -3373,8 +3478,54 @@ H5VL_file_open(const H5VL_connector_prop_t *connector_prop, const char *name, un
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a VOL connector ID")
/* Call the corresponding internal VOL routine */
- if (NULL == (ret_value = H5VL__file_open(cls, name, flags, fapl_id, dxpl_id, req)))
- HGOTO_ERROR(H5E_VOL, H5E_CANTOPENOBJ, NULL, "open failed")
+ if (NULL == (ret_value = H5VL__file_open(cls, name, flags, fapl_id, dxpl_id, req))) {
+ H5VL_file_open_find_connector_t find_connector_ud;
+ hbool_t find_connector;
+ hbool_t connector_available = FALSE;
+
+ /* Opening the file failed - Determine whether we should search
+ * the plugin path to see if any other VOL connectors are available
+ * to attempt to open the file with. This only occurs if no particular
+ * VOL connector was specified (either via a FAPL or the
+ * HDF5_VOL_CONNECTOR environment variable).
+ */
+ find_connector = !getenv("HDF5_VOL_CONNECTOR") && ((H5P_FILE_ACCESS_DEFAULT == fapl_id) ||
+ connector_prop->connector_id == H5_DEFAULT_VOL);
+
+ if (find_connector) {
+ herr_t iter_ret;
+
+ find_connector_ud.connector_prop = connector_prop;
+ find_connector_ud.filename = name;
+ find_connector_ud.cls = NULL;
+ find_connector_ud.fapl_id = fapl_id;
+
+ iter_ret = H5PL_iterate(H5PL_ITER_TYPE_VOL, H5VL__file_open_find_connector_cb,
+ (void *)&find_connector_ud);
+ if (iter_ret < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_BADITER, NULL,
+ "failed to iterate over available VOL connector plugins")
+ else if (iter_ret)
+ connector_available = TRUE;
+ } /* end if */
+
+ /* If one of the available VOL connector plugins is
+ * able to open the file, clear the error stack from any
+ * previous file open failures and then open the file.
+ * Otherwise, if no VOL connectors are available, throw
+ * error from original file open failure.
+ */
+ if (connector_available) {
+ H5E_clear_stack(NULL);
+
+ if (NULL == (ret_value = H5VL__file_open(find_connector_ud.cls, name, flags,
+ find_connector_ud.fapl_id, dxpl_id, req)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPENOBJ, NULL, "can't open file '%s' with VOL connector '%s'",
+ name, find_connector_ud.cls->name)
+ }
+ else
+ HGOTO_ERROR(H5E_VOL, H5E_CANTOPENOBJ, NULL, "open failed")
+ } /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5VLint.c b/src/H5VLint.c
index bc06361..17578b8 100644
--- a/src/H5VLint.c
+++ b/src/H5VLint.c
@@ -1197,6 +1197,27 @@ H5VL__register_connector_by_class(const H5VL_class_t *cls, hbool_t app_ref, hid_
FUNC_ENTER_PACKAGE
+ /* Check arguments */
+ if (!cls)
+ HGOTO_ERROR(H5E_ARGS, H5E_UNINITIALIZED, H5I_INVALID_HID,
+ "VOL connector class pointer cannot be NULL")
+ if (H5VL_VERSION != cls->version)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "VOL connector has incompatible version")
+ if (!cls->name)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID,
+ "VOL connector class name cannot be the NULL pointer")
+ if (0 == HDstrlen(cls->name))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID,
+ "VOL connector class name cannot be the empty string")
+ if (cls->info_cls.copy && !cls->info_cls.free)
+ HGOTO_ERROR(
+ H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID,
+ "VOL connector must provide free callback for VOL info objects when a copy callback is provided")
+ if (cls->wrap_cls.get_wrap_ctx && !cls->wrap_cls.free_wrap_ctx)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID,
+ "VOL connector must provide free callback for object wrapping contexts when a get "
+ "callback is provided")
+
/* Set up op data for iteration */
op_data.kind = H5VL_GET_CONNECTOR_BY_NAME;
op_data.u.name = cls->name;
diff --git a/src/H5VLprivate.h b/src/H5VLprivate.h
index eefd648..a224a14 100644
--- a/src/H5VLprivate.h
+++ b/src/H5VLprivate.h
@@ -197,7 +197,7 @@ H5_DLL herr_t H5VL_datatype_close(const H5VL_object_t *vol_obj, hid_t dxpl_id, v
/* File functions */
H5_DLL void * H5VL_file_create(const H5VL_connector_prop_t *connector_prop, const char *name, unsigned flags,
hid_t fcpl_id, hid_t fapl_id, hid_t dxpl_id, void **req);
-H5_DLL void * H5VL_file_open(const H5VL_connector_prop_t *connector_prop, const char *name, unsigned flags,
+H5_DLL void * H5VL_file_open(H5VL_connector_prop_t *connector_prop, const char *name, unsigned flags,
hid_t fapl_id, hid_t dxpl_id, void **req);
H5_DLL herr_t H5VL_file_get(const H5VL_object_t *vol_obj, H5VL_file_get_t get_type, hid_t dxpl_id, void **req,
...);