summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@lbl.gov>2020-12-10 17:01:04 (GMT)
committerGitHub <noreply@github.com>2020-12-10 17:01:04 (GMT)
commit17a2e88769c15d8684bda4d8a6c9f53836f7b65b (patch)
treee11decdcdfdd7bf594475b3d9520a403d1478d49
parent4713a6d23840ed222d90f3ca73f037cb20b5d444 (diff)
downloadhdf5-17a2e88769c15d8684bda4d8a6c9f53836f7b65b.zip
hdf5-17a2e88769c15d8684bda4d8a6c9f53836f7b65b.tar.gz
hdf5-17a2e88769c15d8684bda4d8a6c9f53836f7b65b.tar.bz2
Enforce VOL framework version compatibility when registering connectors. Also add a version for the connector itself, some refactoring on the register calls, and move the logic for matching / rejecting a VOL connector class from the plugin module to the VOL module. (#151)
-rw-r--r--src/H5PLint.c29
-rw-r--r--src/H5VL.c5
-rw-r--r--src/H5VLconnector.h3
-rw-r--r--src/H5VLint.c72
-rw-r--r--src/H5VLnative.c17
-rw-r--r--src/H5VLpassthru.c3
-rw-r--r--src/H5VLpkg.h3
-rw-r--r--src/H5VLprivate.h5
-rw-r--r--src/H5VLpublic.h11
-rw-r--r--test/h5test.c1
-rw-r--r--test/null_vol_connector.c3
-rw-r--r--test/vol.c22
12 files changed, 132 insertions, 42 deletions
diff --git a/src/H5PLint.c b/src/H5PLint.c
index 0975a9e..3b9683b 100644
--- a/src/H5PLint.c
+++ b/src/H5PLint.c
@@ -354,30 +354,19 @@ H5PL__open(const char *path, H5PL_type_t type, const H5PL_key_t *key, hbool_t *s
}
case H5PL_TYPE_VOL: {
- const H5VL_class_t *cls;
+ const void *cls;
/* Get the plugin info */
- if (NULL == (cls = (const H5VL_class_t *)(*get_plugin_info)()))
+ if (NULL == (cls = (const void *)(*get_plugin_info)()))
HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "can't get VOL connector info from plugin")
- /* Which kind of key are we looking for? */
- if (key->vol.kind == H5VL_GET_CONNECTOR_BY_NAME) {
- /* If the plugin names match, we're done. Set the output parameters. */
- if (cls->name && !HDstrcmp(cls->name, key->vol.u.name)) {
- *plugin_info = (const void *)cls;
- *success = TRUE;
- } /* end if */
- } /* end if */
- else {
- /* Sanity check */
- HDassert(key->vol.kind == H5VL_GET_CONNECTOR_BY_VALUE);
-
- /* If the plugin values match, we're done. Set the output parameters. */
- if (cls->value == key->vol.u.value) {
- *plugin_info = (const void *)cls;
- *success = TRUE;
- } /* end if */
- } /* end else */
+ /* 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)
+ *plugin_info = cls;
break;
}
diff --git a/src/H5VL.c b/src/H5VL.c
index a06120c..d73c95e 100644
--- a/src/H5VL.c
+++ b/src/H5VL.c
@@ -91,6 +91,9 @@ H5VLregister_connector(const H5VL_class_t *cls, hid_t vipl_id)
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")
@@ -113,7 +116,7 @@ H5VLregister_connector(const H5VL_class_t *cls, hid_t vipl_id)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a VOL initialize property list")
/* Register connector */
- if ((ret_value = H5VL__register_connector(cls, TRUE, vipl_id)) < 0)
+ if ((ret_value = H5VL__register_connector_by_class(cls, TRUE, vipl_id)) < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VOL connector")
done:
diff --git a/src/H5VLconnector.h b/src/H5VLconnector.h
index 48f4a28..d873019 100644
--- a/src/H5VLconnector.h
+++ b/src/H5VLconnector.h
@@ -445,9 +445,10 @@ typedef struct H5VL_token_class_t {
//! [H5VL_class_t_snip]
typedef struct H5VL_class_t {
/* Overall connector fields & callbacks */
- unsigned int version; /**< VOL connector class struct version # */
+ unsigned version; /**< VOL connector class struct version # */
H5VL_class_value_t value; /**< Value to identify connector */
const char * name; /**< Connector name (MUST be unique!) */
+ unsigned conn_version; /**< Version # of connector */
unsigned cap_flags; /**< Capability flags for connector */
herr_t (*initialize)(hid_t vipl_id); /**< Connector initialization callback */
herr_t (*terminate)(void); /**< Connector termination callback */
diff --git a/src/H5VLint.c b/src/H5VLint.c
index 10df59a..cdd8139 100644
--- a/src/H5VLint.c
+++ b/src/H5VLint.c
@@ -1075,7 +1075,7 @@ done:
} /* end H5VL_file_is_same() */
/*-------------------------------------------------------------------------
- * Function: H5VL_register_connector
+ * Function: H5VL__register_connector
*
* Purpose: Registers a new VOL connector as a member of the virtual object
* layer class.
@@ -1091,13 +1091,13 @@ done:
*-------------------------------------------------------------------------
*/
hid_t
-H5VL_register_connector(const void *_cls, hbool_t app_ref, hid_t vipl_id)
+H5VL__register_connector(const void *_cls, hbool_t app_ref, hid_t vipl_id)
{
const H5VL_class_t *cls = (const H5VL_class_t *)_cls;
H5VL_class_t * saved = NULL;
hid_t ret_value = H5I_INVALID_HID;
- FUNC_ENTER_NOAPI(H5I_INVALID_HID)
+ FUNC_ENTER_PACKAGE
/* Check arguments */
HDassert(cls);
@@ -1128,10 +1128,10 @@ done:
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5VL_register_connector() */
+} /* end H5VL__register_connector() */
/*-------------------------------------------------------------------------
- * Function: H5VL__register_connector
+ * Function: H5VL__register_connector_by_class
*
* Purpose: Registers a new VOL connector as a member of the virtual object
* layer class.
@@ -1148,7 +1148,7 @@ done:
*-------------------------------------------------------------------------
*/
hid_t
-H5VL__register_connector(const H5VL_class_t *cls, hbool_t app_ref, hid_t vipl_id)
+H5VL__register_connector_by_class(const H5VL_class_t *cls, hbool_t app_ref, hid_t vipl_id)
{
H5VL_get_connector_ud_t op_data; /* Callback info for connector search */
hid_t ret_value = H5I_INVALID_HID; /* Return value */
@@ -1173,13 +1173,13 @@ H5VL__register_connector(const H5VL_class_t *cls, hbool_t app_ref, hid_t vipl_id
} /* end if */
else {
/* Create a new class ID */
- if ((ret_value = H5VL_register_connector(cls, app_ref, vipl_id)) < 0)
+ if ((ret_value = H5VL__register_connector(cls, app_ref, vipl_id)) < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VOL connector")
} /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5VL__register_connector() */
+} /* end H5VL__register_connector_by_class() */
/*-------------------------------------------------------------------------
* Function: H5VL__register_connector_by_name
@@ -1233,7 +1233,7 @@ H5VL__register_connector_by_name(const char *name, hbool_t app_ref, hid_t vipl_i
HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, H5I_INVALID_HID, "unable to load VOL connector")
/* Register the connector we loaded */
- if ((ret_value = H5VL_register_connector(cls, app_ref, vipl_id)) < 0)
+ if ((ret_value = H5VL__register_connector(cls, app_ref, vipl_id)) < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VOL connector ID")
} /* end else */
@@ -1293,7 +1293,7 @@ H5VL__register_connector_by_value(H5VL_class_value_t value, hbool_t app_ref, hid
HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, H5I_INVALID_HID, "unable to load VOL connector")
/* Register the connector we loaded */
- if ((ret_value = H5VL_register_connector(cls, app_ref, vipl_id)) < 0)
+ if ((ret_value = H5VL__register_connector(cls, app_ref, vipl_id)) < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VOL connector ID")
} /* end else */
@@ -2341,3 +2341,55 @@ H5VL_wrap_register(H5I_type_t type, void *obj, hbool_t app_ref)
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5VL_wrap_register() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_check_plugin_load
+ *
+ * Purpose: Check if a VOL connector matches the search criteria, and
+ * can be loaded.
+ *
+ * Note: Matching the connector's name / value, but the connector
+ * having an incompatible version is not an error, but means
+ * that the connector isn't a "match". Setting the SUCCEED
+ * value to FALSE and not failing for that case allows the
+ * plugin framework to keep looking for other DLLs that match
+ * and have a compatible version.
+ *
+ * Return: SUCCEED / FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_check_plugin_load(const H5VL_class_t *cls, const H5PL_key_t *key, hbool_t *success)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity checks */
+ HDassert(cls);
+ HDassert(key);
+ HDassert(success);
+
+ /* Which kind of key are we looking for? */
+ if (key->vol.kind == H5VL_GET_CONNECTOR_BY_NAME) {
+ /* Check if plugin name matches VOL connector class name */
+ if (cls->name && !HDstrcmp(cls->name, key->vol.u.name))
+ *success = TRUE;
+ } /* end if */
+ else {
+ /* Sanity check */
+ HDassert(key->vol.kind == H5VL_GET_CONNECTOR_BY_VALUE);
+
+ /* Check if plugin value matches VOL connector class value */
+ if (cls->value == key->vol.u.value)
+ *success = TRUE;
+ } /* end else */
+
+ /* Connector is a match, but might not be a compatible version */
+ if (*success && cls->version != H5VL_VERSION)
+ *success = FALSE;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_check_plugin_load() */
diff --git a/src/H5VLnative.c b/src/H5VLnative.c
index 0973e34..746264f 100644
--- a/src/H5VLnative.c
+++ b/src/H5VLnative.c
@@ -15,6 +15,16 @@
* using HDF5 VFDs.
*/
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5VL_FRIEND /* Suppress error about including H5VLpkg */
+
+/***********/
+/* Headers */
+/***********/
+
#include "H5private.h" /* Generic Functions */
#include "H5Aprivate.h" /* Attributes */
#include "H5Dprivate.h" /* Datasets */
@@ -25,7 +35,7 @@
#include "H5Oprivate.h" /* Object headers */
#include "H5Pprivate.h" /* Property lists */
#include "H5Tprivate.h" /* Datatypes */
-#include "H5VLprivate.h" /* Virtual Object Layer */
+#include "H5VLpkg.h" /* Virtual Object Layer */
#include "H5VLnative_private.h" /* Native VOL connector */
@@ -37,9 +47,10 @@ static herr_t H5VL__native_term(void);
/* Native VOL connector class struct */
static const H5VL_class_t H5VL_native_cls_g = {
- H5VL_NATIVE_VERSION, /* version */
+ H5VL_VERSION, /* VOL class struct version */
H5VL_NATIVE_VALUE, /* value */
H5VL_NATIVE_NAME, /* name */
+ H5VL_NATIVE_VERSION, /* connector version */
0, /* capability flags */
NULL, /* initialize */
H5VL__native_term, /* terminate */
@@ -176,7 +187,7 @@ H5VL_native_register(void)
/* Register the native VOL connector, if it isn't already */
if (H5I_INVALID_HID == H5VL_NATIVE_ID_g)
if ((H5VL_NATIVE_ID_g =
- H5VL_register_connector(&H5VL_native_cls_g, TRUE, H5P_VOL_INITIALIZE_DEFAULT)) < 0)
+ H5VL__register_connector(&H5VL_native_cls_g, TRUE, H5P_VOL_INITIALIZE_DEFAULT)) < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTINSERT, H5I_INVALID_HID, "can't create ID for native VOL connector")
/* Set return value */
diff --git a/src/H5VLpassthru.c b/src/H5VLpassthru.c
index 0725900..4097a75 100644
--- a/src/H5VLpassthru.c
+++ b/src/H5VLpassthru.c
@@ -263,9 +263,10 @@ static herr_t H5VL_pass_through_optional(void *obj, int op_type, hid_t dxpl_id,
/* Pass through VOL connector class struct */
static const H5VL_class_t H5VL_pass_through_g = {
- H5VL_PASSTHRU_VERSION, /* version */
+ H5VL_VERSION, /* VOL class struct version */
(H5VL_class_value_t)H5VL_PASSTHRU_VALUE, /* value */
H5VL_PASSTHRU_NAME, /* name */
+ H5VL_PASSTHRU_VERSION, /* connector version */
0, /* capability flags */
H5VL_pass_through_init, /* initialize */
H5VL_pass_through_term, /* terminate */
diff --git a/src/H5VLpkg.h b/src/H5VLpkg.h
index c784e50..5799d2c 100644
--- a/src/H5VLpkg.h
+++ b/src/H5VLpkg.h
@@ -43,7 +43,8 @@
/******************************/
/* Package Private Prototypes */
/******************************/
-H5_DLL hid_t H5VL__register_connector(const H5VL_class_t *cls, hbool_t app_ref, hid_t vipl_id);
+H5_DLL hid_t H5VL__register_connector(const void *cls, hbool_t app_ref, hid_t vipl_id);
+H5_DLL hid_t H5VL__register_connector_by_class(const H5VL_class_t *cls, hbool_t app_ref, hid_t vipl_id);
H5_DLL hid_t H5VL__register_connector_by_name(const char *name, hbool_t app_ref, hid_t vipl_id);
H5_DLL hid_t H5VL__register_connector_by_value(H5VL_class_value_t value, hbool_t app_ref, hid_t vipl_id);
H5_DLL htri_t H5VL__is_connector_registered_by_name(const char *name);
diff --git a/src/H5VLprivate.h b/src/H5VLprivate.h
index a020923..b54d8aa 100644
--- a/src/H5VLprivate.h
+++ b/src/H5VLprivate.h
@@ -14,7 +14,7 @@
#define _H5VLprivate_H
/* Include package's public header */
-#include "H5VLpublic.h" /* Generic Functions */
+#include "H5VLpublic.h" /* Generic Functions */
/* Private headers needed by this file */
@@ -67,7 +67,8 @@ H5_DLL herr_t H5VL_conn_copy(H5VL_connector_prop_t *value);
H5_DLL herr_t H5VL_conn_free(const H5VL_connector_prop_t *info);
/* Functions that deal with VOL connectors */
-H5_DLL hid_t H5VL_register_connector(const void *cls, hbool_t app_ref, hid_t vipl_id);
+union H5PL_key_t;
+H5_DLL herr_t H5VL_check_plugin_load(const H5VL_class_t *cls, const union H5PL_key_t *key, hbool_t *success);
/* NOTE: The object and ID functions below deal in VOL objects (i.e.;
* H5VL_object_t). Similar non-VOL calls exist in H5Iprivate.h. Use
diff --git a/src/H5VLpublic.h b/src/H5VLpublic.h
index 7494586..03bf807 100644
--- a/src/H5VLpublic.h
+++ b/src/H5VLpublic.h
@@ -25,6 +25,17 @@
/* Public Macros */
/*****************/
+/**
+ * \ingroup H5VLDEF
+ * \brief Version # of VOL class struct & callbacks
+ *
+ * \details Each VOL connector must set the 'version' field in the H5VL_class_t
+ * struct to the version of the H5VL_class_t struct that the connector
+ * implements. The HDF5 library will reject connectors with
+ * incompatible structs.
+ */
+#define H5VL_VERSION 1
+
/* VOL connector identifier values
* These are H5VL_class_value_t values, NOT hid_t values!
*/
diff --git a/test/h5test.c b/test/h5test.c
index 92534bd..9c59e77 100644
--- a/test/h5test.c
+++ b/test/h5test.c
@@ -2040,6 +2040,7 @@ h5_get_dummy_vol_class(void)
/* Fill in the minimum parameters to make a VOL connector class that
* can be registered.
*/
+ vol_class->version = H5VL_VERSION;
vol_class->name = "dummy";
return vol_class;
diff --git a/test/null_vol_connector.c b/test/null_vol_connector.c
index 095169c..9a382b7 100644
--- a/test/null_vol_connector.c
+++ b/test/null_vol_connector.c
@@ -26,9 +26,10 @@
/* The VOL class struct */
static const H5VL_class_t null_vol_g = {
- 0, /* version */
+ H5VL_VERSION, /* VOL class struct version */
NULL_VOL_CONNECTOR_VALUE, /* value */
NULL_VOL_CONNECTOR_NAME, /* name */
+ 0, /* connector version */
0, /* capability flags */
NULL, /* initialize */
NULL, /* terminate */
diff --git a/test/vol.c b/test/vol.c
index b662cb8..6c9da62 100644
--- a/test/vol.c
+++ b/test/vol.c
@@ -42,9 +42,10 @@ const char *FILENAME[] = {"native_vol_test", NULL};
* functionality.
*/
static const H5VL_class_t fake_vol_g = {
- 0, /* version */
+ H5VL_VERSION, /* VOL class struct version */
FAKE_VOL_VALUE, /* value */
FAKE_VOL_NAME, /* name */
+ 0, /* connector version */
0, /* capability flags */
NULL, /* initialize */
NULL, /* terminate */
@@ -181,6 +182,7 @@ test_vol_registration(void)
htri_t is_registered = FAIL;
hid_t vol_id = H5I_INVALID_HID;
hid_t vol_id2 = H5I_INVALID_HID;
+ H5VL_class_t *bad_fake_vol_class = NULL;
TESTING("VOL registration");
@@ -204,6 +206,19 @@ test_vol_registration(void)
if (H5Pclose(lapl_id) < 0)
TEST_ERROR;
+ /* Test registering a VOL connector with an incompatible version # */
+ if (NULL == (bad_fake_vol_class = HDmalloc(sizeof(H5VL_class_t))))
+ TEST_ERROR;
+ HDmemcpy(bad_fake_vol_class, &fake_vol_g, sizeof(H5VL_class_t));
+ bad_fake_vol_class->version = H5VL_VERSION + 1;
+ H5E_BEGIN_TRY {
+ vol_id = H5VLregister_connector(bad_fake_vol_class, H5P_DEFAULT);
+ } H5E_END_TRY;
+ if (H5I_INVALID_HID != vol_id)
+ FAIL_PUTS_ERROR("should not be able to register a connector with an incompatible version #");
+ HDfree(bad_fake_vol_class);
+ bad_fake_vol_class = NULL;
+
/* Load a VOL interface
* The vipl_id does nothing without a VOL that needs it, but we do need to
* test creating a property list of that class and passing it along as a
@@ -277,8 +292,11 @@ error:
H5Pclose(vipl_id);
}
H5E_END_TRY;
- return FAIL;
+ if (bad_fake_vol_class)
+ HDfree(bad_fake_vol_class);
+
+ return FAIL;
} /* end test_vol_registration() */
/*-------------------------------------------------------------------------