summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/H5.c6
-rw-r--r--src/H5Dcontig.c20
-rw-r--r--src/H5Fint.c13
-rw-r--r--src/H5Pfapl.c37
-rw-r--r--src/H5Pint.c110
-rw-r--r--src/H5Ppkg.h4
-rw-r--r--src/H5Pprivate.h3
-rw-r--r--src/H5VL.c200
-rw-r--r--src/H5VLcallback.c45
-rw-r--r--src/H5VLint.c629
-rw-r--r--src/H5VLpassthru.c36
-rw-r--r--src/H5VLpkg.h15
-rw-r--r--src/H5VLprivate.h8
13 files changed, 840 insertions, 286 deletions
diff --git a/src/H5.c b/src/H5.c
index bf4643c..104c9fd 100644
--- a/src/H5.c
+++ b/src/H5.c
@@ -214,7 +214,7 @@ H5_init_library(void)
*/
if(H5E_init() < 0)
HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize error interface")
- if(H5VL_init() < 0)
+ if(H5VL_init_phase1() < 0)
HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize vol interface")
if(H5P_init() < 0)
HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize property list interface")
@@ -229,6 +229,10 @@ H5_init_library(void)
if(H5FS_init() < 0)
HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize FS interface")
+ /* Finish initializing interfaces that depend on the interfaces above */
+ if(H5VL_init_phase2() < 0)
+ HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize vol interface")
+
/* Debugging? */
H5_debug_mask("-all");
H5_debug_mask(HDgetenv("HDF5_DEBUG"));
diff --git a/src/H5Dcontig.c b/src/H5Dcontig.c
index ad12ba0..8bd5e31 100644
--- a/src/H5Dcontig.c
+++ b/src/H5Dcontig.c
@@ -755,11 +755,6 @@ H5D__contig_readvv_sieve_cb(hsize_t dst_off, hsize_t src_off, size_t len,
/* Reset sieve buffer dirty flag */
dset_contig->sieve_dirty = FALSE;
-
- /* Stash local copies of these value */
- sieve_start = dset_contig->sieve_loc;
- sieve_size = dset_contig->sieve_size;
- sieve_end = sieve_start+sieve_size;
} /* end else */
} /* end if */
else {
@@ -825,11 +820,6 @@ H5D__contig_readvv_sieve_cb(hsize_t dst_off, hsize_t src_off, size_t len,
min = MIN3(rel_eoa - dset_contig->sieve_loc, max_data, dset_contig->sieve_buf_size);
H5_CHECKED_ASSIGN(dset_contig->sieve_size, size_t, min, hsize_t);
- /* Update local copies of sieve information */
- sieve_start = dset_contig->sieve_loc;
- sieve_size = dset_contig->sieve_size;
- sieve_end = sieve_start + sieve_size;
-
/* Read the new sieve buffer */
if(H5F_block_read(file, H5FD_MEM_DRAW, dset_contig->sieve_loc, dset_contig->sieve_size, dset_contig->sieve_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "block read failed")
@@ -1110,11 +1100,6 @@ H5D__contig_writevv_sieve_cb(hsize_t dst_off, hsize_t src_off, size_t len,
/* Adjust sieve size */
dset_contig->sieve_size += len;
-
- /* Update local copies of sieve information */
- sieve_start = dset_contig->sieve_loc;
- sieve_size = dset_contig->sieve_size;
- sieve_end = sieve_start + sieve_size;
} /* end if */
/* Can't add the new data onto the existing sieve buffer */
else {
@@ -1146,11 +1131,6 @@ H5D__contig_writevv_sieve_cb(hsize_t dst_off, hsize_t src_off, size_t len,
min = MIN3(rel_eoa - dset_contig->sieve_loc, max_data, dset_contig->sieve_buf_size);
H5_CHECKED_ASSIGN(dset_contig->sieve_size, size_t, min, hsize_t);
- /* Update local copies of sieve information */
- sieve_start = dset_contig->sieve_loc;
- sieve_size = dset_contig->sieve_size;
- sieve_end = sieve_start + sieve_size;
-
/* Check if there is any point in reading the data from the file */
if(dset_contig->sieve_size > len) {
/* Read the new sieve buffer */
diff --git a/src/H5Fint.c b/src/H5Fint.c
index 8a7019d..339c61b 100644
--- a/src/H5Fint.c
+++ b/src/H5Fint.c
@@ -1362,19 +1362,10 @@ H5F__dest(H5F_t *f, hbool_t flush)
HDONE_ERROR(H5E_FILE, H5E_CANTDEC, FAIL, "can't close property list")
/* Clean up the cached VOL connector ID & info */
- if(f->shared->vol_info) {
- H5VL_class_t *connector; /* Pointer to connector */
-
- /* Retrieve the connector for the ID */
- if(NULL == (connector = (H5VL_class_t *)H5I_object(f->shared->vol_id)))
- /* Push error, but keep going*/
- HDONE_ERROR(H5E_FILE, H5E_BADTYPE, FAIL, "not a VOL connector ID")
-
- /* Free the connector info */
- if(H5VL_free_connector_info(connector, f->shared->vol_info) < 0)
+ if(f->shared->vol_info)
+ if(H5VL_free_connector_info(f->shared->vol_id, f->shared->vol_info) < 0)
/* Push error, but keep going*/
HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "unable to release VOL connector info object")
- } /* end if */
if(f->shared->vol_id > 0)
if(H5I_dec_ref(f->shared->vol_id) < 0)
/* Push error, but keep going*/
diff --git a/src/H5Pfapl.c b/src/H5Pfapl.c
index bfb52ff..4b9bbdc 100644
--- a/src/H5Pfapl.c
+++ b/src/H5Pfapl.c
@@ -4907,6 +4907,43 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5P_reset_vol_class
+ *
+ * Purpose: Change the VOL connector for a file access property class.
+ *
+ * Note: The VOL property will be copied into the property list and
+ * the reference count on the previous VOL will _NOT_ be decremented.
+ * The reference count on the new VOL will _NOT_ be incremented.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * March 8, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5P_reset_vol_class(const H5P_genclass_t *pclass, const H5VL_connector_prop_t *vol_prop)
+{
+ H5VL_connector_prop_t old_vol_prop; /* Previous VOL connector property */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Get the connector ID & info property */
+ if(H5P__class_get(pclass, H5F_ACS_VOL_CONN_NAME, &old_vol_prop) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get VOL connector ID & info")
+
+ /* Set the new connector ID & info property */
+ if(H5P__class_set(pclass, H5F_ACS_VOL_CONN_NAME, vol_prop) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set VOL connector ID & info")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5P_set_vol_class() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5Pset_vol
*
* Purpose: Set the file VOL connector (VOL_ID) for a file access
diff --git a/src/H5Pint.c b/src/H5Pint.c
index e2ae792..79b6cf5 100644
--- a/src/H5Pint.c
+++ b/src/H5Pint.c
@@ -3061,6 +3061,116 @@ done:
/*--------------------------------------------------------------------------
NAME
+ H5P__class_get
+ PURPOSE
+ Internal routine to get a property's value from a property class.
+ USAGE
+ herr_t H5P__class_get(pclass, name, value)
+ const H5P_genclass_t *pclass; IN: Property class to find property in
+ const char *name; IN: Name of property to get
+ void *value; IN: Pointer to the value for the property
+ RETURNS
+ Returns non-negative on success, negative on failure.
+ DESCRIPTION
+ Gets the current value for a property in a property class. The property
+ name must exist or this routine will fail.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ The 'get' callback routine registered for this property will _NOT_ be
+ called, this routine is designed for internal library use only!
+
+ This routine may not be called for zero-sized properties and will
+ return an error in that case.
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5P__class_get(const H5P_genclass_t *pclass, const char *name, void *value)
+{
+ H5P_genprop_t *prop; /* Temporary property pointer */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Sanity check */
+ HDassert(pclass);
+ HDassert(name);
+ HDassert(value);
+
+ /* Find property in list */
+ if(NULL == (prop = (H5P_genprop_t *)H5SL_search(pclass->props, name)))
+ HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "property doesn't exist")
+
+ /* Check for property size >0 */
+ if(0 == prop->size)
+ HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "property has zero size")
+
+ /* Copy the property value */
+ HDmemcpy(value, prop->value, prop->size);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5P__class_get() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5P__class_set
+ PURPOSE
+ Internal routine to set a property's value in a property class.
+ USAGE
+ herr_t H5P__class_set(pclass, name, value)
+ const H5P_genclass_t *pclass; IN: Property class to find property in
+ const char *name; IN: Name of property to set
+ const void *value; IN: Pointer to the value for the property
+ RETURNS
+ Returns non-negative on success, negative on failure.
+ DESCRIPTION
+ Sets a new value for a property in a property class. The property name
+ must exist or this routine will fail.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ The 'set' callback routine registered for this property will _NOT_ be
+ called, this routine is designed for internal library use only!
+
+ This routine may not be called for zero-sized properties and will
+ return an error in that case.
+
+ The previous value is overwritten, not released in any way.
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5P__class_set(const H5P_genclass_t *pclass, const char *name, const void *value)
+{
+ H5P_genprop_t *prop; /* Temporary property pointer */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Sanity check */
+ HDassert(pclass);
+ HDassert(name);
+ HDassert(value);
+
+ /* Find property in list */
+ if(NULL == (prop = (H5P_genprop_t *)H5SL_search(pclass->props, name)))
+ HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "property doesn't exist")
+
+ /* Check for property size >0 */
+ if(0 == prop->size)
+ HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "property has zero size")
+
+ /* Copy the property value */
+ HDmemcpy(prop->value, value, prop->size);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5P__class_set() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
H5P_exist_plist
PURPOSE
Internal routine to query the existance of a property in a property list.
diff --git a/src/H5Ppkg.h b/src/H5Ppkg.h
index 13f3b13..c8e5e98 100644
--- a/src/H5Ppkg.h
+++ b/src/H5Ppkg.h
@@ -151,6 +151,10 @@ H5_DLL herr_t H5P__register(H5P_genclass_t **pclass, const char *name, size_t si
H5P_prp_close_func_t prp_close);
H5_DLL herr_t H5P__add_prop(H5SL_t *props, H5P_genprop_t *prop);
H5_DLL herr_t H5P__access_class(H5P_genclass_t *pclass, H5P_class_mod_t mod);
+H5_DLL herr_t H5P__class_get(const H5P_genclass_t *pclass, const char *name,
+ void *value);
+H5_DLL herr_t H5P__class_set(const H5P_genclass_t *pclass, const char *name,
+ const void *value);
H5_DLL htri_t H5P__exist_pclass(H5P_genclass_t *pclass, const char *name);
H5_DLL herr_t H5P__get_size_plist(const H5P_genplist_t *plist, const char *name,
size_t *size);
diff --git a/src/H5Pprivate.h b/src/H5Pprivate.h
index 866f088..49f7a12 100644
--- a/src/H5Pprivate.h
+++ b/src/H5Pprivate.h
@@ -148,6 +148,7 @@ H5_DLLVAR const struct H5P_libclass_t H5P_CLS_OCPY[1]; /* Object copy */
/* Forward declaration of structs used below */
struct H5O_fill_t;
struct H5T_t;
+struct H5VL_connector_prop_t;
/* Package initialization routine */
H5_DLL herr_t H5P_init(void);
@@ -178,6 +179,8 @@ H5_DLL const void *H5P_peek_driver_info(H5P_genplist_t *plist);
H5_DLL herr_t H5P_set_driver(H5P_genplist_t *plist, hid_t new_driver_id,
const void *new_driver_info);
H5_DLL herr_t H5P_set_vol(H5P_genplist_t *plist, hid_t vol_id, const void *vol_info);
+H5_DLL herr_t H5P_reset_vol_class(const H5P_genclass_t *pclass,
+ const struct H5VL_connector_prop_t *vol_prop);
H5_DLL herr_t H5P_set_vlen_mem_manager(H5P_genplist_t *plist,
H5MM_allocate_t alloc_func, void *alloc_info, H5MM_free_t free_func,
void *free_info);
diff --git a/src/H5VL.c b/src/H5VL.c
index 334de88..fd45bf8 100644
--- a/src/H5VL.c
+++ b/src/H5VL.c
@@ -29,11 +29,8 @@
/***********/
#include "H5private.h" /* Generic Functions */
-#include "H5Aprivate.h" /* Attributes */
#include "H5Eprivate.h" /* Error handling */
#include "H5Iprivate.h" /* IDs */
-#include "H5MMprivate.h" /* Memory management */
-#include "H5PLprivate.h" /* Plugins */
#include "H5VLpkg.h" /* Virtual Object Layer */
@@ -46,29 +43,10 @@
/* Local Typedefs */
/******************/
-/* Information needed for iterating over the registered VOL connector hid_t IDs.
- * The name or value of the new VOL connector that is being registered is
- * stored in the name (or value) field and the found_id field is initialized to
- * H5I_INVALID_HID (-1). If we find a VOL connector with the same name / value,
- * we set the found_id field to the existing ID for return to the function.
- */
-typedef struct {
- /* IN */
- H5VL_get_connector_kind_t kind; /* Which kind of connector search to make */
- union {
- const char *name; /* The name of the VOL connector to check */
- H5VL_class_value_t value; /* The value of the VOL connector to check */
- } u;
-
- /* OUT */
- hid_t found_id; /* The connector ID, if we found a match */
-} H5VL_get_connector_ud_t;
-
/********************/
/* Local Prototypes */
/********************/
-static int H5VL__get_connector_cb(void *obj, hid_t id, void *_op_data);
/*********************/
@@ -88,45 +66,6 @@ static int H5VL__get_connector_cb(void *obj, hid_t id, void *_op_data);
/*-------------------------------------------------------------------------
- * Function: H5VL__get_connector_cb
- *
- * Purpose: Callback routine to search through registered VOLs
- *
- * Return: Success: H5_ITER_STOP if the class and op_data name
- * members match. H5_ITER_CONT otherwise.
- *
- * Failure: Can't fail
- *
- *-------------------------------------------------------------------------
- */
-static int
-H5VL__get_connector_cb(void *obj, hid_t id, void *_op_data)
-{
- H5VL_get_connector_ud_t *op_data = (H5VL_get_connector_ud_t *)_op_data; /* User data for callback */
- H5VL_class_t *cls = (H5VL_class_t *)obj;
- int ret_value = H5_ITER_CONT; /* Callback return value */
-
- FUNC_ENTER_STATIC_NOERR
-
- if(H5VL_GET_CONNECTOR_BY_NAME == op_data->kind) {
- if(0 == HDstrcmp(cls->name, op_data->u.name)) {
- op_data->found_id = id;
- ret_value = H5_ITER_STOP;
- } /* end if */
- } /* end if */
- else {
- HDassert(H5VL_GET_CONNECTOR_BY_VALUE == op_data->kind);
- if(cls->value == op_data->u.value) {
- op_data->found_id = id;
- ret_value = H5_ITER_STOP;
- } /* end if */
- } /* end else */
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5VL__get_connector_cb() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5VLregister_connector
*
* Purpose: Registers a new VOL connector as a member of the virtual object
@@ -143,8 +82,7 @@ H5VL__get_connector_cb(void *obj, hid_t id, void *_op_data)
hid_t
H5VLregister_connector(const H5VL_class_t *cls, hid_t vipl_id)
{
- H5VL_get_connector_ud_t op_data; /* Callback info for connector search */
- hid_t ret_value = H5I_INVALID_HID;
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
FUNC_ENTER_API(H5I_INVALID_HID)
H5TRACE2("i", "*xi", cls, vipl_id);
@@ -161,25 +99,9 @@ H5VLregister_connector(const H5VL_class_t *cls, hid_t vipl_id)
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")
- op_data.kind = H5VL_GET_CONNECTOR_BY_NAME;
- op_data.u.name = cls->name;
- op_data.found_id = H5I_INVALID_HID;
-
- /* check if connector is already registered */
- if (H5I_iterate(H5I_VOL, H5VL__get_connector_cb, &op_data, TRUE) < 0)
- HGOTO_ERROR(H5E_VOL, H5E_BADITER, H5I_INVALID_HID, "can't iterate over VOL IDs")
-
- /* Increment the ref count on the existing VOL connector ID, if it's already registered */
- if(op_data.found_id != H5I_INVALID_HID) {
- if (H5I_inc_ref(op_data.found_id, TRUE) < 0)
- HGOTO_ERROR(H5E_VOL, H5E_CANTINC, H5I_INVALID_HID, "unable to increment ref count on VOL connector")
- ret_value = op_data.found_id;
- } /* end if */
- else {
- /* Create a new class ID */
- if ((ret_value = H5VL_register_connector(cls, TRUE, vipl_id)) < 0)
- HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VOL connector")
- } /* end else */
+ /* Register connector */
+ if((ret_value = H5VL__register_connector(cls, TRUE, vipl_id)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VOL connector")
done:
FUNC_LEAVE_API(ret_value)
@@ -203,8 +125,7 @@ done:
hid_t
H5VLregister_connector_by_name(const char *name, hid_t vipl_id)
{
- H5VL_get_connector_ud_t op_data; /* Callback info for connector search */
- hid_t ret_value = H5I_INVALID_HID;
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
FUNC_ENTER_API(H5I_INVALID_HID)
H5TRACE2("i", "*si", name, vipl_id);
@@ -215,34 +136,9 @@ H5VLregister_connector_by_name(const char *name, hid_t vipl_id)
if (0 == HDstrlen(name))
HGOTO_ERROR(H5E_ARGS, H5E_UNINITIALIZED, H5I_INVALID_HID, "zero-length VOL connector name is disallowed")
- op_data.kind = H5VL_GET_CONNECTOR_BY_NAME;
- op_data.u.name = name;
- op_data.found_id = H5I_INVALID_HID;
-
- /* Check if connector is already registered */
- if(H5I_iterate(H5I_VOL, H5VL__get_connector_cb, &op_data, TRUE) < 0)
- HGOTO_ERROR(H5E_VOL, H5E_BADITER, H5I_INVALID_HID, "can't iterate over VOL ids")
-
- /* If connector alread registered, increment ref count on ID and return ID */
- if(op_data.found_id != H5I_INVALID_HID) {
- if(H5I_inc_ref(op_data.found_id, TRUE) < 0)
- HGOTO_ERROR(H5E_VOL, H5E_CANTINC, H5I_INVALID_HID, "unable to increment ref count on VOL connector")
- ret_value = op_data.found_id;
- } /* end if */
- else {
- H5PL_key_t key;
- const H5VL_class_t *cls;
-
- /* Try loading the connector */
- key.vol.kind = H5VL_GET_CONNECTOR_BY_NAME;
- key.vol.u.name = name;
- if(NULL == (cls = (const H5VL_class_t *)H5PL_load(H5PL_TYPE_VOL, &key)))
- 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, TRUE, vipl_id)) < 0)
- HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VOL connector ID")
- } /* end else */
+ /* Register connector */
+ if((ret_value = H5VL__register_connector_by_name(name, TRUE, vipl_id)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VOL connector")
done:
FUNC_LEAVE_API(ret_value)
@@ -266,8 +162,7 @@ done:
hid_t
H5VLregister_connector_by_value(H5VL_class_value_t value, hid_t vipl_id)
{
- H5VL_get_connector_ud_t op_data; /* Callback info for connector search */
- hid_t ret_value = H5I_INVALID_HID;
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
FUNC_ENTER_API(H5I_INVALID_HID)
H5TRACE2("i", "VCi", value, vipl_id);
@@ -276,34 +171,9 @@ H5VLregister_connector_by_value(H5VL_class_value_t value, hid_t vipl_id)
if(value < 0)
HGOTO_ERROR(H5E_ARGS, H5E_UNINITIALIZED, H5I_INVALID_HID, "negative VOL connector value is disallowed")
- op_data.kind = H5VL_GET_CONNECTOR_BY_VALUE;
- op_data.u.value = value;
- op_data.found_id = H5I_INVALID_HID;
-
- /* Check if connector is already registered */
- if(H5I_iterate(H5I_VOL, H5VL__get_connector_cb, &op_data, TRUE) < 0)
- HGOTO_ERROR(H5E_VOL, H5E_BADITER, H5I_INVALID_HID, "can't iterate over VOL ids")
-
- /* If connector alread registered, increment ref count on ID and return ID */
- if(op_data.found_id != H5I_INVALID_HID) {
- if(H5I_inc_ref(op_data.found_id, TRUE) < 0)
- HGOTO_ERROR(H5E_VOL, H5E_CANTINC, H5I_INVALID_HID, "unable to increment ref count on VOL connector")
- ret_value = op_data.found_id;
- } /* end if */
- else {
- H5PL_key_t key;
- const H5VL_class_t *cls;
-
- /* Try loading the connector */
- key.vol.kind = H5VL_GET_CONNECTOR_BY_VALUE;
- key.vol.u.value = value;
- if(NULL == (cls = (const H5VL_class_t *)H5PL_load(H5PL_TYPE_VOL, &key)))
- 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, TRUE, vipl_id)) < 0)
- HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VOL connector ID")
- } /* end else */
+ /* Register connector */
+ if((ret_value = H5VL__register_connector_by_value(value, TRUE, vipl_id)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VOL connector")
done:
FUNC_LEAVE_API(ret_value)
@@ -315,33 +185,26 @@ done:
*
* Purpose: Tests whether a VOL class has been registered or not
*
- * Return: Positive if the VOL class has been registered
- *
- * Zero if it is unregistered
+ * Return: >0 if the VOL class has been registered
+ * 0 if it is unregistered
+ * <0 on error (if the class is not a valid class ID)
*
- * Negative on error (if the class is not a valid class ID)
+ * Programmer: Dana Robinson
+ * June 17, 2017
*
*-------------------------------------------------------------------------
*/
htri_t
H5VLis_connector_registered(const char *name)
{
- H5VL_get_connector_ud_t op_data; /* Callback info for connector search */
htri_t ret_value = FALSE; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE1("t", "*s", name);
- op_data.kind = H5VL_GET_CONNECTOR_BY_NAME;
- op_data.u.name = name;
- op_data.found_id = H5I_INVALID_HID;
-
- /* Check arguments */
- if (H5I_iterate(H5I_VOL, H5VL__get_connector_cb, &op_data, TRUE) < 0)
- HGOTO_ERROR(H5E_VOL, H5E_BADITER, FAIL, "can't iterate over VOL ids")
-
- if (op_data.found_id != H5I_INVALID_HID)
- ret_value = TRUE;
+ /* Check if connector with this name is registered */
+ if((ret_value = H5VL__is_connector_registered(name)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't check for VOL")
done:
FUNC_LEAVE_API(ret_value)
@@ -356,30 +219,22 @@ done:
* Return: Positive if the VOL class has been registered
* Negative on error (if the class is not a valid class or not registered)
*
+ * Programmer: Dana Robinson
+ * June 17, 2017
+ *
*-------------------------------------------------------------------------
*/
hid_t
H5VLget_connector_id(const char *name)
{
- H5VL_get_connector_ud_t op_data; /* Callback info for connector search */
hid_t ret_value = H5I_INVALID_HID; /* Return value */
FUNC_ENTER_API(H5I_INVALID_HID)
H5TRACE1("i", "*s", name);
- op_data.kind = H5VL_GET_CONNECTOR_BY_NAME;
- op_data.u.name = name;
- op_data.found_id = H5I_INVALID_HID;
-
- /* Check arguments */
- if (H5I_iterate(H5I_VOL, H5VL__get_connector_cb, &op_data, TRUE) < 0)
- HGOTO_ERROR(H5E_VOL, H5E_BADITER, H5I_INVALID_HID, "can't iterate over VOL connector IDs")
-
- if (op_data.found_id != H5I_INVALID_HID) {
- if (H5I_inc_ref(op_data.found_id, TRUE) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTINC, H5I_INVALID_HID, "unable to increment ref count on VOL connector")
- ret_value = op_data.found_id;
- } /* end if */
+ /* Get connector ID with this name */
+ if((ret_value = H5VL__get_connector_id(name, TRUE)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, H5I_INVALID_HID, "can't get VOL id")
done:
FUNC_LEAVE_API(ret_value)
@@ -406,7 +261,8 @@ H5VLget_connector_name(hid_t obj_id, char *name/*out*/, size_t size)
FUNC_ENTER_API(FAIL)
H5TRACE3("Zs", "ixz", obj_id, name, size);
- if ((ret_value = H5VL_get_connector_name(obj_id, name, size)) < 0)
+ /* Call internal routine */
+ if((ret_value = H5VL__get_connector_name(obj_id, name, size)) < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "Can't get connector name")
done:
diff --git a/src/H5VLcallback.c b/src/H5VLcallback.c
index 5a5d9ee..d77c9f6 100644
--- a/src/H5VLcallback.c
+++ b/src/H5VLcallback.c
@@ -506,20 +506,25 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5VL_free_connector_info(const H5VL_class_t *connector, void *info)
+H5VL_free_connector_info(hid_t connector_id, void *info)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5VL_class_t *cls; /* VOL connector's class struct */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
- /* Sanity checks */
- HDassert(connector);
+ /* Sanity check */
+ HDassert(connector_id > 0);
+
+ /* Check args and get class pointer */
+ if(NULL == (cls = (H5VL_class_t *)H5I_object_verify(connector_id, H5I_VOL)))
+ HGOTO_ERROR(H5E_VOL, H5E_BADTYPE, FAIL, "not a VOL connector ID")
/* Only free info object, if it's non-NULL */
if(info) {
/* Allow the connector to free info or do it ourselves */
- if(connector->info_cls.free) {
- if((connector->info_cls.free)(info) < 0)
+ if(cls->info_cls.free) {
+ if((cls->info_cls.free)(info) < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "connector info free request failed")
} /* end if */
else
@@ -544,18 +549,13 @@ done:
herr_t
H5VLfree_connector_info(hid_t connector_id, void *info)
{
- H5VL_class_t *cls; /* VOL connector's class struct */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API_NOINIT
H5TRACE2("e", "i*x", connector_id, info);
- /* Check args and get class pointer */
- if(NULL == (cls = (H5VL_class_t *)H5I_object_verify(connector_id, H5I_VOL)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a VOL connector ID")
-
/* Free the VOL connector info object */
- if(H5VL_free_connector_info(cls, info) < 0)
+ if(H5VL_free_connector_info(connector_id, info) < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "unable to release VOL connector info object")
done:
@@ -623,24 +623,9 @@ H5VLconnector_str_to_info(const char *str, hid_t connector_id, void **info)
FUNC_ENTER_API_NOINIT
H5TRACE3("e", "*si**x", str, connector_id, info);
- /* Only deserialize string, if it's non-NULL */
- if(str) {
- H5VL_class_t *cls; /* VOL connector's class struct */
-
- /* Check args and get class pointer */
- if(NULL == (cls = (H5VL_class_t *)H5I_object_verify(connector_id, H5I_VOL)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a VOL connector ID")
-
- /* Allow the connector to deserialize info */
- if(cls->info_cls.from_str) {
- if((cls->info_cls.from_str)(str, info) < 0)
- HGOTO_ERROR(H5E_VOL, H5E_CANTUNSERIALIZE, FAIL, "can't deserialize connector info")
- } /* end if */
- else
- *info = NULL;
- } /* end if */
- else
- *info = NULL;
+ /* Call internal routine */
+ if(H5VL__connector_str_to_info(str, connector_id, info) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTDECODE, FAIL, "can't deserialize connector info")
done:
FUNC_LEAVE_API_NOINIT(ret_value)
diff --git a/src/H5VLint.c b/src/H5VLint.c
index 7aeea02..339c60b 100644
--- a/src/H5VLint.c
+++ b/src/H5VLint.c
@@ -29,14 +29,19 @@
/* Headers */
/***********/
-#include "H5private.h" /* Generic Functions */
-#include "H5CXprivate.h" /* API Contexts */
-#include "H5Eprivate.h" /* Error handling */
-#include "H5FLprivate.h" /* Free lists */
-#include "H5Iprivate.h" /* IDs */
-#include "H5MMprivate.h" /* Memory management */
-#include "H5Tprivate.h" /* Datatypes */
-#include "H5VLpkg.h" /* Virtual Object Layer */
+#include "H5private.h" /* Generic Functions */
+#include "H5CXprivate.h" /* API Contexts */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5FLprivate.h" /* Free lists */
+#include "H5Iprivate.h" /* IDs */
+#include "H5MMprivate.h" /* Memory management */
+#include "H5PLprivate.h" /* Plugins */
+#include "H5Tprivate.h" /* Datatypes */
+#include "H5VLpkg.h" /* Virtual Object Layer */
+
+/* VOL connectors */
+#include "H5VLnative.h" /* Native VOL connector */
+#include "H5VLpassthru.h" /* Pass-through VOL connector */
/****************/
@@ -55,6 +60,24 @@ typedef struct H5VL_wrap_ctx_t {
void *obj_wrap_ctx; /* "wrap context" for outermost connector */
} H5VL_wrap_ctx_t;
+/* Information needed for iterating over the registered VOL connector hid_t IDs.
+ * The name or value of the new VOL connector that is being registered is
+ * stored in the name (or value) field and the found_id field is initialized to
+ * H5I_INVALID_HID (-1). If we find a VOL connector with the same name / value,
+ * we set the found_id field to the existing ID for return to the function.
+ */
+typedef struct {
+ /* IN */
+ H5VL_get_connector_kind_t kind; /* Which kind of connector search to make */
+ union {
+ const char *name; /* The name of the VOL connector to check */
+ H5VL_class_value_t value; /* The value of the VOL connector to check */
+ } u;
+
+ /* OUT */
+ hid_t found_id; /* The connector ID, if we found a match */
+} H5VL_get_connector_ud_t;
+
/********************/
/* Package Typedefs */
@@ -65,6 +88,8 @@ typedef struct H5VL_wrap_ctx_t {
/* Local Prototypes */
/********************/
static herr_t H5VL__free_cls(H5VL_class_t *cls);
+static int H5VL__get_connector_cb(void *obj, hid_t id, void *_op_data);
+static herr_t H5VL__set_def_conn(void);
static void *H5VL__wrap_obj(void *obj, H5I_type_t obj_type);
static H5VL_object_t *H5VL__new_vol_obj(H5I_type_t type, void *object,
H5VL_t *vol_connector, hbool_t wrap_obj);
@@ -86,6 +111,7 @@ hbool_t H5_PKG_INIT_VAR = FALSE;
/* Library Private Variables */
/*****************************/
+
/*******************/
/* Local Variables */
/*******************/
@@ -110,21 +136,27 @@ H5FL_DEFINE(H5VL_object_t);
/* Declare a free list to manage the H5VL_wrap_ctx_t struct */
H5FL_DEFINE_STATIC(H5VL_wrap_ctx_t);
+/* Default VOL connector */
+static H5VL_connector_prop_t H5VL_def_conn_s = {-1, NULL};
+
/*-------------------------------------------------------------------------
- * Function: H5VL_init
+ * Function: H5VL_init_phase1
*
- * Purpose: Initialize the interface from some other package
+ * Purpose: Initialize the interface from some other package. This should
+ * be followed with a call to H5VL_init_phase2 after the H5P
+ * interface is completely set up, finish setting up the H5VL
+ * information.
*
- * Return: Success: Non-negative
*
+ * Return: Success: Non-negative
* Failure: Negative
*
*-------------------------------------------------------------------------
*/
herr_t
-H5VL_init(void)
+H5VL_init_phase1(void)
{
herr_t ret_value = SUCCEED; /* Return value */
@@ -134,7 +166,36 @@ H5VL_init(void)
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5VL_init() */
+} /* end H5VL_init_phase1() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL_init_phase2
+ *
+ * Purpose: Finish initializing the interface from some other package.
+ *
+ * Note: This is broken out as a separate routine to avoid a circular
+ * reference with the H5P package.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL_init_phase2(void)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Set up the default VOL connector in the default FAPL */
+ if(H5VL__set_def_conn() < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "unable to set default VOL connector")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL_init_phase2() */
/*-------------------------------------------------------------------------
@@ -151,12 +212,12 @@ done:
herr_t
H5VL__init_package(void)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
/* Initialize the atom group for the VL IDs */
- if (H5I_register_type(H5I_VOL_CLS) < 0)
+ if(H5I_register_type(H5I_VOL_CLS) < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "unable to initialize H5VL interface")
done:
@@ -183,17 +244,27 @@ H5VL_term_package(void)
FUNC_ENTER_NOAPI_NOINIT_NOERR
if(H5_PKG_INIT_VAR) {
- if (H5I_nmembers(H5I_VOL) > 0) {
- (void)H5I_clear_type(H5I_VOL, FALSE, FALSE);
+ if(H5VL_def_conn_s.connector_id > 0) {
+ /* Release the default VOL connector */
+ (void)H5VL_conn_free(&H5VL_def_conn_s);
+ H5VL_def_conn_s.connector_id = -1;
+ H5VL_def_conn_s.connector_info = NULL;
n++;
} /* end if */
else {
- /* Destroy the VOL connector ID group */
- n += (H5I_dec_type_ref(H5I_VOL) > 0);
-
- /* Mark interface as closed */
- if (0 == n)
- H5_PKG_INIT_VAR = FALSE;
+ if(H5I_nmembers(H5I_VOL) > 0) {
+ /* Unregister all VOL connectors */
+ (void)H5I_clear_type(H5I_VOL, FALSE, FALSE);
+ n++;
+ } /* end if */
+ else {
+ /* Destroy the VOL connector ID group */
+ n += (H5I_dec_type_ref(H5I_VOL) > 0);
+
+ /* Mark interface as closed */
+ if(0 == n)
+ H5_PKG_INIT_VAR = FALSE;
+ } /* end else */
} /* end else */
} /* end if */
@@ -237,6 +308,182 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5VL__get_connector_cb
+ *
+ * Purpose: Callback routine to search through registered VOLs
+ *
+ * Return: Success: H5_ITER_STOP if the class and op_data name
+ * members match. H5_ITER_CONT otherwise.
+ * Failure: Can't fail
+ *
+ * Programmer: Dana Robinson
+ * June 22, 2017
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+H5VL__get_connector_cb(void *obj, hid_t id, void *_op_data)
+{
+ H5VL_get_connector_ud_t *op_data = (H5VL_get_connector_ud_t *)_op_data; /* User data for callback */
+ H5VL_class_t *cls = (H5VL_class_t *)obj;
+ int ret_value = H5_ITER_CONT; /* Callback return value */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ if(H5VL_GET_CONNECTOR_BY_NAME == op_data->kind) {
+ if(0 == HDstrcmp(cls->name, op_data->u.name)) {
+ op_data->found_id = id;
+ ret_value = H5_ITER_STOP;
+ } /* end if */
+ } /* end if */
+ else {
+ HDassert(H5VL_GET_CONNECTOR_BY_VALUE == op_data->kind);
+ if(cls->value == op_data->u.value) {
+ op_data->found_id = id;
+ ret_value = H5_ITER_STOP;
+ } /* end if */
+ } /* end else */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__get_connector_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__set_def_conn
+ *
+ * Purpose: Parses a string that contains the default VOL connector for
+ * the library.
+ *
+ * Note: Usually from the environment variable "HDF5_VOL_CONNECTOR",
+ * but could be from elsewhere.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ * Programmer: Jordan Henderson
+ * November 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5VL__set_def_conn(void)
+{
+ H5P_genplist_t *def_fapl; /* Default file access property list */
+ H5P_genclass_t *def_fapclass; /* Default file access property class */
+ const char *env_var; /* Environment variable for default VOL connector */
+ char *buf = NULL; /* Buffer for tokenizing string */
+ hid_t connector_id = -1; /* VOL conntector ID */
+ void *vol_info = NULL; /* VOL connector info */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity check */
+ HDassert(H5VL_def_conn_s.connector_id == (-1));
+ HDassert(H5VL_def_conn_s.connector_info == NULL);
+
+ /* Check for environment variable set */
+ env_var = HDgetenv("HDF5_VOL_CONNECTOR");
+
+ /* Only parse the string if it's set */
+ if(env_var && *env_var) {
+ char *lasts = NULL; /* Context pointer for strtok_r() call */
+ const char *tok = NULL; /* Token from strtok_r call */
+ htri_t connector_is_registered; /* Whether connector is already registered */
+
+ /* Duplicate the string to parse, as it is modified as we go */
+ if(NULL == (buf = H5MM_strdup(env_var)))
+ HGOTO_ERROR(H5E_VOL, H5E_CANTALLOC, FAIL, "can't allocate memory for environment variable string")
+
+ /* Get the first 'word' of the environment variable.
+ * If it's nothing (environment variable was whitespace) return error.
+ */
+ if(NULL == (tok = HDstrtok_r(buf, " \t\n\r", &lasts)))
+ HGOTO_ERROR(H5E_VOL, H5E_BADVALUE, FAIL, "VOL connector environment variable set empty?")
+
+ /* First, check to see if the connector is already registered */
+ if((connector_is_registered = H5VL__is_connector_registered(tok)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't check if VOL connector already registered")
+ else if(connector_is_registered) {
+ /* Retrieve the ID of the already-registered VOL connector */
+ if((connector_id = H5VL__get_connector_id(tok, FALSE)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't get VOL connector ID")
+ } /* end else-if */
+ else {
+ /* Check for VOL connectors that ship with the library */
+ if(!HDstrcmp(tok, "native")) {
+ connector_id = H5VL_NATIVE;
+ if(H5I_inc_ref(connector_id, FALSE) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTINC, FAIL, "can't increment VOL connector refcount")
+ } /* end if */
+ else if(!HDstrcmp(tok, "pass_through")) {
+ connector_id = H5VL_PASSTHRU;
+ if(H5I_inc_ref(connector_id, FALSE) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTINC, FAIL, "can't increment VOL connector refcount")
+ } /* end else-if */
+ else {
+ /* Register the VOL connector */
+ /* (NOTE: No provisions for vipl_id currently) */
+ if((connector_id = H5VL__register_connector_by_name(tok, FALSE, H5P_DEFAULT)) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, FAIL, "can't register connector")
+ } /* end else */
+ } /* end else */
+
+ /* Was there any connector info specified in the environment variable? */
+ if(NULL != (tok = HDstrtok_r(NULL, " \t\n\r", &lasts)))
+ if(H5VL__connector_str_to_info(tok, connector_id, &vol_info) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTDECODE, FAIL, "can't deserialize connector info")
+
+ /* Set the default VOL connector */
+ H5VL_def_conn_s.connector_id = connector_id;
+ H5VL_def_conn_s.connector_info = vol_info;
+ } /* end if */
+ else {
+ /* Set the default VOL connector */
+ H5VL_def_conn_s.connector_id = H5_DEFAULT_VOL;
+ H5VL_def_conn_s.connector_info = NULL;
+
+ /* Increment the ref count on the default connector */
+ if(H5I_inc_ref(H5VL_def_conn_s.connector_id, FALSE) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTINC, FAIL, "can't increment VOL connector refcount")
+ } /* end else */
+
+ /* Get default file access pclass */
+ if(NULL == (def_fapclass = (H5P_genclass_t *)H5I_object(H5P_FILE_ACCESS)))
+ HGOTO_ERROR(H5E_VOL, H5E_BADATOM, FAIL, "can't find object for default file access property class ID")
+
+ /* Change the default VOL for the default file access pclass */
+ if(H5P_reset_vol_class(def_fapclass, &H5VL_def_conn_s) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set default VOL connector for default file access property class")
+
+ /* Get default file access plist */
+ if(NULL == (def_fapl = (H5P_genplist_t *)H5I_object(H5P_FILE_ACCESS_DEFAULT)))
+ HGOTO_ERROR(H5E_VOL, H5E_BADATOM, FAIL, "can't find object for default fapl ID")
+
+ /* Change the default VOL for the default FAPL */
+ if(H5P_set_vol(def_fapl, H5VL_def_conn_s.connector_id, H5VL_def_conn_s.connector_info) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set default VOL connector for default FAPL")
+
+done:
+ /* Clean up on error */
+ if(ret_value < 0) {
+ if(vol_info)
+ if(H5VL_free_connector_info(connector_id, vol_info) < 0)
+ HDONE_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "can't free VOL connector info")
+ if(connector_id >= 0)
+ /* The H5VL_class_t struct will be freed by this function */
+ if(H5I_dec_ref(connector_id) < 0)
+ HDONE_ERROR(H5E_VOL, H5E_CANTDEC, FAIL, "unable to unregister VOL connector")
+ } /* end if */
+
+ /* Clean up */
+ H5MM_xfree(buf);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__set_def_conn() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5VL__wrap_obj
*
* Purpose: Wraps a library object with possible VOL connector wrappers, to
@@ -396,29 +643,22 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5VL_conn_free(const H5VL_connector_prop_t *info)
+H5VL_conn_free(const H5VL_connector_prop_t *connector_prop)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
- if(info) {
+ if(connector_prop) {
/* Free the connector info (if it exists) and decrement the ID */
- if(info->connector_id > 0) {
- if(info->connector_info) {
- H5VL_class_t *connector; /* Pointer to connector */
-
- /* Retrieve the connector for the ID */
- if(NULL == (connector = (H5VL_class_t *)H5I_object(info->connector_id)))
- HGOTO_ERROR(H5E_VOL, H5E_BADTYPE, FAIL, "not a VOL connector ID")
-
+ if(connector_prop->connector_id > 0) {
+ if(connector_prop->connector_info)
/* Free the connector info */
- if(H5VL_free_connector_info(connector, (void *)info->connector_info) < 0) /* Casting away const OK - QAK */
+ if(H5VL_free_connector_info(connector_prop->connector_id, (void *)connector_prop->connector_info) < 0) /* Casting away const OK - QAK */
HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "unable to release VOL connector info object")
- } /* end if */
/* Decrement reference count for connector ID */
- if(H5I_dec_ref(info->connector_id) < 0)
+ if(H5I_dec_ref(connector_prop->connector_id) < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTDEC, FAIL, "can't decrement reference count for connector ID")
} /* end if */
} /* end if */
@@ -664,6 +904,9 @@ done:
*
* Failure: H5I_INVALID_HID
*
+ * Programmer: Dana Robinson
+ * June 22, 2017
+ *
*-------------------------------------------------------------------------
*/
hid_t
@@ -679,7 +922,7 @@ H5VL_register_connector(const void *_cls, hbool_t app_ref, hid_t vipl_id)
HDassert(cls);
/* Copy the class structure so the caller can reuse or free it */
- if (NULL == (saved = H5FL_CALLOC(H5VL_class_t)))
+ if(NULL == (saved = H5FL_MALLOC(H5VL_class_t)))
HGOTO_ERROR(H5E_VOL, H5E_CANTALLOC, H5I_INVALID_HID, "memory allocation failed for VOL connector class struct")
HDmemcpy(saved, cls, sizeof(H5VL_class_t));
if(NULL == (saved->name = H5MM_strdup(cls->name)))
@@ -690,23 +933,319 @@ H5VL_register_connector(const void *_cls, hbool_t app_ref, hid_t vipl_id)
HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, H5I_INVALID_HID, "unable to init VOL connector")
/* Create the new class ID */
- if ((ret_value = H5I_register(H5I_VOL, saved, app_ref)) < 0)
+ if((ret_value = H5I_register(H5I_VOL, saved, app_ref)) < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VOL connector ID")
done:
- if (ret_value < 0 && saved) {
- if (saved->name)
+ if(ret_value < 0 && saved) {
+ if(saved->name)
H5MM_xfree((void *)(saved->name)); /* Casting away const OK -QAK */
H5FL_FREE(H5VL_class_t, saved);
- }
+ } /* end if */
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5VL_register_connector() */
/*-------------------------------------------------------------------------
- * Function: H5VL_get_connector_name
+ * Function: H5VL__register_connector
+ *
+ * Purpose: Registers a new VOL connector as a member of the virtual object
+ * layer class.
+ *
+ * Return: Success: A VOL connector ID which is good until the
+ * library is closed or the connector is
+ * unregistered.
+ *
+ * Failure: H5I_INVALID_HID
+ *
+ * Programmer: Dana Robinson
+ * June 22, 2017
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5VL__register_connector(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 */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Set up op data for iteration */
+ op_data.kind = H5VL_GET_CONNECTOR_BY_NAME;
+ op_data.u.name = cls->name;
+ op_data.found_id = H5I_INVALID_HID;
+
+ /* Check if connector is already registered */
+ if(H5I_iterate(H5I_VOL, H5VL__get_connector_cb, &op_data, TRUE) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_BADITER, H5I_INVALID_HID, "can't iterate over VOL IDs")
+
+ /* Increment the ref count on the existing VOL connector ID, if it's already registered */
+ if(op_data.found_id != H5I_INVALID_HID) {
+ if(H5I_inc_ref(op_data.found_id, app_ref) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTINC, H5I_INVALID_HID, "unable to increment ref count on VOL connector")
+ ret_value = op_data.found_id;
+ } /* end if */
+ else {
+ /* Create a new class ID */
+ 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() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__register_connector_by_name
+ *
+ * Purpose: Registers a new VOL connector as a member of the virtual object
+ * layer class.
+ *
+ * Return: Success: A VOL connector ID which is good until the
+ * library is closed or the connector is
+ * unregistered.
+ *
+ * Failure: H5I_INVALID_HID
+ *
+ * Programmer: Dana Robinson
+ * June 22, 2017
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5VL__register_connector_by_name(const char *name, 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 */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Set up op data for iteration */
+ op_data.kind = H5VL_GET_CONNECTOR_BY_NAME;
+ op_data.u.name = name;
+ op_data.found_id = H5I_INVALID_HID;
+
+ /* Check if connector is already registered */
+ if(H5I_iterate(H5I_VOL, H5VL__get_connector_cb, &op_data, TRUE) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_BADITER, H5I_INVALID_HID, "can't iterate over VOL ids")
+
+ /* If connector alread registered, increment ref count on ID and return ID */
+ if(op_data.found_id != H5I_INVALID_HID) {
+ if(H5I_inc_ref(op_data.found_id, app_ref) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTINC, H5I_INVALID_HID, "unable to increment ref count on VOL connector")
+ ret_value = op_data.found_id;
+ } /* end if */
+ else {
+ H5PL_key_t key;
+ const H5VL_class_t *cls;
+
+ /* Try loading the connector */
+ key.vol.kind = H5VL_GET_CONNECTOR_BY_NAME;
+ key.vol.u.name = name;
+ if(NULL == (cls = (const H5VL_class_t *)H5PL_load(H5PL_TYPE_VOL, &key)))
+ 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)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VOL connector ID")
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__register_connector_by_name() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__register_connector_by_value
+ *
+ * Purpose: Registers a new VOL connector as a member of the virtual object
+ * layer class.
+ *
+ * Return: Success: A VOL connector ID which is good until the
+ * library is closed or the connector is
+ * unregistered.
+ *
+ * Failure: H5I_INVALID_HID
+ *
+ * Programmer: Dana Robinson
+ * June 22, 2017
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5VL__register_connector_by_value(H5VL_class_value_t value, 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 */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Set up op data for iteration */
+ op_data.kind = H5VL_GET_CONNECTOR_BY_VALUE;
+ op_data.u.value = value;
+ op_data.found_id = H5I_INVALID_HID;
+
+ /* Check if connector is already registered */
+ if(H5I_iterate(H5I_VOL, H5VL__get_connector_cb, &op_data, TRUE) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_BADITER, H5I_INVALID_HID, "can't iterate over VOL ids")
+
+ /* If connector alread registered, increment ref count on ID and return ID */
+ if(op_data.found_id != H5I_INVALID_HID) {
+ if(H5I_inc_ref(op_data.found_id, app_ref) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTINC, H5I_INVALID_HID, "unable to increment ref count on VOL connector")
+ ret_value = op_data.found_id;
+ } /* end if */
+ else {
+ H5PL_key_t key;
+ const H5VL_class_t *cls;
+
+ /* Try loading the connector */
+ key.vol.kind = H5VL_GET_CONNECTOR_BY_VALUE;
+ key.vol.u.value = value;
+ if(NULL == (cls = (const H5VL_class_t *)H5PL_load(H5PL_TYPE_VOL, &key)))
+ 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)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VOL connector ID")
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__register_connector_by_value() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__is_connector_registered
+ *
+ * Purpose: Checks if a connector with a particular name is registered.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ * Programmer: Dana Robinson
+ * June 17, 2017
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5VL__is_connector_registered(const char *name)
+{
+ H5VL_get_connector_ud_t op_data; /* Callback info for connector search */
+ htri_t ret_value = FALSE; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Set up op data for iteration */
+ op_data.kind = H5VL_GET_CONNECTOR_BY_NAME;
+ op_data.u.name = name;
+ op_data.found_id = H5I_INVALID_HID;
+
+ /* Find connector with name */
+ if(H5I_iterate(H5I_VOL, H5VL__get_connector_cb, &op_data, TRUE) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_BADITER, FAIL, "can't iterate over VOL connectors")
+
+ /* Found a connector with that name */
+ if(op_data.found_id != H5I_INVALID_HID)
+ ret_value = TRUE;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__is_connector_registered() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__get_connector_id
+ *
+ * Purpose: Retrieves the ID for a registered VOL connector.
+ *
+ * Return: Positive if the VOL class has been registered
+ * Negative on error (if the class is not a valid class or not registered)
+ *
+ * Programmer: Dana Robinson
+ * June 17, 2017
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5VL__get_connector_id(const char *name, hbool_t is_api)
+{
+ H5VL_get_connector_ud_t op_data; /* Callback info for connector search */
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Set up op data for iteration */
+ op_data.kind = H5VL_GET_CONNECTOR_BY_NAME;
+ op_data.u.name = name;
+ op_data.found_id = H5I_INVALID_HID;
+
+ /* Find connector with name */
+ if(H5I_iterate(H5I_VOL, H5VL__get_connector_cb, &op_data, TRUE) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_BADITER, H5I_INVALID_HID, "can't iterate over VOL connectors")
+
+ /* Found a connector with that name */
+ if(op_data.found_id != H5I_INVALID_HID) {
+ if(H5I_inc_ref(op_data.found_id, is_api) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINC, H5I_INVALID_HID, "unable to increment ref count on VOL connector")
+ ret_value = op_data.found_id;
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__get_connector_id() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__connector_str_to_info
+ *
+ * Purpose: Deserializes a string into a connector's info object
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * March 2, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5VL__connector_str_to_info(const char *str, hid_t connector_id, void **info)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Only deserialize string, if it's non-NULL */
+ if(str) {
+ H5VL_class_t *cls; /* VOL connector's class struct */
+
+ /* Check args and get class pointer */
+ if(NULL == (cls = (H5VL_class_t *)H5I_object_verify(connector_id, H5I_VOL)))
+ HGOTO_ERROR(H5E_VOL, H5E_BADTYPE, FAIL, "not a VOL connector ID")
+
+ /* Allow the connector to deserialize info */
+ if(cls->info_cls.from_str) {
+ if((cls->info_cls.from_str)(str, info) < 0)
+ HGOTO_ERROR(H5E_VOL, H5E_CANTUNSERIALIZE, FAIL, "can't deserialize connector info")
+ } /* end if */
+ else
+ *info = NULL;
+ } /* end if */
+ else
+ *info = NULL;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5VL__connector_str_to_info() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5VL__get_connector_name
*
* Purpose: Private version of H5VLget_connector_name
*
@@ -716,14 +1255,14 @@ done:
*-------------------------------------------------------------------------
*/
ssize_t
-H5VL_get_connector_name(hid_t id, char *name /*out*/, size_t size)
+H5VL__get_connector_name(hid_t id, char *name /*out*/, size_t size)
{
H5VL_object_t *vol_obj;
const H5VL_class_t *cls;
size_t len;
ssize_t ret_value = -1;
- FUNC_ENTER_NOAPI(FAIL)
+ FUNC_ENTER_PACKAGE
/* get the object pointer */
if (NULL == (vol_obj = H5VL_vol_object(id)))
@@ -743,7 +1282,7 @@ H5VL_get_connector_name(hid_t id, char *name /*out*/, size_t size)
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5VL_get_connector_name() */
+} /* end H5VL__get_connector_name() */
/*-------------------------------------------------------------------------
diff --git a/src/H5VLpassthru.c b/src/H5VLpassthru.c
index fe72000..a4c85cc 100644
--- a/src/H5VLpassthru.c
+++ b/src/H5VLpassthru.c
@@ -20,6 +20,11 @@
* include _any_ private HDF5 header files. This connector should
* therefore only make public HDF5 API calls and use standard C /
* POSIX calls.
+ *
+ * Note that the HDF5 error stack must be preserved on code paths
+ * that could be invoked when the underlying VOL connector's
+ * callback can fail.
+ *
*/
@@ -297,6 +302,9 @@ H5VL_pass_through_new_obj(void *under_obj, hid_t under_vol_id)
*
* Purpose: Release a pass through object
*
+ * Note: Take care to preserve the current HDF5 error stack
+ * when calling HDF5 API calls.
+ *
* Return: Success: 0
* Failure: -1
*
@@ -308,7 +316,14 @@ H5VL_pass_through_new_obj(void *under_obj, hid_t under_vol_id)
static herr_t
H5VL_pass_through_free_obj(H5VL_pass_through_t *obj)
{
+ hid_t err_id;
+
+ err_id = H5Eget_current_stack();
+
H5Idec_ref(obj->under_vol_id);
+
+ H5Eset_current_stack(err_id);
+
free(obj);
return 0;
@@ -332,11 +347,8 @@ H5VL_pass_through_free_obj(H5VL_pass_through_t *obj)
hid_t
H5VL_pass_through_register(void)
{
- /* Clear the error stack */
- H5Eclear2(H5E_DEFAULT);
-
/* Singleton register the pass-through VOL connector ID */
- if(H5I_VOL != H5Iget_type(H5VL_PASSTHRU_g))
+ if(H5VL_PASSTHRU_g < 0)
H5VL_PASSTHRU_g = H5VLregister_connector(&H5VL_pass_through_g, H5P_DEFAULT);
return H5VL_PASSTHRU_g;
@@ -476,6 +488,9 @@ H5VL_pass_through_info_cmp(int *cmp_value, const void *_info1, const void *_info
*
* Purpose: Release an info object for the connector.
*
+ * Note: Take care to preserve the current HDF5 error stack
+ * when calling HDF5 API calls.
+ *
* Return: Success: 0
* Failure: -1
*
@@ -485,16 +500,21 @@ static herr_t
H5VL_pass_through_info_free(void *_info)
{
H5VL_pass_through_info_t *info = (H5VL_pass_through_info_t *)_info;
+ hid_t err_id;
#ifdef ENABLE_PASSTHRU_LOGGING
printf("------- PASS THROUGH VOL INFO Free\n");
#endif
+ err_id = H5Eget_current_stack();
+
/* Release underlying VOL ID and info */
if(info->under_vol_info)
H5VLfree_connector_info(info->under_vol_id, info->under_vol_info);
H5Idec_ref(info->under_vol_id);
+ H5Eset_current_stack(err_id);
+
/* Free pass through info object itself */
free(info);
@@ -695,6 +715,9 @@ H5VL_pass_through_wrap_object(void *obj, H5I_type_t obj_type, void *_wrap_ctx)
*
* Purpose: Release a "wrapper context" for an object
*
+ * Note: Take care to preserve the current HDF5 error stack
+ * when calling HDF5 API calls.
+ *
* Return: Success: 0
* Failure: -1
*
@@ -704,16 +727,21 @@ static herr_t
H5VL_pass_through_free_wrap_ctx(void *_wrap_ctx)
{
H5VL_pass_through_wrap_ctx_t *wrap_ctx = (H5VL_pass_through_wrap_ctx_t *)_wrap_ctx;
+ hid_t err_id;
#ifdef ENABLE_PASSTHRU_LOGGING
printf("------- PASS THROUGH VOL WRAP CTX Free\n");
#endif
+ err_id = H5Eget_current_stack();
+
/* Release underlying VOL ID and wrap context */
if(wrap_ctx->under_wrap_ctx)
H5VLfree_wrap_ctx(wrap_ctx->under_wrap_ctx, wrap_ctx->under_vol_id);
H5Idec_ref(wrap_ctx->under_vol_id);
+ H5Eset_current_stack(err_id);
+
/* Free pass through wrap context object itself */
free(wrap_ctx);
diff --git a/src/H5VLpkg.h b/src/H5VLpkg.h
index bbdb0cc..69e51c2 100644
--- a/src/H5VLpkg.h
+++ b/src/H5VLpkg.h
@@ -28,21 +28,36 @@
/* Other private headers needed by this file */
+
/**************************/
/* Package Private Macros */
/**************************/
+
/****************************/
/* Package Private Typedefs */
/****************************/
+
/*****************************/
/* Package Private Variables */
/*****************************/
+
/******************************/
/* 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_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(const char *name);
+H5_DLL hid_t H5VL__get_connector_id(const char *name, hbool_t is_api);
+H5_DLL herr_t H5VL__connector_str_to_info(const char *str, hid_t connector_id,
+ void **info);
+H5_DLL ssize_t H5VL__get_connector_name(hid_t id, char *name/*out*/, size_t size);
#endif /* _H5VLpkg_H */
diff --git a/src/H5VLprivate.h b/src/H5VLprivate.h
index ac77ee0..dc4f9c5 100644
--- a/src/H5VLprivate.h
+++ b/src/H5VLprivate.h
@@ -18,10 +18,12 @@
/* Private headers needed by this file */
+
/**************************/
/* Library Private Macros */
/**************************/
+
/****************************/
/* Library Private Typedefs */
/****************************/
@@ -62,14 +64,14 @@ typedef enum H5VL_get_connector_kind_t {
/******************************/
/* Utility functions */
-H5_DLL herr_t H5VL_init(void);
+H5_DLL herr_t H5VL_init_phase1(void);
+H5_DLL herr_t H5VL_init_phase2(void);
H5_DLL herr_t H5VL_cmp_connector_cls(int *cmp_value, const H5VL_class_t *cls1, const H5VL_class_t *cls2);
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);
-H5_DLL ssize_t H5VL_get_connector_name(hid_t id, char *name/*out*/, size_t size);
/* 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
@@ -120,7 +122,7 @@ H5_DLL int H5VL_copy_connector_info(const H5VL_class_t *connector, void **dst_in
const void *src_info);
H5_DLL herr_t H5VL_cmp_connector_info(const H5VL_class_t *connector, int *cmp_value,
const void *info1, const void *info2);
-H5_DLL herr_t H5VL_free_connector_info(const H5VL_class_t *connector, void *info);
+H5_DLL herr_t H5VL_free_connector_info(hid_t connector_id, void *info);
/* Attribute functions */
H5_DLL void *H5VL_attr_create(const H5VL_object_t *vol_obj, const H5VL_loc_params_t *loc_params, const char *attr_name, hid_t acpl_id, hid_t aapl_id, hid_t dxpl_id, void **req);